Merge "Improve doc for EditorInfo#initialSel{Start,End}"
diff --git a/Android.mk b/Android.mk
index 57091cc..5c48dfe 100644
--- a/Android.mk
+++ b/Android.mk
@@ -162,6 +162,7 @@
 	core/java/android/os/ICancellationSignal.aidl \
 	core/java/android/os/IHardwareService.aidl \
 	core/java/android/os/IMessenger.aidl \
+	core/java/android/os/INetworkActivityListener.aidl \
 	core/java/android/os/INetworkManagementService.aidl \
 	core/java/android/os/IPermissionController.aidl \
 	core/java/android/os/IPowerManager.aidl \
@@ -261,23 +262,23 @@
 	media/java/android/media/IAudioService.aidl \
 	media/java/android/media/IAudioFocusDispatcher.aidl \
 	media/java/android/media/IAudioRoutesObserver.aidl \
-	media/java/android/media/IMediaController.aidl \
-	media/java/android/media/IMediaControllerCallback.aidl \
 	media/java/android/media/IMediaHTTPConnection.aidl \
 	media/java/android/media/IMediaHTTPService.aidl \
 	media/java/android/media/IMediaRouterClient.aidl \
 	media/java/android/media/IMediaRouterService.aidl \
 	media/java/android/media/IMediaScannerListener.aidl \
 	media/java/android/media/IMediaScannerService.aidl \
-	media/java/android/media/IMediaSession.aidl \
-	media/java/android/media/IMediaSessionCallback.aidl \
-	media/java/android/media/IMediaSessionManager.aidl \
 	media/java/android/media/IRemoteControlClient.aidl \
 	media/java/android/media/IRemoteControlDisplay.aidl \
 	media/java/android/media/IRemoteDisplayCallback.aidl \
 	media/java/android/media/IRemoteDisplayProvider.aidl \
 	media/java/android/media/IRemoteVolumeObserver.aidl \
 	media/java/android/media/IRingtonePlayer.aidl \
+	media/java/android/media/session/IMediaController.aidl \
+	media/java/android/media/session/IMediaControllerCallback.aidl \
+	media/java/android/media/session/IMediaSession.aidl \
+	media/java/android/media/session/IMediaSessionCallback.aidl \
+	media/java/android/media/session/IMediaSessionManager.aidl \
 	telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl \
 	telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \
 	telephony/java/com/android/internal/telephony/ITelephony.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 1e49fcb..448b03d 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -186,6 +186,7 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/framework-res_intermediates)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/print/IPrintClient.*)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/services_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/media/java/android/media/IMedia*)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/api/current.txt b/api/current.txt
index 983da5d..754a84f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -345,7 +345,7 @@
     field public static final int canRetrieveWindowContent = 16843653; // 0x1010385
     field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
     field public static final deprecated int capitalize = 16843113; // 0x1010169
-    field public static final int castsShadow = 16843778; // 0x1010402
+    field public static final int castsShadow = 16843774; // 0x10103fe
     field public static final int category = 16843752; // 0x10103e8
     field public static final int centerBright = 16842956; // 0x10100cc
     field public static final int centerColor = 16843275; // 0x101020b
@@ -379,8 +379,6 @@
     field public static final int colorActivatedHighlight = 16843664; // 0x1010390
     field public static final int colorBackground = 16842801; // 0x1010031
     field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
-    field public static final int colorFilterColor = 16843767; // 0x10103f7
-    field public static final int colorFilterMode = 16843768; // 0x10103f8
     field public static final int colorFocusedHighlight = 16843663; // 0x101038f
     field public static final int colorForeground = 16842800; // 0x1010030
     field public static final int colorForegroundInverse = 16843270; // 0x1010206
@@ -401,10 +399,10 @@
     field public static final int content = 16843355; // 0x101025b
     field public static final int contentAuthority = 16843408; // 0x1010290
     field public static final int contentDescription = 16843379; // 0x1010273
-    field public static final int controlX1 = 16843770; // 0x10103fa
-    field public static final int controlX2 = 16843772; // 0x10103fc
-    field public static final int controlY1 = 16843771; // 0x10103fb
-    field public static final int controlY2 = 16843773; // 0x10103fd
+    field public static final int controlX1 = 16843768; // 0x10103f8
+    field public static final int controlX2 = 16843770; // 0x10103fa
+    field public static final int controlY1 = 16843769; // 0x10103f9
+    field public static final int controlY2 = 16843771; // 0x10103fb
     field public static final int cropToPadding = 16843043; // 0x1010123
     field public static final int cursorVisible = 16843090; // 0x1010152
     field public static final int customNavigationLayout = 16843474; // 0x10102d2
@@ -544,7 +542,6 @@
     field public static final int fromAlpha = 16843210; // 0x10101ca
     field public static final int fromDegrees = 16843187; // 0x10101b3
     field public static final int fromScene = 16843741; // 0x10103dd
-    field public static final int fromSceneName = 16843774; // 0x10103fe
     field public static final int fromXDelta = 16843206; // 0x10101c6
     field public static final int fromXScale = 16843202; // 0x10101c2
     field public static final int fromYDelta = 16843208; // 0x10101c8
@@ -639,7 +636,6 @@
     field public static final int isScrollContainer = 16843342; // 0x101024e
     field public static final int isSticky = 16843335; // 0x1010247
     field public static final int isolatedProcess = 16843689; // 0x10103a9
-    field public static final int isolatedZVolume = 16843769; // 0x10103f9
     field public static final int itemBackground = 16843056; // 0x1010130
     field public static final int itemIconDisabledAlpha = 16843057; // 0x1010131
     field public static final int itemPadding = 16843565; // 0x101032d
@@ -892,6 +888,7 @@
     field public static final int required = 16843406; // 0x101028e
     field public static final int requiredAccountType = 16843734; // 0x10103d6
     field public static final int requiredForAllUsers = 16843728; // 0x10103d0
+    field public static final int requiredForProfile = 16843775; // 0x10103ff
     field public static final int requiresFadingEdge = 16843685; // 0x10103a5
     field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
     field public static final int resizeMode = 16843619; // 0x1010363
@@ -962,7 +959,7 @@
     field public static final int shadowRadius = 16843108; // 0x1010164
     field public static final int shape = 16843162; // 0x101019a
     field public static final int shareInterpolator = 16843195; // 0x10101bb
-    field public static final int sharedElementName = 16843776; // 0x1010400
+    field public static final int sharedElementName = 16843772; // 0x10103fc
     field public static final int sharedUserId = 16842763; // 0x101000b
     field public static final int sharedUserLabel = 16843361; // 0x1010261
     field public static final int shouldDisableView = 16843246; // 0x10101ee
@@ -1139,13 +1136,13 @@
     field public static final int tileMode = 16843265; // 0x1010201
     field public static final int timeZone = 16843724; // 0x10103cc
     field public static final int tint = 16843041; // 0x1010121
+    field public static final int tintMode = 16843767; // 0x10103f7
     field public static final int title = 16843233; // 0x10101e1
     field public static final int titleCondensed = 16843234; // 0x10101e2
     field public static final int titleTextStyle = 16843512; // 0x10102f8
     field public static final int toAlpha = 16843211; // 0x10101cb
     field public static final int toDegrees = 16843188; // 0x10101b4
     field public static final int toScene = 16843742; // 0x10103de
-    field public static final int toSceneName = 16843775; // 0x10103ff
     field public static final int toXDelta = 16843207; // 0x10101c7
     field public static final int toXScale = 16843203; // 0x10101c3
     field public static final int toYDelta = 16843209; // 0x10101c9
@@ -1161,7 +1158,7 @@
     field public static final int transformPivotX = 16843552; // 0x1010320
     field public static final int transformPivotY = 16843553; // 0x1010321
     field public static final int transition = 16843743; // 0x10103df
-    field public static final int transitionGroup = 16843777; // 0x1010401
+    field public static final int transitionGroup = 16843773; // 0x10103fd
     field public static final int transitionOrdering = 16843744; // 0x10103e0
     field public static final int translationX = 16843554; // 0x1010322
     field public static final int translationY = 16843555; // 0x1010323
@@ -3041,7 +3038,6 @@
     method public int getTaskId();
     method public final java.lang.CharSequence getTitle();
     method public final int getTitleColor();
-    method public android.os.Bundle getTransitionArgs();
     method public final int getVolumeControlStream();
     method public android.view.Window getWindow();
     method public android.view.WindowManager getWindowManager();
@@ -3063,6 +3059,8 @@
     method public void onAttachFragment(android.app.Fragment);
     method public void onAttachedToWindow();
     method public void onBackPressed();
+    method public void onCaptureSharedElementEnd();
+    method public void onCaptureSharedElementStart(android.transition.Transition);
     method protected void onChildTitleChanged(android.app.Activity, java.lang.CharSequence);
     method public void onConfigurationChanged(android.content.res.Configuration);
     method public void onContentChanged();
@@ -3121,6 +3119,7 @@
     method public void onUserInteraction();
     method protected void onUserLeaveHint();
     method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
+    method public void onWindowDismissed();
     method public void onWindowFocusChanged(boolean);
     method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
     method public void openContextMenu(android.view.View);
@@ -3137,7 +3136,6 @@
     method public void setContentView(android.view.View);
     method public void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
     method public final void setDefaultKeyMode(int);
-    method public void setEarlyBackgroundTransition(boolean);
     method public final void setFeatureDrawable(int, android.graphics.drawable.Drawable);
     method public final void setFeatureDrawableAlpha(int, int);
     method public final void setFeatureDrawableResource(int, int);
@@ -3178,7 +3176,6 @@
     method public boolean startNextMatchingActivity(android.content.Intent);
     method public boolean startNextMatchingActivity(android.content.Intent, android.os.Bundle);
     method public void startSearch(java.lang.String, boolean, android.os.Bundle, boolean);
-    method protected void startSharedElementTransition(android.os.Bundle);
     method public deprecated void stopManagingCursor(android.database.Cursor);
     method public void takeKeyEvents(boolean);
     method public void triggerSearch(java.lang.String, android.os.Bundle);
@@ -3349,23 +3346,13 @@
   public class ActivityOptions {
     method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
     method public static android.app.ActivityOptions makeScaleUpAnimation(android.view.View, int, int, int, int);
-    method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.os.Bundle);
+    method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.view.View, java.lang.String);
+    method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.util.Pair<android.view.View, java.lang.String>...);
     method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
     method public android.os.Bundle toBundle();
     method public void update(android.app.ActivityOptions);
   }
 
-  public class ActivityView extends android.view.ViewGroup {
-    ctor public ActivityView(android.content.Context);
-    ctor public ActivityView(android.content.Context, android.util.AttributeSet);
-    ctor public ActivityView(android.content.Context, android.util.AttributeSet, int);
-    method public boolean isAttachedToDisplay();
-    method protected void onLayout(boolean, int, int, int, int);
-    method public void startActivity(android.content.Intent);
-    method public void startActivity(android.content.IntentSender);
-    method public void startActivity(android.app.PendingIntent);
-  }
-
   public class AlarmManager {
     method public void cancel(android.app.PendingIntent);
     method public void set(int, long, android.app.PendingIntent);
@@ -3654,6 +3641,7 @@
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public boolean onTrackballEvent(android.view.MotionEvent);
     method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
+    method public void onWindowDismissed();
     method public void onWindowFocusChanged(boolean);
     method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
     method public void openContextMenu(android.view.View);
@@ -4304,7 +4292,9 @@
   public static class Notification.Builder {
     ctor public Notification.Builder(android.content.Context);
     method public android.app.Notification.Builder addAction(int, java.lang.CharSequence, android.app.PendingIntent);
+    method public android.app.Notification.Builder addExtras(android.os.Bundle);
     method public android.app.Notification build();
+    method public android.os.Bundle getExtras();
     method public deprecated android.app.Notification getNotification();
     method public android.app.Notification.Builder setAutoCancel(boolean);
     method public android.app.Notification.Builder setContent(android.widget.RemoteViews);
@@ -4750,6 +4740,8 @@
   }
 
   public class DevicePolicyManager {
+    method public void addPersistentPreferredActivity(android.content.ComponentName, android.content.IntentFilter, android.content.ComponentName);
+    method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
     method public java.util.List<android.content.ComponentName> getActiveAdmins();
     method public boolean getCameraDisabled(android.content.ComponentName);
     method public int getCurrentFailedPasswordAttempts();
@@ -9933,6 +9925,7 @@
     method public void cubicTo(float, float, float, float, float, float);
     method public android.graphics.Path.FillType getFillType();
     method public void incReserve(int);
+    method public boolean isConvex();
     method public boolean isEmpty();
     method public boolean isInverseFillType();
     method public boolean isRect(android.graphics.RectF);
@@ -10396,6 +10389,7 @@
     method public final android.graphics.Paint getPaint();
     method public android.graphics.Shader.TileMode getTileModeX();
     method public android.graphics.Shader.TileMode getTileModeY();
+    method public android.content.res.ColorStateList getTint();
     method public boolean hasAntiAlias();
     method public boolean hasMipMap();
     method public final boolean isAutoMirrored();
@@ -10410,6 +10404,7 @@
     method public void setTileModeX(android.graphics.Shader.TileMode);
     method public void setTileModeXY(android.graphics.Shader.TileMode, android.graphics.Shader.TileMode);
     method public final void setTileModeY(android.graphics.Shader.TileMode);
+    method public void setTint(android.content.res.ColorStateList);
   }
 
   public class ClipDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
@@ -10452,6 +10447,7 @@
     method public final android.graphics.Rect getBounds();
     method public android.graphics.drawable.Drawable.Callback getCallback();
     method public int getChangingConfigurations();
+    method public android.graphics.ColorFilter getColorFilter();
     method public android.graphics.drawable.Drawable.ConstantState getConstantState();
     method public android.graphics.drawable.Drawable getCurrent();
     method public int getIntrinsicHeight();
@@ -10551,7 +10547,6 @@
     method public float getGradientRadius();
     method public int getOpacity();
     method public android.graphics.drawable.GradientDrawable.Orientation getOrientation();
-    method public boolean onStateChange(int[]);
     method public void setAlpha(int);
     method public void setColor(int);
     method public void setColor(android.content.res.ColorStateList);
@@ -10641,11 +10636,13 @@
     method public void draw(android.graphics.Canvas);
     method public int getOpacity();
     method public android.graphics.Paint getPaint();
+    method public android.content.res.ColorStateList getTint();
     method public void setAlpha(int);
     method public void setColorFilter(android.graphics.ColorFilter);
     method public void setTargetDensity(android.graphics.Canvas);
     method public void setTargetDensity(android.util.DisplayMetrics);
     method public void setTargetDensity(int);
+    method public void setTint(android.content.res.ColorStateList);
   }
 
   public class PaintDrawable extends android.graphics.drawable.ShapeDrawable {
@@ -10714,6 +10711,7 @@
     method public android.graphics.Paint getPaint();
     method public android.graphics.drawable.ShapeDrawable.ShaderFactory getShaderFactory();
     method public android.graphics.drawable.shapes.Shape getShape();
+    method public android.content.res.ColorStateList getTint();
     method protected boolean inflateTag(java.lang.String, android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet);
     method protected void onDraw(android.graphics.drawable.shapes.Shape, android.graphics.Canvas, android.graphics.Paint);
     method public void setAlpha(int);
@@ -10724,6 +10722,7 @@
     method public void setPadding(android.graphics.Rect);
     method public void setShaderFactory(android.graphics.drawable.ShapeDrawable.ShaderFactory);
     method public void setShape(android.graphics.drawable.shapes.Shape);
+    method public void setTint(android.content.res.ColorStateList);
   }
 
   public static abstract class ShapeDrawable.ShaderFactory {
@@ -11497,12 +11496,34 @@
     field public static final int REQUEST_AVAILABLE_CAPABILITIES_ZSL = 4; // 0x4
     field public static final int SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT = 1; // 0x1
     field public static final int SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT = 0; // 0x0
+    field public static final int SENSOR_REFERENCE_ILLUMINANT_CLOUDY_WEATHER = 10; // 0xa
+    field public static final int SENSOR_REFERENCE_ILLUMINANT_COOL_WHITE_FLUORESCENT = 14; // 0xe
+    field public static final int SENSOR_REFERENCE_ILLUMINANT_D50 = 23; // 0x17
+    field public static final int SENSOR_REFERENCE_ILLUMINANT_D55 = 20; // 0x14
+    field public static final int SENSOR_REFERENCE_ILLUMINANT_D65 = 21; // 0x15
+    field public static final int SENSOR_REFERENCE_ILLUMINANT_D75 = 22; // 0x16
+    field public static final int SENSOR_REFERENCE_ILLUMINANT_DAYLIGHT = 1; // 0x1
+    field public static final int SENSOR_REFERENCE_ILLUMINANT_DAYLIGHT_FLUORESCENT = 12; // 0xc
+    field public static final int SENSOR_REFERENCE_ILLUMINANT_DAY_WHITE_FLUORESCENT = 13; // 0xd
+    field public static final int SENSOR_REFERENCE_ILLUMINANT_FINE_WEATHER = 9; // 0x9
+    field public static final int SENSOR_REFERENCE_ILLUMINANT_FLASH = 4; // 0x4
+    field public static final int SENSOR_REFERENCE_ILLUMINANT_FLUORESCENT = 2; // 0x2
+    field public static final int SENSOR_REFERENCE_ILLUMINANT_ISO_STUDIO_TUNGSTEN = 24; // 0x18
+    field public static final int SENSOR_REFERENCE_ILLUMINANT_SHADE = 11; // 0xb
+    field public static final int SENSOR_REFERENCE_ILLUMINANT_STANDARD_A = 17; // 0x11
+    field public static final int SENSOR_REFERENCE_ILLUMINANT_STANDARD_B = 18; // 0x12
+    field public static final int SENSOR_REFERENCE_ILLUMINANT_STANDARD_C = 19; // 0x13
+    field public static final int SENSOR_REFERENCE_ILLUMINANT_TUNGSTEN = 3; // 0x3
+    field public static final int SENSOR_REFERENCE_ILLUMINANT_WHITE_FLUORESCENT = 15; // 0xf
     field public static final int SENSOR_TEST_PATTERN_MODE_COLOR_BARS = 2; // 0x2
     field public static final int SENSOR_TEST_PATTERN_MODE_COLOR_BARS_FADE_TO_GRAY = 3; // 0x3
     field public static final int SENSOR_TEST_PATTERN_MODE_CUSTOM1 = 256; // 0x100
     field public static final int SENSOR_TEST_PATTERN_MODE_OFF = 0; // 0x0
     field public static final int SENSOR_TEST_PATTERN_MODE_PN9 = 4; // 0x4
     field public static final int SENSOR_TEST_PATTERN_MODE_SOLID_COLOR = 1; // 0x1
+    field public static final int SHADING_MODE_FAST = 1; // 0x1
+    field public static final int SHADING_MODE_HIGH_QUALITY = 2; // 0x2
+    field public static final int SHADING_MODE_OFF = 0; // 0x0
     field public static final int STATISTICS_FACE_DETECT_MODE_FULL = 2; // 0x2
     field public static final int STATISTICS_FACE_DETECT_MODE_OFF = 0; // 0x0
     field public static final int STATISTICS_FACE_DETECT_MODE_SIMPLE = 1; // 0x1
@@ -11584,6 +11605,7 @@
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_SENSITIVITY;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TEST_PATTERN_DATA;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TEST_PATTERN_MODE;
+    field public static final android.hardware.camera2.CameraMetadata.Key SHADING_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_FACE_DETECT_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_LENS_SHADING_MAP_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_CURVE_BLUE;
@@ -11647,13 +11669,16 @@
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_EXPOSURE_TIME;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_FORWARD_MATRIX;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_FRAME_DURATION;
+    field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_GREEN_SPLIT;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_NEUTRAL_COLOR_POINT;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_PROFILE_HUE_SAT_MAP;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_PROFILE_TONE_CURVE;
+    field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_REFERENCE_ILLUMINANT;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_SENSITIVITY;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TEMPERATURE;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TEST_PATTERN_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TIMESTAMP;
+    field public static final android.hardware.camera2.CameraMetadata.Key SHADING_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_FACES;
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_FACE_DETECT_MODE;
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_LENS_SHADING_MAP;
@@ -11810,6 +11835,20 @@
     field public static final android.os.Parcelable.Creator CREATOR;
   }
 
+  public class UsbConfiguration implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getAttributes();
+    method public int getId();
+    method public android.hardware.usb.UsbInterface getInterface(int);
+    method public int getInterfaceCount();
+    method public int getMaxPower();
+    method public java.lang.String getName();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ATTR_REMOTE_WAKEUP_MASK = 32; // 0x20
+    field public static final int ATTR_SELF_POWERED_MASK = 64; // 0x40
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
   public final class UsbConstants {
     ctor public UsbConstants();
     field public static final int USB_CLASS_APP_SPEC = 254; // 0xfe
@@ -11849,6 +11888,8 @@
 
   public class UsbDevice implements android.os.Parcelable {
     method public int describeContents();
+    method public android.hardware.usb.UsbConfiguration getConfiguration(int);
+    method public int getConfigurationCount();
     method public int getDeviceClass();
     method public int getDeviceId();
     method public static int getDeviceId(java.lang.String);
@@ -11879,6 +11920,8 @@
     method public java.lang.String getSerial();
     method public boolean releaseInterface(android.hardware.usb.UsbInterface);
     method public android.hardware.usb.UsbRequest requestWait();
+    method public boolean setConfiguration(android.hardware.usb.UsbConfiguration);
+    method public boolean setInterface(android.hardware.usb.UsbInterface);
   }
 
   public class UsbEndpoint implements android.os.Parcelable {
@@ -11896,12 +11939,14 @@
 
   public class UsbInterface implements android.os.Parcelable {
     method public int describeContents();
+    method public int getAlternateSetting();
     method public android.hardware.usb.UsbEndpoint getEndpoint(int);
     method public int getEndpointCount();
     method public int getId();
     method public int getInterfaceClass();
     method public int getInterfaceProtocol();
     method public int getInterfaceSubclass();
+    method public java.lang.String getName();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
   }
@@ -12457,7 +12502,7 @@
     ctor public SettingInjectorService(java.lang.String);
     method public final android.os.IBinder onBind(android.content.Intent);
     method protected abstract boolean onGetEnabled();
-    method protected abstract java.lang.String onGetSummary();
+    method protected deprecated java.lang.String onGetSummary();
     method public final void onStart(android.content.Intent, int);
     method public final int onStartCommand(android.content.Intent, int, int);
     field public static final java.lang.String ACTION_INJECTED_SETTING_CHANGED = "android.location.InjectedSettingChanged";
@@ -13159,23 +13204,6 @@
     method public static final android.media.MediaCodecInfo getCodecInfoAt(int);
   }
 
-  public final class MediaController {
-    ctor public MediaController(android.media.MediaSessionToken);
-    method public void addCallback(android.media.MediaController.Callback);
-    method public void addCallback(android.media.MediaController.Callback, android.os.Handler);
-    method public void removeCallback(android.media.MediaController.Callback);
-    method public void sendCommand(java.lang.String, android.os.Bundle);
-    method public void sendMediaButton(int);
-  }
-
-  public static abstract class MediaController.Callback {
-    ctor public MediaController.Callback();
-    method public void onEvent(java.lang.String, android.os.Bundle);
-    method public void onMetadataUpdate(android.os.Bundle);
-    method public void onPlaybackStateChange(int);
-    method public void onRouteChanged(android.os.Bundle);
-  }
-
   public final class MediaCrypto {
     ctor public MediaCrypto(java.util.UUID, byte[]) throws android.media.MediaCryptoException;
     method public static final boolean isCryptoSchemeSupported(java.util.UUID);
@@ -13742,33 +13770,6 @@
     method public abstract void onScanCompleted(java.lang.String, android.net.Uri);
   }
 
-  public final class MediaSession {
-    method public void addCallback(android.media.MediaSession.Callback);
-    method public void addCallback(android.media.MediaSession.Callback, android.os.Handler);
-    method public android.media.MediaSessionToken getSessionToken();
-    method public void release();
-    method public void removeCallback(android.media.MediaSession.Callback);
-    method public void setPlaybackState(int);
-  }
-
-  public static abstract class MediaSession.Callback {
-    ctor public MediaSession.Callback();
-    method public void onCommand(java.lang.String, android.os.Bundle);
-    method public void onMediaButton(android.content.Intent);
-    method public void onRequestRouteChange(android.os.Bundle);
-  }
-
-  public final class MediaSessionManager {
-    method public android.media.MediaSession createSession(java.lang.String);
-    method public java.util.List<android.media.MediaController> getActiveSessions();
-  }
-
-  public class MediaSessionToken implements android.os.Parcelable {
-    method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator CREATOR;
-  }
-
   public class MediaSyncEvent {
     method public static android.media.MediaSyncEvent createEvent(int) throws java.lang.IllegalArgumentException;
     method public int getAudioSessionId();
@@ -14438,6 +14439,54 @@
 
 }
 
+package android.media.session {
+
+  public final class MediaController {
+    ctor public MediaController(android.media.session.MediaSessionToken);
+    method public void addCallback(android.media.session.MediaController.Callback);
+    method public void addCallback(android.media.session.MediaController.Callback, android.os.Handler);
+    method public void removeCallback(android.media.session.MediaController.Callback);
+    method public void sendCommand(java.lang.String, android.os.Bundle);
+    method public void sendMediaButton(int);
+  }
+
+  public static abstract class MediaController.Callback {
+    ctor public MediaController.Callback();
+    method public void onEvent(java.lang.String, android.os.Bundle);
+    method public void onMetadataUpdate(android.os.Bundle);
+    method public void onPlaybackStateChange(int);
+    method public void onRouteChanged(android.os.Bundle);
+  }
+
+  public final class MediaSession {
+    method public void addCallback(android.media.session.MediaSession.Callback);
+    method public void addCallback(android.media.session.MediaSession.Callback, android.os.Handler);
+    method public android.media.session.MediaSessionToken getSessionToken();
+    method public void release();
+    method public void removeCallback(android.media.session.MediaSession.Callback);
+    method public void setPlaybackState(int);
+  }
+
+  public static abstract class MediaSession.Callback {
+    ctor public MediaSession.Callback();
+    method public void onCommand(java.lang.String, android.os.Bundle);
+    method public void onMediaButton(android.content.Intent);
+    method public void onRequestRouteChange(android.os.Bundle);
+  }
+
+  public final class MediaSessionManager {
+    method public android.media.session.MediaSession createSession(java.lang.String);
+    method public java.util.List<android.media.session.MediaController> getActiveSessions();
+  }
+
+  public class MediaSessionToken implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+}
+
 package android.mtp {
 
   public final class MtpConstants {
@@ -14574,11 +14623,14 @@
     method public android.net.NetworkInfo getNetworkInfo(int);
     method public int getNetworkPreference();
     method public boolean isActiveNetworkMetered();
+    method public boolean isNetworkActive();
     method public static boolean isNetworkTypeValid(int);
+    method public void registerNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
     method public boolean requestRouteToHost(int, int);
     method public void setNetworkPreference(int);
     method public int startUsingNetworkFeature(int, java.lang.String);
     method public int stopUsingNetworkFeature(int, java.lang.String);
+    method public void unregisterNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
     field public static final deprecated java.lang.String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
     field public static final java.lang.String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
     field public static final deprecated int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1
@@ -14601,6 +14653,10 @@
     field public static final int TYPE_WIMAX = 6; // 0x6
   }
 
+  public static abstract interface ConnectivityManager.OnNetworkActiveListener {
+    method public abstract void onNetworkActive();
+  }
+
   public class Credentials {
     ctor public Credentials(int, int, int);
     method public int getGid();
@@ -15497,6 +15553,7 @@
     method public int describeContents();
     method public java.lang.String getBSSID();
     method public static android.net.NetworkInfo.DetailedState getDetailedStateOf(android.net.wifi.SupplicantState);
+    method public int getFrequency();
     method public boolean getHiddenSSID();
     method public int getIpAddress();
     method public int getLinkSpeed();
@@ -15506,6 +15563,7 @@
     method public java.lang.String getSSID();
     method public android.net.wifi.SupplicantState getSupplicantState();
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final java.lang.String FREQUENCY_UNITS = "MHz";
     field public static final java.lang.String LINK_SPEED_UNITS = "Mbps";
   }
 
@@ -15818,6 +15876,7 @@
     method public static android.nfc.NdefRecord createApplicationRecord(java.lang.String);
     method public static android.nfc.NdefRecord createExternal(java.lang.String, java.lang.String, byte[]);
     method public static android.nfc.NdefRecord createMime(java.lang.String, byte[]);
+    method public static android.nfc.NdefRecord createTextRecord(java.lang.String, java.lang.String);
     method public static android.nfc.NdefRecord createUri(android.net.Uri);
     method public static android.nfc.NdefRecord createUri(java.lang.String);
     method public int describeContents();
@@ -15854,6 +15913,7 @@
     method public deprecated void enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage);
     method public void enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle);
     method public static android.nfc.NfcAdapter getDefaultAdapter(android.content.Context);
+    method public boolean invokeBeam(android.app.Activity);
     method public boolean isEnabled();
     method public boolean isNdefPushEnabled();
     method public void setBeamPushUris(android.net.Uri[], android.app.Activity);
@@ -16284,8 +16344,10 @@
   }
 
   public abstract class EGLObjectHandle {
-    ctor protected EGLObjectHandle(int);
-    method public int getHandle();
+    ctor protected deprecated EGLObjectHandle(int);
+    ctor protected EGLObjectHandle(long);
+    method public deprecated int getHandle();
+    method public long getNativeHandle();
   }
 
   public class EGLSurface extends android.opengl.EGLObjectHandle {
@@ -23683,6 +23745,7 @@
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
     method public boolean onSearchRequested();
     method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
+    method public void onWindowDismissed();
     method public void onWindowFocusChanged(boolean);
     method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
     method public void setContentView(int);
@@ -26803,15 +26866,11 @@
     ctor public TransitionManager();
     method public static void beginDelayedTransition(android.view.ViewGroup);
     method public static void beginDelayedTransition(android.view.ViewGroup, android.transition.Transition);
-    method public android.transition.Transition getNamedTransition(java.lang.String, android.transition.Scene);
-    method public android.transition.Transition getNamedTransition(android.transition.Scene, java.lang.String);
-    method public java.lang.String[] getTargetSceneNames(android.transition.Scene);
     method public static void go(android.transition.Scene);
     method public static void go(android.transition.Scene, android.transition.Transition);
+    method public void setExitTransition(android.transition.Scene, android.transition.Transition);
     method public void setTransition(android.transition.Scene, android.transition.Transition);
     method public void setTransition(android.transition.Scene, android.transition.Scene, android.transition.Transition);
-    method public void setTransition(android.transition.Scene, java.lang.String, android.transition.Transition);
-    method public void setTransition(java.lang.String, android.transition.Scene, android.transition.Transition);
     method public void transitionTo(android.transition.Scene);
   }
 
@@ -27155,6 +27214,7 @@
     method public final V put(K, V);
     method public final synchronized int putCount();
     method public final V remove(K);
+    method public void resize(int);
     method public final synchronized int size();
     method protected int sizeOf(K, V);
     method public final synchronized java.util.Map<K, V> snapshot();
@@ -28062,6 +28122,7 @@
     field public static final int KEYCODE_SHIFT_LEFT = 59; // 0x3b
     field public static final int KEYCODE_SHIFT_RIGHT = 60; // 0x3c
     field public static final int KEYCODE_SLASH = 76; // 0x4c
+    field public static final int KEYCODE_SLEEP = 223; // 0xdf
     field public static final int KEYCODE_SOFT_LEFT = 1; // 0x1
     field public static final int KEYCODE_SOFT_RIGHT = 2; // 0x2
     field public static final int KEYCODE_SPACE = 62; // 0x3e
@@ -28083,6 +28144,7 @@
     field public static final int KEYCODE_VOLUME_MUTE = 164; // 0xa4
     field public static final int KEYCODE_VOLUME_UP = 24; // 0x18
     field public static final int KEYCODE_W = 51; // 0x33
+    field public static final int KEYCODE_WAKEUP = 224; // 0xe0
     field public static final int KEYCODE_WINDOW = 171; // 0xab
     field public static final int KEYCODE_X = 52; // 0x34
     field public static final int KEYCODE_Y = 53; // 0x35
@@ -29469,7 +29531,6 @@
     method public int getLayoutMode();
     method public android.animation.LayoutTransition getLayoutTransition();
     method public int getPersistentDrawingCache();
-    method public boolean hasIsolatedZVolume();
     method public int indexOfChild(android.view.View);
     method public final void invalidateChild(android.view.View, android.graphics.Rect);
     method public android.view.ViewParent invalidateChildInParent(int[], android.graphics.Rect);
@@ -29515,7 +29576,6 @@
     method public void setClipChildren(boolean);
     method public void setClipToPadding(boolean);
     method public void setDescendantFocusability(int);
-    method public void setIsolatedZVolume(boolean);
     method public void setLayoutAnimation(android.view.animation.LayoutAnimationController);
     method public void setLayoutAnimationListener(android.view.animation.Animation.AnimationListener);
     method public void setLayoutMode(int);
@@ -29781,6 +29841,7 @@
     method public abstract boolean isFloating();
     method public abstract boolean isShortcutKey(int, android.view.KeyEvent);
     method public final void makeActive();
+    method public void mapTransitionTargets(java.util.Map<java.lang.String, java.lang.String>);
     method protected abstract void onActive();
     method public abstract void onConfigurationChanged(android.content.res.Configuration);
     method public abstract void openPanel(int, android.view.KeyEvent);
@@ -29819,6 +29880,7 @@
     method public abstract void setTitle(java.lang.CharSequence);
     method public abstract deprecated void setTitleColor(int);
     method public void setTransitionManager(android.transition.TransitionManager);
+    method public void setTriggerEarlyEnterTransition(boolean);
     method public void setType(int);
     method public void setUiOptions(int);
     method public void setUiOptions(int, int);
@@ -29839,7 +29901,7 @@
     field public static final int FEATURE_ACTION_BAR = 8; // 0x8
     field public static final int FEATURE_ACTION_BAR_OVERLAY = 9; // 0x9
     field public static final int FEATURE_ACTION_MODE_OVERLAY = 10; // 0xa
-    field public static final int FEATURE_CONTENT_TRANSITIONS = 11; // 0xb
+    field public static final int FEATURE_CONTENT_TRANSITIONS = 12; // 0xc
     field public static final int FEATURE_CONTEXT_MENU = 6; // 0x6
     field public static final int FEATURE_CUSTOM_TITLE = 7; // 0x7
     field public static final int FEATURE_INDETERMINATE_PROGRESS = 5; // 0x5
@@ -29848,6 +29910,7 @@
     field public static final int FEATURE_OPTIONS_PANEL = 0; // 0x0
     field public static final int FEATURE_PROGRESS = 2; // 0x2
     field public static final int FEATURE_RIGHT_ICON = 4; // 0x4
+    field public static final int FEATURE_SWIPE_TO_DISMISS = 11; // 0xb
     field public static final int ID_ANDROID_CONTENT = 16908290; // 0x1020002
     field public static final int PROGRESS_END = 10000; // 0x2710
     field public static final int PROGRESS_INDETERMINATE_OFF = -4; // 0xfffffffc
@@ -29879,6 +29942,7 @@
     method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
     method public abstract boolean onSearchRequested();
     method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
+    method public abstract void onWindowDismissed();
     method public abstract void onWindowFocusChanged(boolean);
     method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
   }
@@ -30260,6 +30324,7 @@
     field public static final java.lang.String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT = "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
     field public static final java.lang.String ACTION_ARGUMENT_SELECTION_END_INT = "ACTION_ARGUMENT_SELECTION_END_INT";
     field public static final java.lang.String ACTION_ARGUMENT_SELECTION_START_INT = "ACTION_ARGUMENT_SELECTION_START_INT";
+    field public static final java.lang.String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE = "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE";
     field public static final int ACTION_CLEAR_ACCESSIBILITY_FOCUS = 128; // 0x80
     field public static final int ACTION_CLEAR_FOCUS = 2; // 0x2
     field public static final int ACTION_CLEAR_SELECTION = 8; // 0x8
@@ -30280,6 +30345,7 @@
     field public static final int ACTION_SCROLL_FORWARD = 4096; // 0x1000
     field public static final int ACTION_SELECT = 4; // 0x4
     field public static final int ACTION_SET_SELECTION = 131072; // 0x20000
+    field public static final int ACTION_SET_TEXT = 2097152; // 0x200000
     field public static final android.os.Parcelable.Creator CREATOR;
     field public static final int FOCUS_ACCESSIBILITY = 2; // 0x2
     field public static final int FOCUS_INPUT = 1; // 0x1
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 89e15d2..01e7615 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -232,6 +232,8 @@
                 "    [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]\n" +
                 "    [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]\n" +
                 "    [--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]\n" +
+                "    [--esa <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]]\n" +
+                "        (to embed a comma into a string escape it using \"\\,\")\n" +
                 "    [-n <COMPONENT>] [-f <FLAGS>]\n" +
                 "    [--grant-read-uri-permission] [--grant-write-uri-permission]\n" +
                 "    [--debug-log-resolution] [--exclude-stopped-packages]\n" +
@@ -419,6 +421,15 @@
                 }
                 intent.putExtra(key, list);
                 hasIntentInfo = true;
+            } else if (opt.equals("--esa")) {
+                String key = nextArgRequired();
+                String value = nextArgRequired();
+                // Split on commas unless they are preceeded by an escape.
+                // The escape character must be escaped for the string and
+                // again for the regex, thus four escape characters become one.
+                String[] strings = value.split("(?<!\\\\),");
+                intent.putExtra(key, strings);
+                hasIntentInfo = true;
             } else if (opt.equals("--ez")) {
                 String key = nextArgRequired();
                 String value = nextArgRequired();
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk
index d5ff84e..a4e2718 100644
--- a/cmds/bootanimation/Android.mk
+++ b/cmds/bootanimation/Android.mk
@@ -19,9 +19,6 @@
     libGLESv1_CM \
     libgui
 
-LOCAL_C_INCLUDES := \
-	$(call include-path-for, corecg graphics)
-
 LOCAL_MODULE:= bootanimation
 
 
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 125bea6..41afa39 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -36,15 +36,14 @@
 #include <ui/Rect.h>
 #include <ui/Region.h>
 #include <ui/DisplayInfo.h>
-#include <ui/FramebufferNativeWindow.h>
 
 #include <gui/ISurfaceComposer.h>
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
 
-#include <core/SkBitmap.h>
-#include <core/SkStream.h>
-#include <core/SkImageDecoder.h>
+#include <SkBitmap.h>
+#include <SkStream.h>
+#include <SkImageDecoder.h>
 
 #include <GLES/gl.h>
 #include <GLES/glext.h>
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 9ad2e76..d513a10 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -18,6 +18,7 @@
 
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
 import android.content.ComponentName;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ContainerEncryptionParams;
@@ -1089,13 +1090,16 @@
 
     public void runListUsers() {
         try {
+            IActivityManager am = ActivityManagerNative.getDefault();
+
             List<UserInfo> users = mUm.getUsers(false);
             if (users == null) {
                 System.err.println("Error: couldn't get users");
             } else {
                 System.out.println("Users:");
                 for (int i = 0; i < users.size(); i++) {
-                    System.out.println("\t" + users.get(i).toString());
+                    String running = am.isUserRunning(users.get(i).id, false) ? " running" : "";
+                    System.out.println("\t" + users.get(i).toString() + running);
                 }
             }
         } catch (RemoteException e) {
diff --git a/cmds/screencap/Android.mk b/cmds/screencap/Android.mk
index ca8008b..5c11b75 100644
--- a/cmds/screencap/Android.mk
+++ b/cmds/screencap/Android.mk
@@ -16,11 +16,4 @@
 
 LOCAL_MODULE_TAGS := optional
 
-LOCAL_C_INCLUDES += \
-	external/skia/include/core \
-	external/skia/include/effects \
-	external/skia/include/images \
-	external/skia/src/ports \
-	external/skia/include/utils
-
 include $(BUILD_EXECUTABLE)
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index a8716bf..af4a362 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.transition.Scene;
+import android.transition.Transition;
 import android.transition.TransitionManager;
 import android.util.ArrayMap;
 import android.util.SuperNotCalledException;
@@ -824,7 +825,7 @@
     }
 
     /**
-     * Return the LoaderManager for this fragment, creating it if needed.
+     * Return the LoaderManager for this activity, creating it if needed.
      */
     public LoaderManager getLoaderManager() {
         if (mLoaderManager != null) {
@@ -1030,7 +1031,7 @@
     /**
      * Called after {@link #onCreate} &mdash; or after {@link #onRestart} when  
      * the activity had been stopped, but is now again being displayed to the 
-	 * user.  It will be followed by {@link #onResume}.
+     * user.  It will be followed by {@link #onResume}.
      *
      * <p><em>Derived classes must call through to the super class's
      * implementation of this method.  If they do not, an exception will be
@@ -2461,6 +2462,13 @@
         }
         return false;
     }
+
+    /**
+     * Called when the main window associated with the activity has been dismissed.
+     */
+    public void onWindowDismissed() {
+        finish();
+    }
     
     /**
      * Called to process key events.  You can override this to intercept all 
@@ -3316,7 +3324,7 @@
             @Nullable Bundle appSearchData, boolean globalSearch) {
         ensureSearchManager();
         mSearchManager.startSearch(initialQuery, selectInitialQuery, getComponentName(),
-                        appSearchData, globalSearch); 
+                appSearchData, globalSearch); 
     }
 
     /**
@@ -3446,7 +3454,11 @@
      * @see #startActivity
      */
     public void startActivityForResult(Intent intent, int requestCode) {
-        startActivityForResult(intent, requestCode, null);
+        Bundle options = null;
+        if (mWindow.hasFeature(Window.FEATURE_CONTENT_TRANSITIONS)) {
+            options = ActivityOptions.makeSceneTransitionAnimation(null).toBundle();
+        }
+        startActivityForResult(intent, requestCode, options);
     }
 
     /**
@@ -3484,12 +3496,15 @@
      * @see #startActivity
      */
     public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
-        TransitionManager tm = getContentTransitionManager();
-        if (tm != null && options != null) {
+        if (options != null) {
             ActivityOptions activityOptions = new ActivityOptions(options);
             if (activityOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
-                getWindow().startExitTransition(activityOptions);
-                options = activityOptions.toBundle();
+                if (mActionBar != null) {
+                    ArrayMap<String, View> sharedElementMap = new ArrayMap<String, View>();
+                    mActionBar.captureSharedElements(sharedElementMap);
+                    activityOptions.addSharedElements(sharedElementMap);
+                }
+                options = mWindow.startExitTransition(activityOptions);
             }
         }
         if (mParent == null) {
@@ -3664,7 +3679,7 @@
      */
     @Override
     public void startActivity(Intent intent) {
-        startActivity(intent, null);
+        this.startActivity(intent, null);
     }
 
     /**
@@ -4720,7 +4735,8 @@
      */
     public final void setProgressBarIndeterminate(boolean indeterminate) {
         getWindow().setFeatureInt(Window.FEATURE_PROGRESS,
-                indeterminate ? Window.PROGRESS_INDETERMINATE_ON : Window.PROGRESS_INDETERMINATE_OFF);
+                indeterminate ? Window.PROGRESS_INDETERMINATE_ON
+                        : Window.PROGRESS_INDETERMINATE_OFF);
     }
     
     /**
@@ -5330,12 +5346,6 @@
                 mTransitionActivityOptions = activityOptions;
                 sceneTransitionListener = new Window.SceneTransitionListener() {
                     @Override
-                    public void enterSharedElement(Bundle transitionArgs) {
-                        startSharedElementTransition(transitionArgs);
-                        mTransitionActivityOptions = null;
-                    }
-
-                    @Override
                     public void nullPendingTransition() {
                         overridePendingTransition(0, 0);
                     }
@@ -5349,6 +5359,16 @@
                     public void convertToTranslucent() {
                         Activity.this.convertToTranslucent(null);
                     }
+
+                    @Override
+                    public void sharedElementStart(Transition transition) {
+                        Activity.this.onCaptureSharedElementStart(transition);
+                    }
+
+                    @Override
+                    public void sharedElementEnd() {
+                        Activity.this.onCaptureSharedElementEnd();
+                    }
                 };
 
             }
@@ -5542,53 +5562,23 @@
     }
 
     /**
-     * Gets the entering Activity transition args. Will be null if
-     * {@link android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)} was
-     * not used to pass a Bundle to startActivity. The Bundle passed to that method in the
-     * calling Activity is returned here.
-     * <p>After startSharedElementTransition is called, this method will return null.</p>
+     * Called when setting up Activity Scene transitions when the start state for shared
+     * elements has been captured. Override this method to modify the start position of shared
+     * elements for the entry Transition.
      *
-     * @return The Bundle passed into Bundle parameter of
-     *         {@link android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)}
-     *         in the calling Activity.
+     * @param transition The <code>Transition</code> being used to change
+     *                   bounds of shared elements in the source Activity to
+     *                   the bounds defined by the entering Scene.
      */
-    public Bundle getTransitionArgs() {
-        if (mTransitionActivityOptions == null) {
-            return null;
-        }
-        return mTransitionActivityOptions.getSceneTransitionArgs();
+    public void onCaptureSharedElementStart(Transition transition) {
     }
 
     /**
-     * Override to transfer a shared element from a calling Activity to this Activity.
-     * Shared elements will be made VISIBLE before this call. The Activity is responsible
-     * for transitioning the shared elements from their location to the eventual destination.
-     * The shared element will be laid out a the destination when this method is called.
-     *
-     * @param transitionArgs The same as returned from {@link #getTransitionArgs()}, this should
-     *                       contain information from the calling Activity to tell where the
-     *                       shared element should be placed.
+     * Called when setting up Activity Scene transitions when the final state for
+     * shared elements state has been captured. Override this method to modify the destination
+     * position of shared elements for the entry Transition.
      */
-    protected void startSharedElementTransition(Bundle transitionArgs) {
-    }
-
-    /**
-     * Controls how the background fade is triggered when there is an entering Activity transition.
-     * If fadeEarly is true, the Window background will fade in as soon as the shared elements are
-     * ready to switch. If fadeEarly is false, the background will fade only after the calling
-     * Activity's exit transition completes. By default, the Window will fade in when the calling
-     * Activity's exit transition completes.
-     *
-     * @param fadeEarly Set to true to fade out the exiting Activity as soon as the shared elements
-     *                  are transferred. Set to false to fade out the exiting Activity as soon as
-     *                  the shared element is transferred.
-     * @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)
-     */
-    public void setEarlyBackgroundTransition(boolean fadeEarly) {
-        if (mTransitionActivityOptions == null) {
-            return;
-        }
-        mWindow.setEarlyBackgroundTransition(fadeEarly);
+    public void onCaptureSharedElementEnd() {
     }
 
     /**
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index b40008e..f4358e9 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1713,6 +1713,15 @@
             return true;
         }
 
+        case START_USER_IN_BACKGROUND_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            int userid = data.readInt();
+            boolean result = startUserInBackground(userid);
+            reply.writeNoException();
+            reply.writeInt(result ? 1 : 0);
+            return true;
+        }
+
         case STOP_USER_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             int userid = data.readInt();
@@ -1843,6 +1852,17 @@
             return true;
         }
 
+        case GET_TAG_FOR_INTENT_SENDER_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IIntentSender r = IIntentSender.Stub.asInterface(
+                data.readStrongBinder());
+            String prefix = data.readString();
+            String tag = getTagForIntentSender(r, prefix);
+            reply.writeNoException();
+            reply.writeString(tag);
+            return true;
+        }
+
         case UPDATE_PERSISTENT_CONFIGURATION_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             Configuration config = Configuration.CREATOR.createFromParcel(data);
@@ -2038,6 +2058,15 @@
             return true;
         }
 
+        case DELETE_ACTIVITY_CONTAINER_TRANSACTION:  {
+            data.enforceInterface(IActivityManager.descriptor);
+            IActivityContainer activityContainer =
+                    IActivityContainer.Stub.asInterface(data.readStrongBinder());
+            deleteActivityContainer(activityContainer);
+            reply.writeNoException();
+            return true;
+        }
+
         case GET_ACTIVITY_CONTAINER_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder activityToken = data.readStrongBinder();
@@ -4284,6 +4313,19 @@
         return result;
     }
 
+    public boolean startUserInBackground(int userid) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeInt(userid);
+        mRemote.transact(START_USER_IN_BACKGROUND_TRANSACTION, data, reply, 0);
+        reply.readException();
+        boolean result = reply.readInt() != 0;
+        reply.recycle();
+        data.recycle();
+        return result;
+    }
+
     public int stopUser(int userid, IStopUserCallback callback) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
@@ -4426,6 +4468,21 @@
         return res;
     }
 
+    public String getTagForIntentSender(IIntentSender sender, String prefix)
+            throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(sender.asBinder());
+        data.writeString(prefix);
+        mRemote.transact(GET_TAG_FOR_INTENT_SENDER_TRANSACTION, data, reply, 0);
+        reply.readException();
+        String res = reply.readString();
+        data.recycle();
+        reply.recycle();
+        return res;
+    }
+
     public void updatePersistentConfiguration(Configuration values) throws RemoteException
     {
         Parcel data = Parcel.obtain();
@@ -4697,6 +4754,18 @@
         return res;
     }
 
+    public void deleteActivityContainer(IActivityContainer activityContainer)
+            throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(activityContainer.asBinder());
+        mRemote.transact(DELETE_ACTIVITY_CONTAINER_TRANSACTION, data, reply, 0);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
+
     public IActivityContainer getEnclosingActivityContainer(IBinder activityToken)
             throws RemoteException {
         Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 3f97c40..07247ff 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -16,7 +16,6 @@
 
 package android.app;
 
-import android.animation.Animator;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.os.Bundle;
@@ -24,8 +23,8 @@
 import android.os.IRemoteCallback;
 import android.os.RemoteException;
 import android.transition.Transition;
-import android.util.ArrayMap;
 import android.util.Log;
+import android.util.Pair;
 import android.view.View;
 
 import java.util.ArrayList;
@@ -100,12 +99,6 @@
     public static final String KEY_ANIM_START_LISTENER = "android:animStartListener";
 
     /**
-     * Arguments for the scene transition about to begin.
-     * @hide
-     */
-    public static final String KEY_SCENE_TRANSITION_ARGS = "android:sceneTransitionArgs";
-
-    /**
      * For Activity transitions, the calling Activity's TransitionListener used to
      * notify the called Activity when the shared element and the exit transitions
      * complete.
@@ -120,9 +113,15 @@
     private static final String KEY_TRANSITION_TARGET_LISTENER = "android:transitionTargetListener";
 
     /**
-     * The shared element's texture ID (TODO: not used yet).
+     * The names of shared elements that are transitioned to the started Activity.
+     * This is also the name of shared elements that the started Activity accepted.
      */
-    private static final String KEY_SHARED_ELEMENT_TEXTURE_ID = "android:sharedElementTextureId";
+    private static final String KEY_SHARED_ELEMENT_NAMES = "android:shared_element_names";
+
+    /**
+     * The shared elements names of the views in the calling Activity.
+     */
+    private static final String KEY_LOCAL_ELEMENT_NAMES = "android:local_element_names";
 
     /** @hide */
     public static final int ANIM_NONE = 0;
@@ -146,9 +145,10 @@
     private int mStartY;
     private int mStartWidth;
     private int mStartHeight;
-    private Bundle mTransitionArgs;
     private IRemoteCallback mAnimationStartedListener;
     private IRemoteCallback mTransitionCompleteListener;
+    private ArrayList<String> mSharedElementNames;
+    private ArrayList<String> mLocalElementNames;
 
     /**
      * Create an ActivityOptions specifying a custom animation to run when
@@ -226,7 +226,7 @@
 
     /** @hide */
     public interface ActivityTransitionTarget {
-        void sharedElementTransitionComplete();
+        void sharedElementTransitionComplete(Bundle transitionArgs);
         void exitTransitionComplete();
     }
 
@@ -348,35 +348,51 @@
     }
 
     /**
-     * Create an ActivityOptions to transition between Activities using cross-Activity animation.
-     * When visual elements are to carry between Activities, args should be used to tell the called
-     * Activity about the location and size.
-     *
-     * TODO: Provide facility to capture layout and bitmap of shared elements.
-     *
-     * <p>When
-     * {@link android.app.Activity#startActivities(android.content.Intent[], android.os.Bundle)}
-     * is used with the {@link #toBundle()} result, the Activity's content scene will automatically
-     * transition out by setting their visibility to {@link View#INVISIBLE}. Shared elements
-     * ({@link android.view.View#setSharedElementName(String)}) are unmodified during the
-     * transition to allow the started Activity to seamlessly take it over. ViewGroups typically
-     * don't transition out, and instead transition out their children unless they have a
-     * background. To modify this behavior, use
-     * {@link android.view.ViewGroup#setTransitionGroup(boolean)}.</p>
+     * Create an ActivityOptions to transition between Activities using cross-Activity scene
+     * animations. This method carries the position of one shared element to the started Activity.
      *
      * <p>This requires {@link android.view.Window#FEATURE_CONTENT_TRANSITIONS} to be
      * enabled on the calling Activity to cause an exit transition. The same must be in
      * the called Activity to get an entering transition.</p>
-     *
-     * @param args Contains information for transferring a view between this Activity and the
-     *             target Activity. Will be used by the called Activity to transition the
-     *             view to its eventual destination
-     * @see android.app.Activity#startSharedElementTransition(android.os.Bundle)
+     * @param sharedElement The View to transition to the started Activity. sharedElement must
+     *                      have a non-null sharedElementName.
+     * @param sharedElementName The shared element name as used in the target Activity. This may
+     *                          be null if it has the same name as sharedElement.
+     * @return Returns a new ActivityOptions object that you can use to
+     *         supply these options as the options Bundle when starting an activity.
      */
-    public static ActivityOptions makeSceneTransitionAnimation(Bundle args) {
+    public static ActivityOptions makeSceneTransitionAnimation(View sharedElement,
+            String sharedElementName) {
+        return makeSceneTransitionAnimation(
+                new Pair<View, String>(sharedElement, sharedElementName));
+    }
+
+    /**
+     * Create an ActivityOptions to transition between Activities using cross-Activity scene
+     * animations. This method carries the position of multiple shared elements to the started
+     * Activity.
+     *
+     * <p>This requires {@link android.view.Window#FEATURE_CONTENT_TRANSITIONS} to be
+     * enabled on the calling Activity to cause an exit transition. The same must be in
+     * the called Activity to get an entering transition.</p>
+     * @param sharedElements The View to transition to the started Activity along with the
+     *                       shared element name as used in the started Activity. The view
+     *                       must have a non-null sharedElementName.
+     * @return Returns a new ActivityOptions object that you can use to
+     *         supply these options as the options Bundle when starting an activity.
+     */
+    public static ActivityOptions makeSceneTransitionAnimation(
+            Pair<View, String>... sharedElements) {
         ActivityOptions opts = new ActivityOptions();
         opts.mAnimationType = ANIM_SCENE_TRANSITION;
-        opts.mTransitionArgs = args;
+        opts.mSharedElementNames = new ArrayList<String>();
+        opts.mLocalElementNames = new ArrayList<String>();
+
+        if (sharedElements != null) {
+            for (Pair<View, String> sharedElement : sharedElements) {
+                opts.addSharedElement(sharedElement.first, sharedElement.second);
+            }
+        }
         return opts;
     }
 
@@ -412,9 +428,10 @@
                 break;
 
             case ANIM_SCENE_TRANSITION:
-                mTransitionArgs = opts.getBundle(KEY_SCENE_TRANSITION_ARGS);
                 mTransitionCompleteListener = IRemoteCallback.Stub.asInterface(
                         opts.getBinder(KEY_TRANSITION_COMPLETE_LISTENER));
+                mSharedElementNames = opts.getStringArrayList(KEY_SHARED_ELEMENT_NAMES);
+                mLocalElementNames = opts.getStringArrayList(KEY_LOCAL_ELEMENT_NAMES);
                 break;
         }
     }
@@ -465,17 +482,19 @@
     }
 
     /** @hide */
-    public Bundle getSceneTransitionArgs() {
-        return mTransitionArgs;
-    }
-
-    /** @hide */
     public IRemoteCallback getOnAnimationStartListener() {
         return mAnimationStartedListener;
     }
 
     /** @hide */
-    public void dispatchSceneTransitionStarted(final ActivityTransitionTarget target) {
+    public ArrayList<String> getSharedElementNames() { return mSharedElementNames; }
+
+    /** @hide */
+    public ArrayList<String> getLocalElementNames() { return mLocalElementNames; }
+
+    /** @hide */
+    public void dispatchSceneTransitionStarted(final ActivityTransitionTarget target,
+            ArrayList<String> sharedElementNames) {
         boolean listenerSent = false;
         if (mTransitionCompleteListener != null) {
             IRemoteCallback callback = new IRemoteCallback.Stub() {
@@ -484,13 +503,13 @@
                     if (data == null) {
                         target.exitTransitionComplete();
                     } else {
-                        // TODO: Use texture id
-                        target.sharedElementTransitionComplete();
+                        target.sharedElementTransitionComplete(data);
                     }
                 }
             };
             Bundle bundle = new Bundle();
             bundle.putBinder(KEY_TRANSITION_TARGET_LISTENER, callback.asBinder());
+            bundle.putStringArrayList(KEY_SHARED_ELEMENT_NAMES, sharedElementNames);
             try {
                 mTransitionCompleteListener.sendResult(bundle);
                 listenerSent = true;
@@ -499,12 +518,23 @@
             }
         }
         if (!listenerSent) {
-            target.sharedElementTransitionComplete();
+            target.sharedElementTransitionComplete(null);
             target.exitTransitionComplete();
         }
     }
 
     /** @hide */
+    public void dispatchSharedElementsReady() {
+        if (mTransitionCompleteListener != null) {
+            try {
+                mTransitionCompleteListener.sendResult(null);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Couldn't synchronize shared elements", e);
+            }
+        }
+    }
+
+    /** @hide */
     public void abort() {
         if (mAnimationStartedListener != null) {
             try {
@@ -530,6 +560,8 @@
         if (otherOptions.mPackageName != null) {
             mPackageName = otherOptions.mPackageName;
         }
+        mSharedElementNames = null;
+        mLocalElementNames = null;
         switch (otherOptions.mAnimationType) {
             case ANIM_CUSTOM:
                 mAnimationType = otherOptions.mAnimationType;
@@ -544,7 +576,6 @@
                 }
                 mAnimationStartedListener = otherOptions.mAnimationStartedListener;
                 mTransitionCompleteListener = null;
-                mTransitionArgs = null;
                 break;
             case ANIM_SCALE_UP:
                 mAnimationType = otherOptions.mAnimationType;
@@ -560,7 +591,6 @@
                 }
                 mAnimationStartedListener = null;
                 mTransitionCompleteListener = null;
-                mTransitionArgs = null;
                 break;
             case ANIM_THUMBNAIL_SCALE_UP:
             case ANIM_THUMBNAIL_SCALE_DOWN:
@@ -576,14 +606,14 @@
                 }
                 mAnimationStartedListener = otherOptions.mAnimationStartedListener;
                 mTransitionCompleteListener = null;
-                mTransitionArgs = null;
                 break;
             case ANIM_SCENE_TRANSITION:
                 mAnimationType = otherOptions.mAnimationType;
                 mTransitionCompleteListener = otherOptions.mTransitionCompleteListener;
-                mTransitionArgs = otherOptions.mTransitionArgs;
                 mThumbnail = null;
                 mAnimationStartedListener = null;
+                mSharedElementNames = otherOptions.mSharedElementNames;
+                mLocalElementNames = otherOptions.mLocalElementNames;
                 break;
         }
     }
@@ -627,11 +657,12 @@
                 break;
             case ANIM_SCENE_TRANSITION:
                 b.putInt(KEY_ANIM_TYPE, mAnimationType);
-                b.putBundle(KEY_SCENE_TRANSITION_ARGS, mTransitionArgs);
                 if (mTransitionCompleteListener != null) {
                     b.putBinder(KEY_TRANSITION_COMPLETE_LISTENER,
                             mTransitionCompleteListener.asBinder());
                 }
+                b.putStringArrayList(KEY_SHARED_ELEMENT_NAMES, mSharedElementNames);
+                b.putStringArrayList(KEY_LOCAL_ELEMENT_NAMES, mLocalElementNames);
                 break;
         }
         return b;
@@ -652,32 +683,52 @@
     }
 
     /** @hide */
-    public interface SharedElementSource {
-        int getTextureId();
+    public void addSharedElements(Map<String, View> sharedElements) {
+        for (Map.Entry<String, View> entry : sharedElements.entrySet()) {
+            addSharedElement(entry.getValue(), entry.getKey());
+        }
     }
 
-    /**
-     * In the calling Activity when transitioning out, sets the Transition to listen for
-     * changes.
-     * @hide
-     */
-    public void setExitTransition(Transition transition, SharedElementSource sharedElementSource) {
-        mTransitionCompleteListener = new ExitTransitionListener(transition, sharedElementSource);
+    /** @hide */
+    public void updateSceneTransitionAnimation(Transition exitTransition,
+            Transition sharedElementTransition, SharedElementSource sharedElementSource) {
+        mTransitionCompleteListener = new ExitTransitionListener(exitTransition,
+                sharedElementTransition, sharedElementSource);
+    }
+
+    private void addSharedElement(View view, String name) {
+        String sharedElementName = view.getSharedElementName();
+        if (name == null) {
+            name = sharedElementName;
+        }
+        mSharedElementNames.add(name);
+        mLocalElementNames.add(sharedElementName);
+    }
+
+    /** @hide */
+    public interface SharedElementSource {
+        Bundle getSharedElementExitState();
+        void acceptedSharedElements(ArrayList<String> sharedElementNames);
+        void hideSharedElements();
     }
 
     private static class ExitTransitionListener extends IRemoteCallback.Stub
-            implements Transition.TransitionListener, Animator.AnimatorListener {
-        private ArrayList<Animator> mSharedElementAnimators = new ArrayList<Animator>();
+            implements Transition.TransitionListener {
         private boolean mSharedElementNotified;
         private Transition mExitTransition;
+        private Transition mSharedElementTransition;
         private IRemoteCallback mTransitionCompleteCallback;
         private boolean mExitComplete;
+        private boolean mSharedElementComplete;
         private SharedElementSource mSharedElementSource;
 
-        public ExitTransitionListener(Transition transition, SharedElementSource sharedElementSource) {
+        public ExitTransitionListener(Transition exitTransition, Transition sharedElementTransition,
+                SharedElementSource sharedElementSource) {
             mSharedElementSource = sharedElementSource;
-            mExitTransition = transition;
+            mExitTransition = exitTransition;
             mExitTransition.addListener(this);
+            mSharedElementTransition = sharedElementTransition;
+            mSharedElementTransition.addListener(this);
         }
 
         @Override
@@ -685,36 +736,36 @@
             if (data != null) {
                 mTransitionCompleteCallback = IRemoteCallback.Stub.asInterface(
                         data.getBinder(KEY_TRANSITION_TARGET_LISTENER));
+                ArrayList<String> sharedElementNames
+                        = data.getStringArrayList(KEY_SHARED_ELEMENT_NAMES);
+                mSharedElementSource.acceptedSharedElements(sharedElementNames);
                 notifySharedElement();
                 notifyExit();
+            } else {
+                mSharedElementSource.hideSharedElements();
             }
         }
 
         @Override
         public void onTransitionStart(Transition transition) {
-            ArrayMap<Animator, Transition.AnimationInfo> runningAnimators
-                    = Transition.getRunningAnimators();
-            for (Map.Entry<Animator, Transition.AnimationInfo> entry : runningAnimators.entrySet()) {
-                if (entry.getValue().view.getSharedElementName() != null) {
-                    mSharedElementAnimators.add(entry.getKey());
-                    entry.getKey().addListener(this);
-                }
-            }
-            notifySharedElement();
         }
 
         @Override
         public void onTransitionEnd(Transition transition) {
-            mExitComplete = true;
-            notifyExit();
-            mExitTransition.removeListener(this);
+            if (transition == mExitTransition) {
+                mExitComplete = true;
+                notifyExit();
+                mExitTransition.removeListener(this);
+            } else {
+                mSharedElementComplete = true;
+                notifySharedElement();
+                mSharedElementTransition.removeListener(this);
+            }
         }
 
         @Override
         public void onTransitionCancel(Transition transition) {
-            mExitComplete = true;
-            notifyExit();
-            mExitTransition.removeListener(this);
+            onTransitionEnd(transition);
         }
 
         @Override
@@ -725,34 +776,13 @@
         public void onTransitionResume(Transition transition) {
         }
 
-        @Override
-        public void onAnimationStart(Animator animation) {
-        }
-
-        @Override
-        public void onAnimationEnd(Animator animation) {
-            mSharedElementAnimators.remove(animation);
-            notifySharedElement();
-        }
-
-        @Override
-        public void onAnimationCancel(Animator animation) {
-            mSharedElementAnimators.remove(animation);
-            notifySharedElement();
-        }
-
-        @Override
-        public void onAnimationRepeat(Animator animation) {
-        }
-
         private void notifySharedElement() {
-            if (!mSharedElementNotified && mSharedElementAnimators.isEmpty()
+            if (!mSharedElementNotified && mSharedElementComplete
                     && mTransitionCompleteCallback != null) {
                 mSharedElementNotified = true;
                 try {
-                    Bundle bundle = new Bundle();
-                    bundle.putInt(KEY_SHARED_ELEMENT_TEXTURE_ID, mSharedElementSource.getTextureId());
-                    mTransitionCompleteCallback.sendResult(bundle);
+                    Bundle sharedElementState = mSharedElementSource.getSharedElementExitState();
+                    mTransitionCompleteCallback.sendResult(sharedElementState);
                 } catch (RemoteException e) {
                     Log.w(TAG, "Couldn't notify that the transition ended", e);
                 }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3258585..138eea2 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -71,6 +71,7 @@
 import android.os.UserHandle;
 import android.transition.Scene;
 import android.transition.TransitionManager;
+import android.provider.Settings;
 import android.util.AndroidRuntimeException;
 import android.util.ArrayMap;
 import android.util.DisplayMetrics;
@@ -110,6 +111,7 @@
 import java.lang.ref.WeakReference;
 import java.net.InetAddress;
 import java.security.Security;
+import java.text.DateFormat;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
@@ -750,8 +752,42 @@
 
             setCoreSettings(coreSettings);
 
-            // Tell the VMRuntime about the application.
-            VMRuntime.registerAppInfo(appInfo.dataDir, appInfo.processName);
+            /*
+             * Two possible indications that this package could be
+             * sharing its runtime with other packages:
+             *
+             * 1.) the sharedUserId attribute is set in the manifest,
+             *     indicating a request to share a VM with other
+             *     packages with the same sharedUserId.
+             *
+             * 2.) the application element of the manifest has an
+             *     attribute specifying a non-default process name,
+             *     indicating the desire to run in another packages VM.
+             *
+             * If sharing is enabled we do not have a unique application
+             * in a process and therefore cannot rely on the package
+             * name inside the runtime.
+             */
+            IPackageManager pm = getPackageManager();
+            android.content.pm.PackageInfo pi = null;
+            try {
+                pi = pm.getPackageInfo(appInfo.packageName, 0, UserHandle.myUserId());
+            } catch (RemoteException e) {
+            }
+            if (pi != null) {
+                boolean sharedUserIdSet = (pi.sharedUserId != null);
+                boolean processNameNotDefault =
+                (pi.applicationInfo != null &&
+                 !appInfo.packageName.equals(pi.applicationInfo.processName));
+                boolean sharable = (sharedUserIdSet || processNameNotDefault);
+
+                // Tell the VMRuntime about the application, unless it is shared
+                // inside a process.
+                if (!sharable) {
+                    VMRuntime.registerAppInfo(appInfo.packageName, appInfo.dataDir,
+                                            appInfo.processName);
+                }
+            }
 
             AppBindData data = new AppBindData();
             data.processName = processName;
@@ -1103,6 +1139,11 @@
         public void scheduleInstallProvider(ProviderInfo provider) {
             sendMessage(H.INSTALL_PROVIDER, provider);
         }
+
+        @Override
+        public final void updateTimePrefs(boolean is24Hour) {
+            DateFormat.set24HourTimePref(is24Hour);
+        }
     }
 
     private class H extends Handler {
@@ -1152,6 +1193,7 @@
         public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143;
         public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144;
         public static final int INSTALL_PROVIDER        = 145;
+
         String codeToString(int code) {
             if (DEBUG_MESSAGES) {
                 switch (code) {
@@ -4215,6 +4257,11 @@
                 Log.e(TAG, "Unable to setupGraphicsSupport due to missing cache directory");
             }
         }
+
+
+        final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24));
+        DateFormat.set24HourTimePref(is24Hr);
+
         /**
          * For system applications on userdebug/eng builds, log stack
          * traces of disk and network access to dropbox for analysis.
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index 48ec420..113f123 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -37,8 +37,10 @@
 import android.view.ViewGroup;
 import android.view.WindowManager;
 
+/** @hide */
 public class ActivityView extends ViewGroup {
     private final String TAG = "ActivityView";
+    private final boolean DEBUG = false;
 
     private final TextureView mTextureView;
     private IActivityContainer mActivityContainer;
@@ -76,6 +78,7 @@
         mTextureView = new TextureView(context);
         mTextureView.setSurfaceTextureListener(new ActivityViewSurfaceTextureListener());
         addView(mTextureView);
+        if (DEBUG) Log.v(TAG, "ctor()");
     }
 
     @Override
@@ -85,6 +88,8 @@
 
     @Override
     protected void onAttachedToWindow() {
+        if (DEBUG) Log.v(TAG, "onAttachedToWindow()");
+        super.onAttachedToWindow();
         try {
             final IBinder token = mActivity.getActivityToken();
             mActivityContainer =
@@ -99,19 +104,30 @@
 
     @Override
     protected void onDetachedFromWindow() {
+        if (DEBUG) Log.v(TAG, "onDetachedFromWindow(): mActivityContainer=" + mActivityContainer);
+        super.onDetachedFromWindow();
         if (mActivityContainer != null) {
             detach();
+            try {
+                ActivityManagerNative.getDefault().deleteActivityContainer(mActivityContainer);
+            } catch (RemoteException e) {
+            }
             mActivityContainer = null;
         }
     }
 
     @Override
     protected void onWindowVisibilityChanged(int visibility) {
+        if (DEBUG) Log.v(TAG, "onWindowVisibilityChanged(): visibility=" + visibility);
         super.onWindowVisibilityChanged(visibility);
-        if (visibility == View.VISIBLE) {
-            attachToSurfaceWhenReady();
-        } else {
-            detach();
+        switch (visibility) {
+            case  View.VISIBLE:
+                attachToSurfaceWhenReady();
+                break;
+            case  View.INVISIBLE:
+                break;
+            case View.GONE:
+                break;
         }
     }
 
@@ -143,6 +159,8 @@
     }
 
     public void startActivity(Intent intent) {
+        if (DEBUG) Log.v(TAG, "startActivity(): intent=" + intent + " " +
+                (isAttachedToDisplay() ? "" : "not") + " attached");
         if (mSurface != null) {
             try {
                 mActivityContainer.startActivity(intent);
@@ -165,6 +183,8 @@
     }
 
     public void startActivity(IntentSender intentSender) {
+        if (DEBUG) Log.v(TAG, "startActivityIntentSender(): intentSender=" + intentSender + " " +
+                (isAttachedToDisplay() ? "" : "not") + " attached");
         final IIntentSender iIntentSender = intentSender.getTarget();
         if (mSurface != null) {
             startActivityIntentSender(iIntentSender);
@@ -175,6 +195,8 @@
     }
 
     public void startActivity(PendingIntent pendingIntent) {
+        if (DEBUG) Log.v(TAG, "startActivityPendingIntent(): PendingIntent=" + pendingIntent + " "
+                + (isAttachedToDisplay() ? "" : "not") + " attached");
         final IIntentSender iIntentSender = pendingIntent.getTarget();
         if (mSurface != null) {
             startActivityIntentSender(iIntentSender);
@@ -205,6 +227,8 @@
                     "ActivityView: Unable to create ActivityContainer. " + e);
         }
 
+        if (DEBUG) Log.v(TAG, "attachToSurfaceWhenReady: " + (mQueuedIntent != null ||
+                mQueuedPendingIntent != null ? "" : "no") + " queued intent");
         if (mQueuedIntent != null) {
             startActivity(mQueuedIntent);
             mQueuedIntent = null;
@@ -215,6 +239,7 @@
     }
 
     private void detach() {
+        if (DEBUG) Log.d(TAG, "detach: attached=" + isAttachedToDisplay());
         if (mSurface != null) {
             try {
                 mActivityContainer.detachFromDisplay();
@@ -229,6 +254,8 @@
         @Override
         public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width,
                 int height) {
+            if (DEBUG) Log.d(TAG, "onSurfaceTextureAvailable: width=" + width + " height="
+                    + height);
             mWidth = width;
             mHeight = height;
             if (mActivityContainer != null) {
@@ -239,12 +266,12 @@
         @Override
         public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width,
                 int height) {
-            Log.d(TAG, "onSurfaceTextureSizeChanged: w=" + width + " h=" + height);
+            if (DEBUG) Log.d(TAG, "onSurfaceTextureSizeChanged: w=" + width + " h=" + height);
         }
 
         @Override
         public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
-            Log.d(TAG, "onSurfaceTextureDestroyed");
+            if (DEBUG) Log.d(TAG, "onSurfaceTextureDestroyed");
             detach();
             return true;
         }
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 6b48130..061e5a5 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1059,7 +1059,7 @@
     }
 
     @Override
-	  public void installPackageWithVerificationAndEncryption(Uri packageURI,
+    public void installPackageWithVerificationAndEncryption(Uri packageURI,
             IPackageInstallObserver observer, int flags, String installerPackageName,
             VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
         try {
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index c8f1280..f1c632e 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -630,6 +630,15 @@
             reply.writeNoException();
             return true;
         }
+
+        case UPDATE_TIME_PREFS_TRANSACTION:
+        {
+            data.enforceInterface(IApplicationThread.descriptor);
+            byte is24Hour = data.readByte();
+            updateTimePrefs(is24Hour == (byte) 1);
+            reply.writeNoException();
+            return true;
+        }
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -714,7 +723,7 @@
     }
 
     public final void scheduleSendResult(IBinder token, List<ResultInfo> results)
-    		throws RemoteException {
+            throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeStrongBinder(token);
@@ -884,7 +893,7 @@
     }
 
     public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
-	    int flags, Intent args) throws RemoteException {
+            int flags, Intent args) throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeStrongBinder(token);
@@ -1273,4 +1282,13 @@
         mRemote.transact(SCHEDULE_INSTALL_PROVIDER_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
         data.recycle();
     }
+
+    @Override
+    public void updateTimePrefs(boolean is24Hour) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        data.writeInterfaceToken(IApplicationThread.descriptor);
+        data.writeByte(is24Hour ? (byte) 1 : (byte) 0);
+        mRemote.transact(UPDATE_TIME_PREFS_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
+        data.recycle();
+    }
 }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 873db8e..9b3643c 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -63,7 +63,7 @@
 import android.location.LocationManager;
 import android.media.AudioManager;
 import android.media.MediaRouter;
-import android.media.MediaSessionManager;
+import android.media.session.MediaSessionManager;
 import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
 import android.net.INetworkPolicyManager;
@@ -358,10 +358,11 @@
                             ctx.mMainThread.getHandler());
                 }});
 
-        registerService(CONNECTIVITY_SERVICE, new StaticServiceFetcher() {
-                public Object createStaticService() {
+        registerService(CONNECTIVITY_SERVICE, new ServiceFetcher() {
+                public Object createService(ContextImpl ctx) {
                     IBinder b = ServiceManager.getService(CONNECTIVITY_SERVICE);
-                    return new ConnectivityManager(IConnectivityManager.Stub.asInterface(b));
+                    return new ConnectivityManager(IConnectivityManager.Stub.asInterface(b),
+                        ctx.getPackageName());
                 }});
 
         registerService(COUNTRY_DETECTOR, new StaticServiceFetcher() {
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 2559254..fb96d8d 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -707,6 +707,10 @@
     
     public void onDetachedFromWindow() {
     }
+
+    public void onWindowDismissed() {
+        dismiss();
+    }
     
     /**
      * Called to process key events.  You can override this to intercept all 
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index c09da87..6c0d379 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -1405,6 +1405,7 @@
         mRestored = false;
         mBackStackNesting = 0;
         mFragmentManager = null;
+        mChildFragmentManager = null;
         mActivity = null;
         mFragmentId = 0;
         mContainerId = 0;
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index bf2a629..76f9d97 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1026,6 +1026,7 @@
                                     f.mActivity = null;
                                     f.mParentFragment = null;
                                     f.mFragmentManager = null;
+                                    f.mChildFragmentManager = null;
                                 }
                             }
                         }
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 8c7fe10..1943bba 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -349,6 +349,7 @@
 
     // Multi-user APIs
     public boolean switchUser(int userid) throws RemoteException;
+    public boolean startUserInBackground(int userid) throws RemoteException;
     public int stopUser(int userid, IStopUserCallback callback) throws RemoteException;
     public UserInfo getCurrentUser() throws RemoteException;
     public boolean isUserRunning(int userid, boolean orStopping) throws RemoteException;
@@ -367,6 +368,8 @@
 
     public Intent getIntentForIntentSender(IIntentSender sender) throws RemoteException;
 
+    public String getTagForIntentSender(IIntentSender sender, String prefix) throws RemoteException;
+
     public void updatePersistentConfiguration(Configuration values) throws RemoteException;
 
     public long[] getProcessPss(int[] pids) throws RemoteException;
@@ -408,9 +411,13 @@
 
     public void performIdleMaintenance() throws RemoteException;
 
+    /** @hide */
     public IActivityContainer createActivityContainer(IBinder parentActivityToken,
             IActivityContainerCallback callback) throws RemoteException;
 
+    /** @hide */
+    public void deleteActivityContainer(IActivityContainer container) throws RemoteException;
+
     public IActivityContainer getEnclosingActivityContainer(IBinder activityToken)
             throws RemoteException;
 
@@ -704,4 +711,10 @@
     int APP_NOT_RESPONDING_VIA_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+182;
     int GET_HOME_ACTIVITY_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+183;
     int GET_ACTIVITY_CONTAINER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+184;
+    int DELETE_ACTIVITY_CONTAINER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+185;
+
+
+    // Start of L transactions
+    int GET_TAG_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+210;
+    int START_USER_IN_BACKGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+211;
 }
diff --git a/core/java/android/app/IAlarmManager.aidl b/core/java/android/app/IAlarmManager.aidl
index 8476609..ef9f26e 100644
--- a/core/java/android/app/IAlarmManager.aidl
+++ b/core/java/android/app/IAlarmManager.aidl
@@ -28,7 +28,7 @@
 	/** windowLength == 0 means exact; windowLength < 0 means the let the OS decide */
     void set(int type, long triggerAtTime, long windowLength,
             long interval, in PendingIntent operation, in WorkSource workSource);
-    void setTime(long millis);
+    boolean setTime(long millis);
     void setTimeZone(String zone);
     void remove(in PendingIntent operation);
 }
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 1ea9d87..ac8ac8f 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -139,6 +139,7 @@
             throws RemoteException;
     void setProcessState(int state) throws RemoteException;
     void scheduleInstallProvider(ProviderInfo provider) throws RemoteException;
+    void updateTimePrefs(boolean is24Hour) throws RemoteException;
 
     String descriptor = "android.app.IApplicationThread";
 
@@ -192,4 +193,5 @@
     int SCHEDULE_TRANSLUCENT_CONVERSION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+48;
     int SET_PROCESS_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+49;
     int SCHEDULE_INSTALL_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+50;
+    int UPDATE_TIME_PREFS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+51;
 }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 7926595..12a8ff6 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -204,6 +204,15 @@
      */
     public RemoteViews bigContentView;
 
+
+    /**
+     * @hide
+     * A medium-format version of {@link #contentView}, giving the Notification an
+     * opportunity to add action buttons to contentView. The system UI may
+     * choose to show this as a popup notification at its discretion.
+     */
+    public RemoteViews headsUpContentView;
+
     /**
      * The bitmap that may escape the bounds of the panel and bar.
      */
@@ -603,6 +612,13 @@
     public static final String EXTRA_AS_HEADS_UP = "headsup";
 
     /**
+     * Extra added from {@link Notification.Builder} to indicate that the remote views were inflated
+     * from the builder, as opposed to being created directly from the application.
+     * @hide
+     */
+    public static final String EXTRA_BUILDER_REMOTE_VIEWS = "android.builderRemoteViews";
+
+    /**
      * Value for {@link #EXTRA_AS_HEADS_UP}.
      * @hide
      */
@@ -809,6 +825,10 @@
             bigContentView = RemoteViews.CREATOR.createFromParcel(parcel);
         }
 
+        if (parcel.readInt() != 0) {
+            headsUpContentView = RemoteViews.CREATOR.createFromParcel(parcel);
+        }
+
         visibility = parcel.readInt();
 
         if (parcel.readInt() != 0) {
@@ -899,6 +919,10 @@
             that.bigContentView = this.bigContentView.clone();
         }
 
+        if (heavy && this.headsUpContentView != null) {
+            that.headsUpContentView = this.headsUpContentView.clone();
+        }
+
         that.visibility = this.visibility;
 
         if (this.publicVersion != null) {
@@ -920,6 +944,7 @@
         tickerView = null;
         contentView = null;
         bigContentView = null;
+        headsUpContentView = null;
         largeIcon = null;
         if (extras != null) {
             extras.remove(Notification.EXTRA_LARGE_ICON);
@@ -1032,6 +1057,13 @@
             parcel.writeInt(0);
         }
 
+        if (headsUpContentView != null) {
+            parcel.writeInt(1);
+            headsUpContentView.writeToParcel(parcel, 0);
+        } else {
+            parcel.writeInt(0);
+        }
+
         parcel.writeInt(visibility);
 
         if (publicVersion != null) {
@@ -1182,6 +1214,9 @@
         if (bigContentView != null) {
             bigContentView.setUser(user);
         }
+        if (headsUpContentView != null) {
+            headsUpContentView.setUser(user);
+        }
     }
 
     /**
@@ -1245,6 +1280,7 @@
         private boolean mShowWhen = true;
         private int mVisibility = VISIBILITY_PRIVATE;
         private Notification mPublicVersion = null;
+        private boolean mQuantumTheme;
 
         /**
          * Constructs a new Builder with the defaults:
@@ -1272,6 +1308,9 @@
             mWhen = System.currentTimeMillis();
             mAudioStreamType = STREAM_DEFAULT;
             mPriority = PRIORITY_DEFAULT;
+
+            // TODO: Decide on targetSdk from calling app whether to use quantum theme.
+            mQuantumTheme = true;
         }
 
         /**
@@ -1652,12 +1691,31 @@
         }
 
         /**
-         * Add metadata to this notification.
+         * Merge additional metadata into this notification.
          *
-         * A reference to the Bundle is held for the lifetime of this Builder, and the Bundle's
+         * <p>Values within the Bundle will replace existing extras values in this Builder.
+         *
+         * @see Notification#extras
+         */
+        public Builder addExtras(Bundle bag) {
+            if (mExtras == null) {
+                mExtras = new Bundle(bag);
+            } else {
+                mExtras.putAll(bag);
+            }
+            return this;
+        }
+
+        /**
+         * Set metadata for this notification.
+         *
+         * <p>A reference to the Bundle is held for the lifetime of this Builder, and the Bundle's
          * current contents are copied into the Notification each time {@link #build()} is
          * called.
          *
+         * <p>Replaces any existing extras values with those from the provided Bundle.
+         * Use {@link #addExtras} to merge in metadata instead.
+         *
          * @see Notification#extras
          */
         public Builder setExtras(Bundle bag) {
@@ -1666,6 +1724,23 @@
         }
 
         /**
+         * Get the current metadata Bundle used by this notification Builder.
+         *
+         * <p>The returned Bundle is shared with this Builder.
+         *
+         * <p>The current contents of this Bundle are copied into the Notification each time
+         * {@link #build()} is called.
+         *
+         * @see Notification#extras
+         */
+        public Bundle getExtras() {
+            if (mExtras == null) {
+                mExtras = new Bundle();
+            }
+            return mExtras;
+        }
+
+        /**
          * Add an action to this notification. Actions are typically displayed by
          * the system as a button adjacent to the notification content.
          * <p>
@@ -1743,7 +1818,7 @@
                 contentView.setImageViewBitmap(R.id.icon, mLargeIcon);
                 smallIconImageViewId = R.id.right_icon;
             }
-            if (mPriority < PRIORITY_LOW) {
+            if (!mQuantumTheme && mPriority < PRIORITY_LOW) {
                 contentView.setInt(R.id.icon,
                         "setBackgroundResource", R.drawable.notification_template_icon_low_bg);
                 contentView.setInt(R.id.status_bar_latest_event_content,
@@ -1857,7 +1932,7 @@
             if (mContentView != null) {
                 return mContentView;
             } else {
-                return applyStandardTemplate(R.layout.notification_template_base, true); // no more special large_icon flavor
+                return applyStandardTemplate(getBaseLayoutResource(), true); // no more special large_icon flavor
             }
         }
 
@@ -1878,14 +1953,21 @@
         private RemoteViews makeBigContentView() {
             if (mActions.size() == 0) return null;
 
-            return applyStandardTemplateWithActions(R.layout.notification_template_big_base);
+            return applyStandardTemplateWithActions(getBigBaseLayoutResource());
         }
 
+        private RemoteViews makeHeadsUpContentView() {
+            if (mActions.size() == 0) return null;
+
+            return applyStandardTemplateWithActions(getBigBaseLayoutResource());
+        }
+
+
         private RemoteViews generateActionButton(Action action) {
             final boolean tombstone = (action.actionIntent == null);
             RemoteViews button = new RemoteViews(mContext.getPackageName(),
-                    tombstone ? R.layout.notification_action_tombstone
-                              : R.layout.notification_action);
+                    tombstone ? getActionTombstoneLayoutResource()
+                              : getActionLayoutResource());
             button.setTextViewCompoundDrawablesRelative(R.id.action0, action.icon, 0, 0, 0);
             button.setTextViewText(R.id.action0, action.title);
             if (!tombstone) {
@@ -1921,6 +2003,7 @@
             n.defaults = mDefaults;
             n.flags = mFlags;
             n.bigContentView = makeBigContentView();
+            n.headsUpContentView = makeHeadsUpContentView();
             if (mLedOnMs != 0 || mLedOffMs != 0) {
                 n.flags |= FLAG_SHOW_LIGHTS;
             }
@@ -1953,7 +2036,7 @@
          * this Notification object.
          * @hide
          */
-        public void addExtras(Bundle extras) {
+        public void populateExtras(Bundle extras) {
             // Store original information used in the construction of this object
             extras.putCharSequence(EXTRA_TITLE, mContentTitle);
             extras.putCharSequence(EXTRA_TEXT, mContentText);
@@ -1965,6 +2048,7 @@
             extras.putBoolean(EXTRA_PROGRESS_INDETERMINATE, mProgressIndeterminate);
             extras.putBoolean(EXTRA_SHOW_CHRONOMETER, mUseChronometer);
             extras.putBoolean(EXTRA_SHOW_WHEN, mShowWhen);
+            extras.putBoolean(EXTRA_BUILDER_REMOTE_VIEWS, mContentView == null);
             if (mLargeIcon != null) {
                 extras.putParcelable(EXTRA_LARGE_ICON, mLargeIcon);
             }
@@ -1991,7 +2075,7 @@
 
             n.extras = mExtras != null ? new Bundle(mExtras) : new Bundle();
 
-            addExtras(n.extras);
+            populateExtras(n.extras);
             if (mStyle != null) {
                 mStyle.addExtras(n.extras);
             }
@@ -2008,6 +2092,49 @@
             build().cloneInto(n, true);
             return n;
         }
+
+
+        private int getBaseLayoutResource() {
+            return mQuantumTheme
+                    ? R.layout.notification_template_quantum_base
+                    : R.layout.notification_template_base;
+        }
+
+        private int getBigBaseLayoutResource() {
+            return mQuantumTheme
+                    ? R.layout.notification_template_quantum_big_base
+                    : R.layout.notification_template_big_base;
+        }
+
+        private int getBigPictureLayoutResource() {
+            return mQuantumTheme
+                    ? R.layout.notification_template_quantum_big_picture
+                    : R.layout.notification_template_big_picture;
+        }
+
+        private int getBigTextLayoutResource() {
+            return mQuantumTheme
+                    ? R.layout.notification_template_quantum_big_text
+                    : R.layout.notification_template_big_text;
+        }
+
+        private int getInboxLayoutResource() {
+            return mQuantumTheme
+                    ? R.layout.notification_template_quantum_inbox
+                    : R.layout.notification_template_inbox;
+        }
+
+        private int getActionLayoutResource() {
+            return mQuantumTheme
+                    ? R.layout.notification_quantum_action
+                    : R.layout.notification_action;
+        }
+
+        private int getActionTombstoneLayoutResource() {
+            return mQuantumTheme
+                    ? R.layout.notification_quantum_action_tombstone
+                    : R.layout.notification_action_tombstone;
+        }
     }
 
     /**
@@ -2177,7 +2304,7 @@
         }
 
         private RemoteViews makeBigContentView() {
-            RemoteViews contentView = getStandardView(R.layout.notification_template_big_picture);
+            RemoteViews contentView = getStandardView(mBuilder.getBigPictureLayoutResource());
 
             contentView.setImageViewBitmap(R.id.big_picture, mPicture);
 
@@ -2276,7 +2403,7 @@
             final boolean hadThreeLines = (mBuilder.mContentText != null && mBuilder.mSubText != null);
             mBuilder.mContentText = null;
 
-            RemoteViews contentView = getStandardView(R.layout.notification_template_big_text);
+            RemoteViews contentView = getStandardView(mBuilder.getBigTextLayoutResource());
 
             if (hadThreeLines) {
                 // vertical centering
@@ -2370,7 +2497,7 @@
         private RemoteViews makeBigContentView() {
             // Remove the content text so line3 disappears unless you have a summary
             mBuilder.mContentText = null;
-            RemoteViews contentView = getStandardView(R.layout.notification_template_inbox);
+            RemoteViews contentView = getStandardView(mBuilder.getInboxLayoutResource());
 
             contentView.setViewVisibility(R.id.text2, View.GONE);
 
diff --git a/core/java/android/app/OnActivityPausedListener.java b/core/java/android/app/OnActivityPausedListener.java
index 379f133..5003973 100644
--- a/core/java/android/app/OnActivityPausedListener.java
+++ b/core/java/android/app/OnActivityPausedListener.java
@@ -5,7 +5,7 @@
  * 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,
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index d4de112..8efc14f 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -889,6 +889,20 @@
     }
 
     /**
+     * @hide
+     * Return descriptive tag for this PendingIntent.
+     */
+    public String getTag(String prefix) {
+        try {
+            return ActivityManagerNative.getDefault()
+                .getTagForIntentSender(mTarget, prefix);
+        } catch (RemoteException e) {
+            // Should never happen.
+            return null;
+        }
+    }
+
+    /**
      * Comparison operator on two PendingIntent objects, such that true
      * is returned then they both represent the same operation from the
      * same package.  This allows you to use {@link #getActivity},
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 0cc878e..1f41c56 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -22,6 +22,7 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
@@ -1154,7 +1155,9 @@
                         }
                         exclSpec = listBuilder.toString();
                     }
-                    android.net.Proxy.validate(hostName, Integer.toString(port), exclSpec);
+                    if (android.net.Proxy.validate(hostName, Integer.toString(port), exclSpec)
+                            != android.net.Proxy.PROXY_VALID)
+                        throw new IllegalArgumentException();
                 }
                 return mService.setGlobalProxy(admin, hostSpec, exclSpec, UserHandle.myUserId());
             } catch (RemoteException e) {
@@ -1766,4 +1769,53 @@
         }
         return null;
     }
+
+    /**
+     * Called by a profile owner or device owner to add a default intent handler activity for
+     * intents that match a certain intent filter. This activity will remain the default intent
+     * handler even if the set of potential event handlers for the intent filter changes and if
+     * the intent preferences are reset.
+     *
+     * <p>The default disambiguation mechanism takes over if the activity is not installed
+     * (anymore). When the activity is (re)installed, it is automatically reset as default
+     * intent handler for the filter.
+     *
+     * <p>The calling device admin must be a profile owner or device owner. If it is not, a
+     * security exception will be thrown.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param filter The IntentFilter for which a default handler is added.
+     * @param activity The Activity that is added as default intent handler.
+     */
+    public void addPersistentPreferredActivity(ComponentName admin, IntentFilter filter,
+            ComponentName activity) {
+        if (mService != null) {
+            try {
+                mService.addPersistentPreferredActivity(admin, filter, activity);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
+
+    /**
+     * Called by a profile owner or device owner to remove all persistent intent handler preferences
+     * associated with the given package that were set by {@link #addPersistentPreferredActivity}.
+     *
+     * <p>The calling device admin must be a profile owner. If it is not, a security
+     * exception will be thrown.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param packageName The name of the package for which preferences are removed.
+     */
+    public void clearPackagePersistentPreferredActivities(ComponentName admin,
+            String packageName) {
+        if (mService != null) {
+            try {
+                mService.clearPackagePersistentPreferredActivities(admin, packageName);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
 }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 9d189db..8119585 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -18,6 +18,7 @@
 package android.app.admin;
 
 import android.content.ComponentName;
+import android.content.IntentFilter;
 import android.os.RemoteCallback;
 
 /**
@@ -109,4 +110,7 @@
 
     boolean installCaCert(in byte[] certBuffer);
     void uninstallCaCert(in byte[] certBuffer);
+
+    void addPersistentPreferredActivity(in ComponentName admin, in IntentFilter filter, in ComponentName activity);
+    void clearPackagePersistentPreferredActivities(in ComponentName admin, String packageName);
 }
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index 7b8b286..4b33799 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -172,7 +172,7 @@
      * <p>This field corresponds to the <code>android:previewImage</code> attribute in
      * the <code>&lt;receiver&gt;</code> element in the AndroidManifest.xml file.
      */
-	public int previewImage;
+    public int previewImage;
 
     /**
      * The rules by which a widget can be resized. See {@link #RESIZE_NONE},
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
index b8b8f5f..333f825 100644
--- a/core/java/android/bluetooth/BluetoothInputDevice.java
+++ b/core/java/android/bluetooth/BluetoothInputDevice.java
@@ -79,6 +79,13 @@
      * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_HANDSHAKE =
+        "android.bluetooth.input.profile.action.HANDSHAKE";
+
+    /**
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_REPORT =
         "android.bluetooth.input.profile.action.REPORT";
 
@@ -185,6 +192,11 @@
     /**
      * @hide
      */
+    public static final String EXTRA_STATUS = "android.bluetooth.BluetoothInputDevice.extra.STATUS";
+
+    /**
+     * @hide
+     */
     public static final String EXTRA_VIRTUAL_UNPLUG_STATUS = "android.bluetooth.BluetoothInputDevice.extra.VIRTUAL_UNPLUG_STATUS";
 
     private Context mContext;
@@ -608,7 +620,7 @@
      * @hide
      */
     public boolean setReport(BluetoothDevice device, byte reportType, String report) {
-        if (DBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
+        if (VDBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
         if (mService != null && isEnabled() && isValidDevice(device)) {
             try {
                 return mService.setReport(device, reportType, report);
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 8694416..f3c803d 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1540,7 +1540,7 @@
      * for a whole class of content.
      * @param notifyForDescendents If <code>true</code> changes to URIs beginning with <code>uri</code>
      * will also cause notifications to be sent. If <code>false</code> only changes to the exact URI
-     * specified by <em>uri</em> will cause notifications to be sent. If true, than any URI values
+     * specified by <em>uri</em> will cause notifications to be sent. If <code>true</code>, any URI values
      * at or below the specified URI will also trigger a match.
      * @param observer The object that receives callbacks when changes occur.
      * @see #unregisterContentObserver
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index d05d1a1..81a886a 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2352,10 +2352,10 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a
-     * {@link android.media.MediaSessionManager} for managing media Sessions.
+     * {@link android.media.session.MediaSessionManager} for managing media Sessions.
      *
      * @see #getSystemService
-     * @see android.media.MediaSessionManager
+     * @see android.media.session.MediaSessionManager
      */
     public static final String MEDIA_SESSION_SERVICE = "media_session";
 
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 3fdb6e7..f0b7ca8 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3334,6 +3334,15 @@
     public static final String EXTRA_SHUTDOWN_USERSPACE_ONLY
             = "android.intent.extra.SHUTDOWN_USERSPACE_ONLY";
 
+    /**
+     * Optional boolean extra for {@link #ACTION_TIME_CHANGED} that indicates the
+     * user has set their time format preferences to the 24 hour format.
+     *
+     * @hide for internal use only.
+     */
+    public static final String EXTRA_TIME_PREF_24_HOUR_FORMAT =
+            "android.intent.extra.TIME_PREF_24_HOUR_FORMAT";
+
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Intent flags (see mFlags variable).
diff --git a/core/java/android/content/Loader.java b/core/java/android/content/Loader.java
index f3828b0..e9d82af 100644
--- a/core/java/android/content/Loader.java
+++ b/core/java/android/content/Loader.java
@@ -24,7 +24,7 @@
 import java.io.PrintWriter;
 
 /**
- * An abstract class that performs asynchronous loading of data. While Loaders are active
+ * A class that performs asynchronous loading of data. While Loaders are active
  * they should monitor the source of their data and deliver new results when the contents
  * change.  See {@link android.app.LoaderManager} for more detail.
  *
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 20002ad..c9fb530 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -237,6 +237,10 @@
     int getPreferredActivities(out List<IntentFilter> outFilters,
             out List<ComponentName> outActivities, String packageName);
 
+    void addPersistentPreferredActivity(in IntentFilter filter, in ComponentName activity, int userId);
+
+    void clearPackagePersistentPreferredActivities(String packageName, int userId);
+
     /**
      * Report the set of 'Home' activity candidates, plus (if any) which of them
      * is the current "always use this one" setting.
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index 785f2b4..ef0c4d5 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -209,6 +209,19 @@
      */
     public static final int INSTALL_LOCATION_PREFER_EXTERNAL = 2;
     /**
+     * Flag for {@link #requiredForProfile}
+     * The application will always be installed for a restricted profile.
+     * @hide
+     */
+    public static final int RESTRICTED_PROFILE = 1;
+    /**
+     * Flag for {@link #requiredForProfile}
+     * The application will always be installed for a managed profile.
+     * @hide
+     */
+    public static final int MANAGED_PROFILE = 2;
+
+    /**
      * The install location requested by the activity.  From the
      * {@link android.R.attr#installLocation} attribute, one of
      * {@link #INSTALL_LOCATION_AUTO},
@@ -218,6 +231,12 @@
      */
     public int installLocation = INSTALL_LOCATION_INTERNAL_ONLY;
 
+    /**
+     * Defines which profiles this app is required for.
+     * @hide
+     */
+    public int requiredForProfile;
+
     /** @hide */
     public boolean requiredForAllUsers;
 
@@ -276,6 +295,7 @@
         dest.writeTypedArray(reqFeatures, parcelableFlags);
         dest.writeInt(installLocation);
         dest.writeInt(requiredForAllUsers ? 1 : 0);
+        dest.writeInt(requiredForProfile);
         dest.writeString(restrictedAccountType);
         dest.writeString(requiredAccountType);
         dest.writeString(overlayTarget);
@@ -318,6 +338,7 @@
         reqFeatures = source.createTypedArray(FeatureInfo.CREATOR);
         installLocation = source.readInt();
         requiredForAllUsers = source.readInt() != 0;
+        requiredForProfile = source.readInt();
         restrictedAccountType = source.readString();
         requiredAccountType = source.readString();
         overlayTarget = source.readString();
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 7fa9417..c222003 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -304,6 +304,7 @@
         if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0
                 || (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
             pi.requiredForAllUsers = p.mRequiredForAllUsers;
+            pi.requiredForProfile = p.mRequiredForProfile;
         }
         pi.restrictedAccountType = p.mRestrictedAccountType;
         pi.requiredAccountType = p.mRequiredAccountType;
@@ -1978,6 +1979,8 @@
                 false)) {
             owner.mRequiredForAllUsers = true;
         }
+        owner.mRequiredForProfile = sa.getInt(
+                com.android.internal.R.styleable.AndroidManifestApplication_requiredForProfile, 0);
 
         String restrictedAccountType = sa.getString(com.android.internal.R.styleable
                 .AndroidManifestApplication_restrictedAccountType);
@@ -3565,6 +3568,9 @@
         /* An app that's required for all users and cannot be uninstalled for a user */
         public boolean mRequiredForAllUsers;
 
+        /* For which types of profile this app is required */
+        public int mRequiredForProfile;
+
         /* The restricted account authenticator type that is used by this application */
         public String mRestrictedAccountType;
 
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index aa4a243..6f1d4f8 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -18,6 +18,7 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 
 /**
@@ -116,6 +117,14 @@
         return (flags & FLAG_MANAGED_PROFILE) == FLAG_MANAGED_PROFILE;
     }
 
+    /**
+     * @return true if this user can be switched to.
+     **/
+    public boolean supportsSwitchTo() {
+        // TODO remove fw.show_hidden_users when we have finished developing managed profiles.
+        return !isManagedProfile() || SystemProperties.getBoolean("fw.show_hidden_users", false);
+    }
+
     public UserInfo() {
     }
 
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 352825f..a41b4f9 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -539,7 +539,7 @@
          * @hide
          */
         public final int getAssetInt() {
-            return (int) mAsset;
+            throw new UnsupportedOperationException();
         }
         /**
          * @hide
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 431226a..419abf2 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -17,12 +17,14 @@
 package android.content.res;
 
 import android.graphics.Color;
+
 import com.android.internal.util.ArrayUtils;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.util.AttributeSet;
+import android.util.MathUtils;
 import android.util.SparseArray;
 import android.util.StateSet;
 import android.util.Xml;
@@ -172,7 +174,7 @@
      * Fill in this object based on the contents of an XML "selector" element.
      */
     private void inflate(Resources r, XmlPullParser parser, AttributeSet attrs)
-        throws XmlPullParserException, IOException {
+            throws XmlPullParserException, IOException {
 
         int type;
 
@@ -195,6 +197,8 @@
                 continue;
             }
 
+            int alphaRes = 0;
+            float alpha = 1.0f;
             int colorRes = 0;
             int color = 0xffff0000;
             boolean haveColor = false;
@@ -206,17 +210,20 @@
             for (i = 0; i < numAttrs; i++) {
                 final int stateResId = attrs.getAttributeNameResource(i);
                 if (stateResId == 0) break;
-                if (stateResId == com.android.internal.R.attr.color) {
+                if (stateResId == com.android.internal.R.attr.alpha) {
+                    alphaRes = attrs.getAttributeResourceValue(i, 0);
+                    if (alphaRes == 0) {
+                        alpha = attrs.getAttributeFloatValue(i, 1.0f);
+                    }
+                } else if (stateResId == com.android.internal.R.attr.color) {
                     colorRes = attrs.getAttributeResourceValue(i, 0);
-
                     if (colorRes == 0) {
                         color = attrs.getAttributeIntValue(i, color);
                         haveColor = true;
                     }
                 } else {
                     stateSpec[j++] = attrs.getAttributeBooleanValue(i, false)
-                                  ? stateResId
-                                  : -stateResId;
+                            ? stateResId : -stateResId;
                 }
             }
             stateSpec = StateSet.trimStateSet(stateSpec, j);
@@ -229,10 +236,18 @@
                         + ": <item> tag requires a 'android:color' attribute.");
             }
 
+            if (alphaRes != 0) {
+                alpha = r.getFraction(alphaRes, 1, 1);
+            }
+
+            // Apply alpha modulation.
+            final int alphaMod = MathUtils.constrain((int) (Color.alpha(color) * alpha), 0, 255);
+            color = (color & 0xFFFFFF) | (alphaMod << 24);
+
             if (listSize == 0 || stateSpec.length == 0) {
                 mDefaultColor = color;
             }
-            
+
             if (listSize + 1 >= listAllocated) {
                 listAllocated = ArrayUtils.idealIntArraySize(listSize + 1);
 
@@ -300,6 +315,25 @@
         return mDefaultColor;
     }
 
+    /**
+     * Return the states in this {@link ColorStateList}.
+     * @return the states in this {@link ColorStateList}
+     * @hide
+     */
+    public int[][] getStates() {
+        return mStateSpecs;
+    }
+
+    /**
+     * Return the colors in this {@link ColorStateList}.
+     * @return the colors in this {@link ColorStateList}
+     * @hide
+     */
+    public int[] getColors() {
+        return mColors;
+    }
+
+    @Override
     public String toString() {
         return "ColorStateList{" +
                "mStateSpecs=" + Arrays.deepToString(mStateSpecs) +
@@ -307,14 +341,16 @@
                "mDefaultColor=" + mDefaultColor + '}';
     }
 
+    @Override
     public int describeContents() {
         return 0;
     }
 
+    @Override
     public void writeToParcel(Parcel dest, int flags) {
         final int N = mStateSpecs.length;
         dest.writeInt(N);
-        for (int i=0; i<N; i++) {
+        for (int i = 0; i < N; i++) {
             dest.writeIntArray(mStateSpecs[i]);
         }
         dest.writeIntArray(mColors);
@@ -322,17 +358,19 @@
 
     public static final Parcelable.Creator<ColorStateList> CREATOR =
             new Parcelable.Creator<ColorStateList>() {
+        @Override
         public ColorStateList[] newArray(int size) {
             return new ColorStateList[size];
         }
 
+        @Override
         public ColorStateList createFromParcel(Parcel source) {
             final int N = source.readInt();
-            int[][] stateSpecs = new int[N][];
-            for (int i=0; i<N; i++) {
+            final int[][] stateSpecs = new int[N][];
+            for (int i = 0; i < N; i++) {
                 stateSpecs[i] = source.createIntArray();
             }
-            int[] colors = source.createIntArray();
+            final int[] colors = source.createIntArray();
             return new ColorStateList(stateSpecs, colors);
         }
     };
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index da6ae56..5c27072 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1625,7 +1625,7 @@
 
             String locale = null;
             if (mConfiguration.locale != null) {
-                locale = localeToLanguageTag(mConfiguration.locale);
+                locale = adjustLanguageTag(localeToLanguageTag(mConfiguration.locale));
             }
             int width, height;
             if (mMetrics.widthPixels >= mMetrics.heightPixels) {
@@ -1713,6 +1713,41 @@
     }
 
     /**
+     * {@code Locale.toLanguageTag} will transform the obsolete (and deprecated)
+     * language codes "in", "ji" and "iw" to "id", "yi" and "he" respectively.
+     *
+     * All released versions of android prior to "L" used the deprecated language
+     * tags, so we will need to support them for backwards compatibility.
+     *
+     * Note that this conversion needs to take place *after* the call to
+     * {@code toLanguageTag} because that will convert all the deprecated codes to
+     * the new ones, even if they're set manually.
+     */
+    private static String adjustLanguageTag(String languageTag) {
+        final int separator = languageTag.indexOf('-');
+        final String language;
+        final String remainder;
+
+        if (separator == -1) {
+            language = languageTag;
+            remainder = "";
+        } else {
+            language = languageTag.substring(0, separator);
+            remainder = languageTag.substring(separator);
+        }
+
+        if ("id".equals(language)) {
+            return "in" + remainder;
+        } else if ("yi".equals(language)) {
+            return "ji" + remainder;
+        } else if ("he".equals(language)) {
+            return "iw" + remainder;
+        } else {
+            return languageTag;
+        }
+    }
+
+    /**
      * Update the system resources configuration if they have previously
      * been initialized.
      *
diff --git a/core/java/android/debug/JNITest.java b/core/java/android/debug/JNITest.java
deleted file mode 100644
index 2ce374a..0000000
--- a/core/java/android/debug/JNITest.java
+++ /dev/null
@@ -1,48 +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.
- */
-
-package android.debug;
-
-/**
- * Simple JNI verification test.
- */
-public class JNITest {
-
-    public JNITest() {
-    }
-
-    public int test(int intArg, double doubleArg, String stringArg) {
-        int[] intArray = { 42, 53, 65, 127 };
-
-        return part1(intArg, doubleArg, stringArg, intArray);
-    }
-
-    private native int part1(int intArg, double doubleArg, String stringArg,
-        int[] arrayArg);
-
-    private int part2(double doubleArg, int fromArray, String stringArg) {
-        int result;
-
-        System.out.println(stringArg + " : " + (float) doubleArg + " : " +
-            fromArray);
-        result = part3(stringArg);
-
-        return result + 6;
-    }
-
-    private static native int part3(String stringArg);
-}
-
diff --git a/core/java/android/hardware/GeomagneticField.java b/core/java/android/hardware/GeomagneticField.java
index 0369825..ef05732 100644
--- a/core/java/android/hardware/GeomagneticField.java
+++ b/core/java/android/hardware/GeomagneticField.java
@@ -361,7 +361,7 @@
             mP[0] = new float[] { 1.0f };
             mPDeriv[0] = new float[] { 0.0f };
             for (int n = 1; n <= maxN; n++) {
-            	mP[n] = new float[n + 1];
+                mP[n] = new float[n + 1];
                 mPDeriv[n] = new float[n + 1];
                 for (int m = 0; m <= n; m++) {
                     if (n == m) {
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index a581982..a62df0f 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -999,7 +999,7 @@
     /**
      * <p>Use specific scene mode. Enabling this disables
      * control.aeMode, control.awbMode and control.afMode
-     * controls; the HAL must ignore those settings while
+     * controls; the camera device will ignore those settings while
      * USE_SCENE_MODE is active (except for FACE_PRIORITY
      * scene mode). Other control entries are still active.
      * This setting can only be used if availableSceneModes !=
@@ -1372,21 +1372,18 @@
     /**
      * <p>No lens shading correction is applied</p>
      * @see CaptureRequest#SHADING_MODE
-     * @hide
      */
     public static final int SHADING_MODE_OFF = 0;
 
     /**
      * <p>Must not slow down frame rate relative to sensor raw output</p>
      * @see CaptureRequest#SHADING_MODE
-     * @hide
      */
     public static final int SHADING_MODE_FAST = 1;
 
     /**
      * <p>Frame rate may be reduced by high quality</p>
      * @see CaptureRequest#SHADING_MODE
-     * @hide
      */
     public static final int SHADING_MODE_HIGH_QUALITY = 2;
 
@@ -1468,14 +1465,16 @@
 
     /**
      * <p>AE is off or recently reset. When a camera device is opened, it starts in
-     * this state.</p>
+     * this state. This is a transient state, the camera device may skip reporting
+     * this state in capture result.</p>
      * @see CaptureResult#CONTROL_AE_STATE
      */
     public static final int CONTROL_AE_STATE_INACTIVE = 0;
 
     /**
      * <p>AE doesn't yet have a good set of control values
-     * for the current scene.</p>
+     * for the current scene. This is a transient state, the camera device may skip
+     * reporting this state in capture result.</p>
      * @see CaptureResult#CONTROL_AE_STATE
      */
     public static final int CONTROL_AE_STATE_SEARCHING = 1;
@@ -1506,7 +1505,8 @@
      * (through the {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger} START),
      * and is currently executing it. Once PRECAPTURE
      * completes, AE will transition to CONVERGED or
-     * FLASH_REQUIRED as appropriate.</p>
+     * FLASH_REQUIRED as appropriate. This is a transient state, the
+     * camera device may skip reporting this state in capture result.</p>
      *
      * @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
      * @see CaptureResult#CONTROL_AE_STATE
@@ -1520,7 +1520,8 @@
     /**
      * <p>AF off or has not yet tried to scan/been asked
      * to scan.  When a camera device is opened, it starts in
-     * this state.</p>
+     * this state. This is a transient state, the camera device may
+     * skip reporting this state in capture result.</p>
      * @see CaptureResult#CONTROL_AF_STATE
      */
     public static final int CONTROL_AF_STATE_INACTIVE = 0;
@@ -1528,7 +1529,8 @@
     /**
      * <p>if CONTINUOUS_* modes are supported. AF is
      * currently doing an AF scan initiated by a continuous
-     * autofocus mode</p>
+     * autofocus mode. This is a transient state, the camera device may
+     * skip reporting this state in capture result.</p>
      * @see CaptureResult#CONTROL_AF_STATE
      */
     public static final int CONTROL_AF_STATE_PASSIVE_SCAN = 1;
@@ -1536,15 +1538,17 @@
     /**
      * <p>if CONTINUOUS_* modes are supported. AF currently
      * believes it is in focus, but may restart scanning at
-     * any time.</p>
+     * any time. This is a transient state, the camera device may skip
+     * reporting this state in capture result.</p>
      * @see CaptureResult#CONTROL_AF_STATE
      */
     public static final int CONTROL_AF_STATE_PASSIVE_FOCUSED = 2;
 
     /**
      * <p>if AUTO or MACRO modes are supported. AF is doing
-     * an AF scan because it was triggered by AF
-     * trigger</p>
+     * an AF scan because it was triggered by AF trigger. This is a
+     * transient state, the camera device may skip reporting
+     * this state in capture result.</p>
      * @see CaptureResult#CONTROL_AF_STATE
      */
     public static final int CONTROL_AF_STATE_ACTIVE_SCAN = 3;
@@ -1552,7 +1556,7 @@
     /**
      * <p>if any AF mode besides OFF is supported. AF
      * believes it is focused correctly and is
-     * locked</p>
+     * locked.</p>
      * @see CaptureResult#CONTROL_AF_STATE
      */
     public static final int CONTROL_AF_STATE_FOCUSED_LOCKED = 4;
@@ -1560,7 +1564,7 @@
     /**
      * <p>if any AF mode besides OFF is supported. AF has
      * failed to focus successfully and is
-     * locked</p>
+     * locked.</p>
      * @see CaptureResult#CONTROL_AF_STATE
      */
     public static final int CONTROL_AF_STATE_NOT_FOCUSED_LOCKED = 5;
@@ -1568,7 +1572,8 @@
     /**
      * <p>if CONTINUOUS_* modes are supported. AF finished a
      * passive scan without finding focus, and may restart
-     * scanning at any time.</p>
+     * scanning at any time. This is a transient state, the camera
+     * device may skip reporting this state in capture result.</p>
      * @see CaptureResult#CONTROL_AF_STATE
      */
     public static final int CONTROL_AF_STATE_PASSIVE_UNFOCUSED = 6;
@@ -1579,14 +1584,16 @@
 
     /**
      * <p>AWB is not in auto mode.  When a camera device is opened, it
-     * starts in this state.</p>
+     * starts in this state. This is a transient state, the camera device may
+     * skip reporting this state in capture result.</p>
      * @see CaptureResult#CONTROL_AWB_STATE
      */
     public static final int CONTROL_AWB_STATE_INACTIVE = 0;
 
     /**
      * <p>AWB doesn't yet have a good set of control
-     * values for the current scene.</p>
+     * values for the current scene. This is a transient state, the camera device
+     * may skip reporting this state in capture result.</p>
      * @see CaptureResult#CONTROL_AWB_STATE
      */
     public static final int CONTROL_AWB_STATE_SEARCHING = 1;
@@ -1670,6 +1677,110 @@
     public static final int LENS_STATE_MOVING = 1;
 
     //
+    // Enumeration values for CaptureResult#SENSOR_REFERENCE_ILLUMINANT
+    //
+
+    /**
+     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT_DAYLIGHT = 1;
+
+    /**
+     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT_FLUORESCENT = 2;
+
+    /**
+     * <p>Incandescent light</p>
+     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT_TUNGSTEN = 3;
+
+    /**
+     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT_FLASH = 4;
+
+    /**
+     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT_FINE_WEATHER = 9;
+
+    /**
+     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT_CLOUDY_WEATHER = 10;
+
+    /**
+     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT_SHADE = 11;
+
+    /**
+     * <p>D 5700 - 7100K</p>
+     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT_DAYLIGHT_FLUORESCENT = 12;
+
+    /**
+     * <p>N 4600 - 5400K</p>
+     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT_DAY_WHITE_FLUORESCENT = 13;
+
+    /**
+     * <p>W 3900 - 4500K</p>
+     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT_COOL_WHITE_FLUORESCENT = 14;
+
+    /**
+     * <p>WW 3200 - 3700K</p>
+     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT_WHITE_FLUORESCENT = 15;
+
+    /**
+     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT_STANDARD_A = 17;
+
+    /**
+     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT_STANDARD_B = 18;
+
+    /**
+     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT_STANDARD_C = 19;
+
+    /**
+     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT_D55 = 20;
+
+    /**
+     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT_D65 = 21;
+
+    /**
+     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT_D75 = 22;
+
+    /**
+     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT_D50 = 23;
+
+    /**
+     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT_ISO_STUDIO_TUNGSTEN = 24;
+
+    //
     // Enumeration values for CaptureResult#STATISTICS_SCENE_FLICKER
     //
 
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index dfde11b..a8caba0 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -390,7 +390,7 @@
 
     /**
      * <p>Gains applying to Bayer raw color channels for
-     * white-balance</p>
+     * white-balance.</p>
      * <p>The 4-channel white-balance gains are defined in
      * the order of <code>[R G_even G_odd B]</code>, where <code>G_even</code> is the gain
      * for green pixels on even rows of the output, and <code>G_odd</code>
@@ -398,11 +398,11 @@
      * does not support a separate gain for even/odd green channels,
      * it should use the <code>G_even</code> value, and write <code>G_odd</code> equal to
      * <code>G_even</code> in the output result metadata.</p>
-     * <p>This array is either set by HAL when the request
+     * <p>This array is either set by the camera device when the request
      * {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode} is not TRANSFORM_MATRIX, or
      * directly by the application in the request when the
      * {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode} is TRANSFORM_MATRIX.</p>
-     * <p>The output should be the gains actually applied by the HAL to
+     * <p>The output should be the gains actually applied by the camera device to
      * the current frame.</p>
      *
      * @see CaptureRequest#COLOR_CORRECTION_MODE
@@ -536,9 +536,9 @@
      * bottom-right pixel in the active pixel array. The weight
      * should be nonnegative.</p>
      * <p>If all regions have 0 weight, then no specific metering area
-     * needs to be used by the HAL. If the metering region is
-     * outside the current {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}, the HAL
-     * should ignore the sections outside the region and output the
+     * needs to be used by the camera device. If the metering region is
+     * outside the current {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}, the camera device
+     * will ignore the sections outside the region and output the
      * used sections in the frame metadata.</p>
      *
      * @see CaptureRequest#SCALER_CROP_REGION
@@ -579,13 +579,15 @@
     /**
      * <p>Whether AF is currently enabled, and what
      * mode it is set to</p>
-     * <p>Only effective if {@link CaptureRequest#CONTROL_MODE android.control.mode} = AUTO.</p>
+     * <p>Only effective if {@link CaptureRequest#CONTROL_MODE android.control.mode} = AUTO and the lens is not fixed focus
+     * (i.e. <code>{@link CameraCharacteristics#LENS_INFO_MINIMUM_FOCUS_DISTANCE android.lens.info.minimumFocusDistance} &gt; 0</code>).</p>
      * <p>If the lens is controlled by the camera device auto-focus algorithm,
      * the camera device will report the current AF status in {@link CaptureResult#CONTROL_AF_STATE android.control.afState}
      * in result metadata.</p>
      *
      * @see CaptureResult#CONTROL_AF_STATE
      * @see CaptureRequest#CONTROL_MODE
+     * @see CameraCharacteristics#LENS_INFO_MINIMUM_FOCUS_DISTANCE
      * @see #CONTROL_AF_MODE_OFF
      * @see #CONTROL_AF_MODE_AUTO
      * @see #CONTROL_AF_MODE_MACRO
@@ -609,9 +611,9 @@
      * bottom-right pixel in the active pixel array. The weight
      * should be nonnegative.</p>
      * <p>If all regions have 0 weight, then no specific focus area
-     * needs to be used by the HAL. If the focusing region is
-     * outside the current {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}, the HAL
-     * should ignore the sections outside the region and output the
+     * needs to be used by the camera device. If the focusing region is
+     * outside the current {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}, the camera device
+     * will ignore the sections outside the region and output the
      * used sections in the frame metadata.</p>
      *
      * @see CaptureRequest#SCALER_CROP_REGION
@@ -651,14 +653,14 @@
     /**
      * <p>Whether AWB is currently setting the color
      * transform fields, and what its illumination target
-     * is</p>
+     * is.</p>
      * <p>This control is only effective if {@link CaptureRequest#CONTROL_MODE android.control.mode} is AUTO.</p>
      * <p>When set to the ON mode, the camera device's auto white balance
      * routine is enabled, overriding the application's selected
      * {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}, {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} and
      * {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode}.</p>
      * <p>When set to the OFF mode, the camera device's auto white balance
-     * routine is disabled. The applicantion manually controls the white
+     * routine is disabled. The application manually controls the white
      * balance by {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}, {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains}
      * and {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode}.</p>
      * <p>When set to any other modes, the camera device's auto white balance
@@ -695,10 +697,10 @@
      * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the
      * bottom-right pixel in the active pixel array. The weight
      * should be nonnegative.</p>
-     * <p>If all regions have 0 weight, then no specific metering area
-     * needs to be used by the HAL. If the metering region is
-     * outside the current {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}, the HAL
-     * should ignore the sections outside the region and output the
+     * <p>If all regions have 0 weight, then no specific auto-white balance (AWB) area
+     * needs to be used by the camera device. If the AWB region is
+     * outside the current {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}, the camera device
+     * will ignore the sections outside the region and output the
      * used sections in the frame metadata.</p>
      *
      * @see CaptureRequest#SCALER_CROP_REGION
@@ -753,7 +755,7 @@
 
     /**
      * <p>Overall mode of 3A control
-     * routines</p>
+     * routines.</p>
      * <p>High-level 3A control. When set to OFF, all 3A control
      * by the camera device is disabled. The application must set the fields for
      * capture parameters itself.</p>
@@ -830,9 +832,9 @@
 
     /**
      * <p>Operation mode for edge
-     * enhancement</p>
+     * enhancement.</p>
      * <p>Edge/sharpness/detail enhancement. OFF means no
-     * enhancement will be applied by the HAL.</p>
+     * enhancement will be applied by the camera device.</p>
      * <p>FAST/HIGH_QUALITY both mean camera device determined enhancement
      * will be applied. HIGH_QUALITY mode indicates that the
      * camera device will use the highest-quality enhancement algorithms,
@@ -1044,7 +1046,7 @@
      * <p>Mode of operation for the noise reduction
      * algorithm</p>
      * <p>Noise filtering control. OFF means no noise reduction
-     * will be applied by the HAL.</p>
+     * will be applied by the camera device.</p>
      * <p>FAST/HIGH_QUALITY both mean camera device determined noise filtering
      * will be applied. HIGH_QUALITY mode indicates that the camera device
      * will use the highest-quality noise filtering algorithms,
@@ -1263,7 +1265,6 @@
      * @see #SHADING_MODE_OFF
      * @see #SHADING_MODE_FAST
      * @see #SHADING_MODE_HIGH_QUALITY
-     * @hide
      */
     public static final Key<Integer> SHADING_MODE =
             new Key<Integer>("android.shading.mode", int.class);
@@ -1285,8 +1286,8 @@
             new Key<Integer>("android.statistics.faceDetectMode", int.class);
 
     /**
-     * <p>Whether the HAL needs to output the lens
-     * shading map in output result metadata</p>
+     * <p>Whether the camera device will output the lens
+     * shading map in output result metadata.</p>
      * <p>When set to ON,
      * {@link CaptureResult#STATISTICS_LENS_SHADING_MAP android.statistics.lensShadingMap} must be provided in
      * the output result metadata.</p>
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 32526bd..0f2c7f7 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -143,7 +143,7 @@
 
     /**
      * <p>Gains applying to Bayer raw color channels for
-     * white-balance</p>
+     * white-balance.</p>
      * <p>The 4-channel white-balance gains are defined in
      * the order of <code>[R G_even G_odd B]</code>, where <code>G_even</code> is the gain
      * for green pixels on even rows of the output, and <code>G_odd</code>
@@ -151,11 +151,11 @@
      * does not support a separate gain for even/odd green channels,
      * it should use the <code>G_even</code> value, and write <code>G_odd</code> equal to
      * <code>G_even</code> in the output result metadata.</p>
-     * <p>This array is either set by HAL when the request
+     * <p>This array is either set by the camera device when the request
      * {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode} is not TRANSFORM_MATRIX, or
      * directly by the application in the request when the
      * {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode} is TRANSFORM_MATRIX.</p>
-     * <p>The output should be the gains actually applied by the HAL to
+     * <p>The output should be the gains actually applied by the camera device to
      * the current frame.</p>
      *
      * @see CaptureRequest#COLOR_CORRECTION_MODE
@@ -225,9 +225,9 @@
      * bottom-right pixel in the active pixel array. The weight
      * should be nonnegative.</p>
      * <p>If all regions have 0 weight, then no specific metering area
-     * needs to be used by the HAL. If the metering region is
-     * outside the current {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}, the HAL
-     * should ignore the sections outside the region and output the
+     * needs to be used by the camera device. If the metering region is
+     * outside the current {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}, the camera device
+     * will ignore the sections outside the region and output the
      * used sections in the frame metadata.</p>
      *
      * @see CaptureRequest#SCALER_CROP_REGION
@@ -370,6 +370,54 @@
      * </tr>
      * </tbody>
      * </table>
+     * <p>For the above table, the camera device may skip reporting any state changes that happen
+     * without application intervention (i.e. mode switch, trigger, locking). Any state that
+     * can be skipped in that manner is called a transient state.</p>
+     * <p>For example, for above AE modes (AE_MODE_ON_*), in addition to the state transitions
+     * listed in above table, it is also legal for the camera device to skip one or more
+     * transient states between two results. See below table for examples:</p>
+     * <table>
+     * <thead>
+     * <tr>
+     * <th align="center">State</th>
+     * <th align="center">Transition Cause</th>
+     * <th align="center">New State</th>
+     * <th align="center">Notes</th>
+     * </tr>
+     * </thead>
+     * <tbody>
+     * <tr>
+     * <td align="center">INACTIVE</td>
+     * <td align="center">Camera device finished AE scan</td>
+     * <td align="center">CONVERGED</td>
+     * <td align="center">Values are already good, transient states are skipped by camera device.</td>
+     * </tr>
+     * <tr>
+     * <td align="center">Any state</td>
+     * <td align="center">{@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger} is START, sequence done</td>
+     * <td align="center">FLASH_REQUIRED</td>
+     * <td align="center">Converged but too dark w/o flash after a precapture sequence, transient states are skipped by camera device.</td>
+     * </tr>
+     * <tr>
+     * <td align="center">Any state</td>
+     * <td align="center">{@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger} is START, sequence done</td>
+     * <td align="center">CONVERGED</td>
+     * <td align="center">Converged after a precapture sequence, transient states are skipped by camera device.</td>
+     * </tr>
+     * <tr>
+     * <td align="center">CONVERGED</td>
+     * <td align="center">Camera device finished AE scan</td>
+     * <td align="center">FLASH_REQUIRED</td>
+     * <td align="center">Converged but too dark w/o flash after a new scan, transient states are skipped by camera device.</td>
+     * </tr>
+     * <tr>
+     * <td align="center">FLASH_REQUIRED</td>
+     * <td align="center">Camera device finished AE scan</td>
+     * <td align="center">CONVERGED</td>
+     * <td align="center">Converged after a new scan, transient states are skipped by camera device.</td>
+     * </tr>
+     * </tbody>
+     * </table>
      *
      * @see CaptureRequest#CONTROL_AE_LOCK
      * @see CaptureRequest#CONTROL_AE_MODE
@@ -389,13 +437,15 @@
     /**
      * <p>Whether AF is currently enabled, and what
      * mode it is set to</p>
-     * <p>Only effective if {@link CaptureRequest#CONTROL_MODE android.control.mode} = AUTO.</p>
+     * <p>Only effective if {@link CaptureRequest#CONTROL_MODE android.control.mode} = AUTO and the lens is not fixed focus
+     * (i.e. <code>{@link CameraCharacteristics#LENS_INFO_MINIMUM_FOCUS_DISTANCE android.lens.info.minimumFocusDistance} &gt; 0</code>).</p>
      * <p>If the lens is controlled by the camera device auto-focus algorithm,
      * the camera device will report the current AF status in {@link CaptureResult#CONTROL_AF_STATE android.control.afState}
      * in result metadata.</p>
      *
      * @see CaptureResult#CONTROL_AF_STATE
      * @see CaptureRequest#CONTROL_MODE
+     * @see CameraCharacteristics#LENS_INFO_MINIMUM_FOCUS_DISTANCE
      * @see #CONTROL_AF_MODE_OFF
      * @see #CONTROL_AF_MODE_AUTO
      * @see #CONTROL_AF_MODE_MACRO
@@ -419,9 +469,9 @@
      * bottom-right pixel in the active pixel array. The weight
      * should be nonnegative.</p>
      * <p>If all regions have 0 weight, then no specific focus area
-     * needs to be used by the HAL. If the focusing region is
-     * outside the current {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}, the HAL
-     * should ignore the sections outside the region and output the
+     * needs to be used by the camera device. If the focusing region is
+     * outside the current {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}, the camera device
+     * will ignore the sections outside the region and output the
      * used sections in the frame metadata.</p>
      *
      * @see CaptureRequest#SCALER_CROP_REGION
@@ -431,7 +481,7 @@
             new Key<int[]>("android.control.afRegions", int[].class);
 
     /**
-     * <p>Current state of AF algorithm</p>
+     * <p>Current state of AF algorithm.</p>
      * <p>Switching between or enabling AF modes ({@link CaptureRequest#CONTROL_AF_MODE android.control.afMode}) always
      * resets the AF state to INACTIVE. Similarly, switching between {@link CaptureRequest#CONTROL_MODE android.control.mode},
      * or {@link CaptureRequest#CONTROL_SCENE_MODE android.control.sceneMode} if <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} == USE_SCENE_MODE</code> resets all
@@ -529,6 +579,48 @@
      * </tr>
      * </tbody>
      * </table>
+     * <p>For the above table, the camera device may skip reporting any state changes that happen
+     * without application intervention (i.e. mode switch, trigger, locking). Any state that
+     * can be skipped in that manner is called a transient state.</p>
+     * <p>For example, for these AF modes (AF_MODE_AUTO and AF_MODE_MACRO), in addition to the
+     * state transitions listed in above table, it is also legal for the camera device to skip
+     * one or more transient states between two results. See below table for examples:</p>
+     * <table>
+     * <thead>
+     * <tr>
+     * <th align="center">State</th>
+     * <th align="center">Transition Cause</th>
+     * <th align="center">New State</th>
+     * <th align="center">Notes</th>
+     * </tr>
+     * </thead>
+     * <tbody>
+     * <tr>
+     * <td align="center">INACTIVE</td>
+     * <td align="center">AF_TRIGGER</td>
+     * <td align="center">FOCUSED_LOCKED</td>
+     * <td align="center">Focus is already good or good after a scan, lens is now locked.</td>
+     * </tr>
+     * <tr>
+     * <td align="center">INACTIVE</td>
+     * <td align="center">AF_TRIGGER</td>
+     * <td align="center">NOT_FOCUSED_LOCKED</td>
+     * <td align="center">Focus failed after a scan, lens is now locked.</td>
+     * </tr>
+     * <tr>
+     * <td align="center">FOCUSED_LOCKED</td>
+     * <td align="center">AF_TRIGGER</td>
+     * <td align="center">FOCUSED_LOCKED</td>
+     * <td align="center">Focus is already good or good after a scan, lens is now locked.</td>
+     * </tr>
+     * <tr>
+     * <td align="center">NOT_FOCUSED_LOCKED</td>
+     * <td align="center">AF_TRIGGER</td>
+     * <td align="center">FOCUSED_LOCKED</td>
+     * <td align="center">Focus is good after a scan, lens is not locked.</td>
+     * </tr>
+     * </tbody>
+     * </table>
      * <p>When {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode} is AF_MODE_CONTINUOUS_VIDEO:</p>
      * <table>
      * <thead>
@@ -735,6 +827,41 @@
      * </tr>
      * </tbody>
      * </table>
+     * <p>When switch between AF_MODE_CONTINUOUS_* (CAF modes) and AF_MODE_AUTO/AF_MODE_MACRO
+     * (AUTO modes), the initial INACTIVE or PASSIVE_SCAN states may be skipped by the
+     * camera device. When a trigger is included in a mode switch request, the trigger
+     * will be evaluated in the context of the new mode in the request.
+     * See below table for examples:</p>
+     * <table>
+     * <thead>
+     * <tr>
+     * <th align="center">State</th>
+     * <th align="center">Transition Cause</th>
+     * <th align="center">New State</th>
+     * <th align="center">Notes</th>
+     * </tr>
+     * </thead>
+     * <tbody>
+     * <tr>
+     * <td align="center">any state</td>
+     * <td align="center">CAF--&gt;AUTO mode switch</td>
+     * <td align="center">INACTIVE</td>
+     * <td align="center">Mode switch without trigger, initial state must be INACTIVE</td>
+     * </tr>
+     * <tr>
+     * <td align="center">any state</td>
+     * <td align="center">CAF--&gt;AUTO mode switch with AF_TRIGGER</td>
+     * <td align="center">trigger-reachable states from INACTIVE</td>
+     * <td align="center">Mode switch with trigger, INACTIVE is skipped</td>
+     * </tr>
+     * <tr>
+     * <td align="center">any state</td>
+     * <td align="center">AUTO--&gt;CAF mode switch</td>
+     * <td align="center">passively reachable states from INACTIVE</td>
+     * <td align="center">Mode switch without trigger, passive transient state is skipped</td>
+     * </tr>
+     * </tbody>
+     * </table>
      *
      * @see CaptureRequest#CONTROL_AF_MODE
      * @see CaptureRequest#CONTROL_MODE
@@ -764,14 +891,14 @@
     /**
      * <p>Whether AWB is currently setting the color
      * transform fields, and what its illumination target
-     * is</p>
+     * is.</p>
      * <p>This control is only effective if {@link CaptureRequest#CONTROL_MODE android.control.mode} is AUTO.</p>
      * <p>When set to the ON mode, the camera device's auto white balance
      * routine is enabled, overriding the application's selected
      * {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}, {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} and
      * {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode}.</p>
      * <p>When set to the OFF mode, the camera device's auto white balance
-     * routine is disabled. The applicantion manually controls the white
+     * routine is disabled. The application manually controls the white
      * balance by {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}, {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains}
      * and {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode}.</p>
      * <p>When set to any other modes, the camera device's auto white balance
@@ -808,10 +935,10 @@
      * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.height - 1) being the
      * bottom-right pixel in the active pixel array. The weight
      * should be nonnegative.</p>
-     * <p>If all regions have 0 weight, then no specific metering area
-     * needs to be used by the HAL. If the metering region is
-     * outside the current {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}, the HAL
-     * should ignore the sections outside the region and output the
+     * <p>If all regions have 0 weight, then no specific auto-white balance (AWB) area
+     * needs to be used by the camera device. If the AWB region is
+     * outside the current {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}, the camera device
+     * will ignore the sections outside the region and output the
      * used sections in the frame metadata.</p>
      *
      * @see CaptureRequest#SCALER_CROP_REGION
@@ -905,11 +1032,35 @@
      * <td align="center">SEARCHING</td>
      * <td align="center">Values not good after unlock</td>
      * </tr>
+     * </tbody>
+     * </table>
+     * <p>For the above table, the camera device may skip reporting any state changes that happen
+     * without application intervention (i.e. mode switch, trigger, locking). Any state that
+     * can be skipped in that manner is called a transient state.</p>
+     * <p>For example, for this AWB mode (AWB_MODE_AUTO), in addition to the state transitions
+     * listed in above table, it is also legal for the camera device to skip one or more
+     * transient states between two results. See below table for examples:</p>
+     * <table>
+     * <thead>
+     * <tr>
+     * <th align="center">State</th>
+     * <th align="center">Transition Cause</th>
+     * <th align="center">New State</th>
+     * <th align="center">Notes</th>
+     * </tr>
+     * </thead>
+     * <tbody>
+     * <tr>
+     * <td align="center">INACTIVE</td>
+     * <td align="center">Camera device finished AWB scan</td>
+     * <td align="center">CONVERGED</td>
+     * <td align="center">Values are already good, transient states are skipped by camera device.</td>
+     * </tr>
      * <tr>
      * <td align="center">LOCKED</td>
      * <td align="center">{@link CaptureRequest#CONTROL_AWB_LOCK android.control.awbLock} is OFF</td>
      * <td align="center">CONVERGED</td>
-     * <td align="center">Values good after unlock</td>
+     * <td align="center">Values good after unlock, transient states are skipped by camera device.</td>
      * </tr>
      * </tbody>
      * </table>
@@ -928,7 +1079,7 @@
 
     /**
      * <p>Overall mode of 3A control
-     * routines</p>
+     * routines.</p>
      * <p>High-level 3A control. When set to OFF, all 3A control
      * by the camera device is disabled. The application must set the fields for
      * capture parameters itself.</p>
@@ -956,9 +1107,9 @@
 
     /**
      * <p>Operation mode for edge
-     * enhancement</p>
+     * enhancement.</p>
      * <p>Edge/sharpness/detail enhancement. OFF means no
-     * enhancement will be applied by the HAL.</p>
+     * enhancement will be applied by the camera device.</p>
      * <p>FAST/HIGH_QUALITY both mean camera device determined enhancement
      * will be applied. HIGH_QUALITY mode indicates that the
      * camera device will use the highest-quality enhancement algorithms,
@@ -1236,7 +1387,7 @@
      * <p>Mode of operation for the noise reduction
      * algorithm</p>
      * <p>Noise filtering control. OFF means no noise reduction
-     * will be applied by the HAL.</p>
+     * will be applied by the camera device.</p>
      * <p>FAST/HIGH_QUALITY both mean camera device determined noise filtering
      * will be applied. HIGH_QUALITY mode indicates that the camera device
      * will use the highest-quality noise filtering algorithms,
@@ -1262,7 +1413,7 @@
      * before the FINAL buffer for frame 4. PARTIAL buffers may be returned
      * in any order relative to other frames, but all PARTIAL buffers for a given
      * capture must arrive before the FINAL buffer for that capture. This entry may
-     * only be used by the HAL if quirks.usePartialResult is set to 1.</p>
+     * only be used by the camera device if quirks.usePartialResult is set to 1.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * @hide
      */
@@ -1459,6 +1610,36 @@
             new Key<Float>("android.sensor.temperature", float.class);
 
     /**
+     * <p>A reference illumination source roughly matching the current scene
+     * illumination, which is used to describe the sensor color space
+     * transformations.</p>
+     * <p>The values in this tag correspond to the values defined for the
+     * EXIF LightSource tag. These illuminants are standard light sources
+     * that are often used for calibrating camera devices.</p>
+     * @see #SENSOR_REFERENCE_ILLUMINANT_DAYLIGHT
+     * @see #SENSOR_REFERENCE_ILLUMINANT_FLUORESCENT
+     * @see #SENSOR_REFERENCE_ILLUMINANT_TUNGSTEN
+     * @see #SENSOR_REFERENCE_ILLUMINANT_FLASH
+     * @see #SENSOR_REFERENCE_ILLUMINANT_FINE_WEATHER
+     * @see #SENSOR_REFERENCE_ILLUMINANT_CLOUDY_WEATHER
+     * @see #SENSOR_REFERENCE_ILLUMINANT_SHADE
+     * @see #SENSOR_REFERENCE_ILLUMINANT_DAYLIGHT_FLUORESCENT
+     * @see #SENSOR_REFERENCE_ILLUMINANT_DAY_WHITE_FLUORESCENT
+     * @see #SENSOR_REFERENCE_ILLUMINANT_COOL_WHITE_FLUORESCENT
+     * @see #SENSOR_REFERENCE_ILLUMINANT_WHITE_FLUORESCENT
+     * @see #SENSOR_REFERENCE_ILLUMINANT_STANDARD_A
+     * @see #SENSOR_REFERENCE_ILLUMINANT_STANDARD_B
+     * @see #SENSOR_REFERENCE_ILLUMINANT_STANDARD_C
+     * @see #SENSOR_REFERENCE_ILLUMINANT_D55
+     * @see #SENSOR_REFERENCE_ILLUMINANT_D65
+     * @see #SENSOR_REFERENCE_ILLUMINANT_D75
+     * @see #SENSOR_REFERENCE_ILLUMINANT_D50
+     * @see #SENSOR_REFERENCE_ILLUMINANT_ISO_STUDIO_TUNGSTEN
+     */
+    public static final Key<Integer> SENSOR_REFERENCE_ILLUMINANT =
+            new Key<Integer>("android.sensor.referenceIlluminant", int.class);
+
+    /**
      * <p>A per-device calibration transform matrix to be applied after the
      * color space transform when rendering the raw image buffer.</p>
      * <p>This matrix is expressed as a 3x3 matrix in row-major-order, and
@@ -1536,6 +1717,39 @@
             new Key<float[]>("android.sensor.profileToneCurve", float[].class);
 
     /**
+     * <p>The worst-case divergence between Bayer green channels.</p>
+     * <p>This value is an estimate of the worst case split between the
+     * Bayer green channels in the red and blue rows in the sensor color
+     * filter array.</p>
+     * <p>The green split is calculated as follows:</p>
+     * <ol>
+     * <li>A representative 5x5 pixel window W within the active
+     * sensor array is chosen.</li>
+     * <li>The arithmetic mean of the green channels from the red
+     * rows (mean_Gr) within W is computed.</li>
+     * <li>The arithmetic mean of the green channels from the blue
+     * rows (mean_Gb) within W is computed.</li>
+     * <li>The maximum ratio R of the two means is computed as follows:
+     * <code>R = max((mean_Gr + 1)/(mean_Gb + 1), (mean_Gb + 1)/(mean_Gr + 1))</code></li>
+     * </ol>
+     * <p>The ratio R is the green split divergence reported for this property,
+     * which represents how much the green channels differ in the mosaic
+     * pattern.  This value is typically used to determine the treatment of
+     * the green mosaic channels when demosaicing.</p>
+     * <p>The green split value can be roughly interpreted as follows:</p>
+     * <ul>
+     * <li>R &lt; 1.03 is a negligible split (&lt;3% divergence).</li>
+     * <li>1.20 &lt;= R &gt;= 1.03 will require some software
+     * correction to avoid demosaic errors (3-20% divergence).</li>
+     * <li>R &gt; 1.20 will require strong software correction to produce
+     * a usuable image (&gt;20% divergence).</li>
+     * </ul>
+     * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     */
+    public static final Key<Float> SENSOR_GREEN_SPLIT =
+            new Key<Float>("android.sensor.greenSplit", float.class);
+
+    /**
      * <p>When enabled, the sensor sends a test pattern instead of
      * doing a real exposure from the camera.</p>
      * <p>When a test pattern is enabled, all manual sensor controls specified
@@ -1583,7 +1797,6 @@
      * @see #SHADING_MODE_OFF
      * @see #SHADING_MODE_FAST
      * @see #SHADING_MODE_HIGH_QUALITY
-     * @hide
      */
     public static final Key<Integer> SHADING_MODE =
             new Key<Integer>("android.shading.mode", int.class);
@@ -1692,7 +1905,7 @@
 
     /**
      * <p>The best-fit color channel gains calculated
-     * by the HAL's statistics units for the current output frame</p>
+     * by the camera device's statistics units for the current output frame.</p>
      * <p>This may be different than the gains used for this frame,
      * since statistics processing on data from a new frame
      * typically completes after the transform has already been
@@ -1711,11 +1924,11 @@
 
     /**
      * <p>The best-fit color transform matrix estimate
-     * calculated by the HAL's statistics units for the current
-     * output frame</p>
-     * <p>The HAL must provide the estimate from its
+     * calculated by the camera device's statistics units for the current
+     * output frame.</p>
+     * <p>The camera device will provide the estimate from its
      * statistics unit on the white balance transforms to use
-     * for the next frame. These are the values the HAL believes
+     * for the next frame. These are the values the camera device believes
      * are the best fit for the current output frame. This may
      * be different than the transform used for this frame, since
      * statistics processing on data from a new frame typically
diff --git a/core/java/android/hardware/usb/UsbConfiguration.java b/core/java/android/hardware/usb/UsbConfiguration.java
new file mode 100644
index 0000000..92d6f75
--- /dev/null
+++ b/core/java/android/hardware/usb/UsbConfiguration.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.usb;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A class representing a configuration on a {@link UsbDevice}.
+ * A USB configuration can have one or more interfaces, each one providing a different
+ * piece of functionality, separate from the other interfaces.
+ * An interface will have one or more {@link UsbEndpoint}s, which are the
+ * channels by which the host transfers data with the device.
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about communicating with USB hardware, read the
+ * <a href="{@docRoot}guide/topics/usb/index.html">USB</a> developer guide.</p>
+ * </div>
+ */
+public class UsbConfiguration implements Parcelable {
+
+    private final int mId;
+    private final String mName;
+    private final int mAttributes;
+    private final int mMaxPower;
+    private Parcelable[] mInterfaces;
+
+    /**
+     * Mask for "self-powered" bit in the configuration's attributes.
+     * @see #getAttributes
+     */
+    public static final int ATTR_SELF_POWERED_MASK = 1 << 6;
+
+    /**
+     * Mask for "remote wakeup" bit in the configuration's attributes.
+     * @see #getAttributes
+     */
+    public static final int ATTR_REMOTE_WAKEUP_MASK = 1 << 5;
+
+    /**
+     * UsbConfiguration should only be instantiated by UsbService implementation
+     * @hide
+     */
+    public UsbConfiguration(int id, String name, int attributes, int maxPower) {
+        mId = id;
+        mName = name;
+        mAttributes = attributes;
+        mMaxPower = maxPower;
+    }
+
+    /**
+     * Returns the configuration's ID field.
+     * This is an integer that uniquely identifies the configuration on the device.
+     *
+     * @return the configuration's ID
+     */
+    public int getId() {
+        return mId;
+    }
+
+    /**
+     * Returns the configuration's name.
+     *
+     * @return the configuration's name
+     */
+    public String getName() {
+        return mName;
+    }
+
+    /**
+     * Returns the configuration's attributes field.
+     * This field contains a bit field with the following flags:
+     *
+     * Bit 7: always set to 1
+     * Bit 6: self-powered
+     * Bit 5: remote wakeup enabled
+     * Bit 0-4: reserved
+     * @see #ATTR_SELF_POWERED_MASK
+     * @see #ATTR_REMOTE_WAKEUP_MASK
+     * @return the configuration's attributes
+     */
+    public int getAttributes() {
+        return mAttributes;
+    }
+
+    /**
+     * Returns the configuration's max power consumption, in milliamps.
+     *
+     * @return the configuration's max power
+     */
+    public int getMaxPower() {
+        return mMaxPower * 2;
+    }
+
+    /**
+     * Returns the number of {@link UsbInterface}s this configuration contains.
+     *
+     * @return the number of endpoints
+     */
+    public int getInterfaceCount() {
+        return mInterfaces.length;
+    }
+
+    /**
+     * Returns the {@link UsbInterface} at the given index.
+     *
+     * @return the interface
+     */
+    public UsbInterface getInterface(int index) {
+        return (UsbInterface)mInterfaces[index];
+    }
+
+    /**
+     * Only used by UsbService implementation
+     * @hide
+     */
+    public void setInterfaces(Parcelable[] interfaces) {
+        mInterfaces = interfaces;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder("UsbConfiguration[mId=" + mId +
+                ",mName=" + mName + ",mAttributes=" + mAttributes +
+                ",mMaxPower=" + mMaxPower + ",mInterfaces=[");
+        for (int i = 0; i < mInterfaces.length; i++) {
+            builder.append("\n");
+            builder.append(mInterfaces[i].toString());
+        }
+        builder.append("]");
+        return builder.toString();
+    }
+
+    public static final Parcelable.Creator<UsbConfiguration> CREATOR =
+        new Parcelable.Creator<UsbConfiguration>() {
+        public UsbConfiguration createFromParcel(Parcel in) {
+            int id = in.readInt();
+            String name = in.readString();
+            int attributes = in.readInt();
+            int maxPower = in.readInt();
+            Parcelable[] interfaces = in.readParcelableArray(UsbInterface.class.getClassLoader());
+            UsbConfiguration configuration = new UsbConfiguration(id, name, attributes, maxPower);
+            configuration.setInterfaces(interfaces);
+            return configuration;
+        }
+
+        public UsbConfiguration[] newArray(int size) {
+            return new UsbConfiguration[size];
+        }
+    };
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeInt(mId);
+        parcel.writeString(mName);
+        parcel.writeInt(mAttributes);
+        parcel.writeInt(mMaxPower);
+        parcel.writeParcelableArray(mInterfaces, 0);
+   }
+}
diff --git a/core/java/android/hardware/usb/UsbDevice.java b/core/java/android/hardware/usb/UsbDevice.java
index b0ba9c1..d90e06e 100644
--- a/core/java/android/hardware/usb/UsbDevice.java
+++ b/core/java/android/hardware/usb/UsbDevice.java
@@ -50,7 +50,10 @@
     private final int mClass;
     private final int mSubclass;
     private final int mProtocol;
-    private final Parcelable[] mInterfaces;
+    private Parcelable[] mConfigurations;
+
+    // list of all interfaces on the device
+    private UsbInterface[] mInterfaces;
 
     /**
      * UsbDevice should only be instantiated by UsbService implementation
@@ -58,8 +61,7 @@
      */
     public UsbDevice(String name, int vendorId, int productId,
             int Class, int subClass, int protocol,
-            String manufacturerName, String productName, String serialNumber,
-            Parcelable[] interfaces) {
+            String manufacturerName, String productName, String serialNumber) {
         mName = name;
         mVendorId = vendorId;
         mProductId = productId;
@@ -69,7 +71,6 @@
         mManufacturerName = manufacturerName;
         mProductName = productName;
         mSerialNumber = serialNumber;
-        mInterfaces = interfaces;
     }
 
     /**
@@ -169,21 +170,74 @@
     }
 
     /**
+     * Returns the number of {@link UsbConfiguration}s this device contains.
+     *
+     * @return the number of configurations
+     */
+    public int getConfigurationCount() {
+        return mConfigurations.length;
+    }
+
+    /**
+     * Returns the {@link UsbConfiguration} at the given index.
+     *
+     * @return the configuration
+     */
+    public UsbConfiguration getConfiguration(int index) {
+        return (UsbConfiguration)mConfigurations[index];
+    }
+
+    private UsbInterface[] getInterfaceList() {
+        if (mInterfaces == null) {
+            int configurationCount = mConfigurations.length;
+            int interfaceCount = 0;
+            for (int i = 0; i < configurationCount; i++) {
+                UsbConfiguration configuration = (UsbConfiguration)mConfigurations[i];
+                interfaceCount += configuration.getInterfaceCount();
+            }
+
+            mInterfaces = new UsbInterface[interfaceCount];
+            int offset = 0;
+            for (int i = 0; i < configurationCount; i++) {
+                UsbConfiguration configuration = (UsbConfiguration)mConfigurations[i];
+                interfaceCount = configuration.getInterfaceCount();
+                for (int j = 0; j < interfaceCount; j++) {
+                    mInterfaces[offset++] = configuration.getInterface(j);
+                }
+            }
+        }
+
+        return mInterfaces;
+    }
+
+    /**
      * Returns the number of {@link UsbInterface}s this device contains.
+     * For devices with multiple configurations, you will probably want to use
+     * {@link UsbConfiguration#getInterfaceCount} instead.
      *
      * @return the number of interfaces
      */
     public int getInterfaceCount() {
-        return mInterfaces.length;
+        return getInterfaceList().length;
     }
 
     /**
      * Returns the {@link UsbInterface} at the given index.
+     * For devices with multiple configurations, you will probably want to use
+     * {@link UsbConfiguration#getInterface} instead.
      *
      * @return the interface
      */
     public UsbInterface getInterface(int index) {
-        return (UsbInterface)mInterfaces[index];
+        return getInterfaceList()[index];
+    }
+
+    /**
+     * Only used by UsbService implementation
+     * @hide
+     */
+    public void setConfigurations(Parcelable[] configuration) {
+        mConfigurations = configuration;
     }
 
     @Override
@@ -204,11 +258,17 @@
 
     @Override
     public String toString() {
-        return "UsbDevice[mName=" + mName + ",mVendorId=" + mVendorId +
-                ",mProductId=" + mProductId + ",mClass=" + mClass +
-                ",mSubclass=" + mSubclass + ",mProtocol=" + mProtocol +
+        StringBuilder builder = new StringBuilder("UsbDevice[mName=" + mName +
+                ",mVendorId=" + mVendorId + ",mProductId=" + mProductId +
+                ",mClass=" + mClass + ",mSubclass=" + mSubclass + ",mProtocol=" + mProtocol +
                 ",mManufacturerName=" + mManufacturerName + ",mProductName=" + mProductName +
-                ",mSerialNumber=" + mSerialNumber + ",mInterfaces=" + mInterfaces + "]";
+                ",mSerialNumber=" + mSerialNumber + ",mConfigurations=[");
+        for (int i = 0; i < mConfigurations.length; i++) {
+            builder.append("\n");
+            builder.append(mConfigurations[i].toString());
+        }
+        builder.append("]");
+        return builder.toString();
     }
 
     public static final Parcelable.Creator<UsbDevice> CREATOR =
@@ -223,9 +283,11 @@
             String manufacturerName = in.readString();
             String productName = in.readString();
             String serialNumber = in.readString();
-            Parcelable[] interfaces = in.readParcelableArray(UsbInterface.class.getClassLoader());
-            return new UsbDevice(name, vendorId, productId, clasz, subClass, protocol,
-                                 manufacturerName, productName, serialNumber, interfaces);
+            Parcelable[] configurations = in.readParcelableArray(UsbInterface.class.getClassLoader());
+            UsbDevice device = new UsbDevice(name, vendorId, productId, clasz, subClass, protocol,
+                                 manufacturerName, productName, serialNumber);
+            device.setConfigurations(configurations);
+            return device;
         }
 
         public UsbDevice[] newArray(int size) {
@@ -247,7 +309,7 @@
         parcel.writeString(mManufacturerName);
         parcel.writeString(mProductName);
         parcel.writeString(mSerialNumber);
-        parcel.writeParcelableArray(mInterfaces, 0);
+        parcel.writeParcelableArray(mConfigurations, 0);
    }
 
     public static int getDeviceId(String name) {
diff --git a/core/java/android/hardware/usb/UsbDeviceConnection.java b/core/java/android/hardware/usb/UsbDeviceConnection.java
index 389475f..6283951 100644
--- a/core/java/android/hardware/usb/UsbDeviceConnection.java
+++ b/core/java/android/hardware/usb/UsbDeviceConnection.java
@@ -101,6 +101,25 @@
     }
 
     /**
+     * Sets the current {@link android.hardware.usb.UsbInterface}.
+     * Used to select between two interfaces with the same ID but different alternate setting.
+     *
+     * @return true if the interface was successfully released
+     */
+    public boolean setInterface(UsbInterface intf) {
+        return native_set_interface(intf.getId(), intf.getAlternateSetting());
+    }
+
+    /**
+     * Sets the device's current {@link android.hardware.usb.UsbConfiguration}.
+     *
+     * @return true if the configuration was successfully set
+     */
+    public boolean setConfiguration(UsbConfiguration configuration) {
+        return native_set_configuration(configuration.getId());
+    }
+
+    /**
      * Performs a control transaction on endpoint zero for this device.
      * The direction of the transfer is determined by the request type.
      * If requestType & {@link UsbConstants#USB_ENDPOINT_DIR_MASK} is
@@ -236,6 +255,8 @@
     private native byte[] native_get_desc();
     private native boolean native_claim_interface(int interfaceID, boolean force);
     private native boolean native_release_interface(int interfaceID);
+    private native boolean native_set_interface(int interfaceID, int alternateSetting);
+    private native boolean native_set_configuration(int configurationID);
     private native int native_control_request(int requestType, int request, int value,
             int index, byte[] buffer, int offset, int length, int timeout);
     private native int native_bulk_request(int endpoint, byte[] buffer,
diff --git a/core/java/android/hardware/usb/UsbInterface.java b/core/java/android/hardware/usb/UsbInterface.java
index e94baa1..de01a88 100644
--- a/core/java/android/hardware/usb/UsbInterface.java
+++ b/core/java/android/hardware/usb/UsbInterface.java
@@ -35,27 +35,31 @@
 public class UsbInterface implements Parcelable {
 
     private final int mId;
+    private final int mAlternateSetting;
+    private final String mName;
     private final int mClass;
     private final int mSubclass;
     private final int mProtocol;
-    private final Parcelable[] mEndpoints;
+    private Parcelable[] mEndpoints;
 
     /**
      * UsbInterface should only be instantiated by UsbService implementation
      * @hide
      */
-    public UsbInterface(int id, int Class, int subClass, int protocol,
-            Parcelable[] endpoints) {
+    public UsbInterface(int id, int alternateSetting, String name,
+            int Class, int subClass, int protocol) {
         mId = id;
+        mAlternateSetting = alternateSetting;
+        mName = name;
         mClass = Class;
         mSubclass = subClass;
         mProtocol = protocol;
-        mEndpoints = endpoints;
     }
 
     /**
-     * Returns the interface's ID field.
-     * This is an integer that uniquely identifies the interface on the device.
+     * Returns the interface's bInterfaceNumber field.
+     * This is an integer that along with the alternate setting uniquely identifies
+     * the interface on the device.
      *
      * @return the interface's ID
      */
@@ -64,6 +68,28 @@
     }
 
     /**
+     * Returns the interface's bAlternateSetting field.
+     * This is an integer that along with the ID uniquely identifies
+     * the interface on the device.
+     * {@link UsbDeviceConnection#setInterface} can be used to switch between
+     * two interfaces with the same ID but different alternate setting.
+     *
+     * @return the interface's alternate setting
+     */
+    public int getAlternateSetting() {
+        return mAlternateSetting;
+    }
+
+    /**
+     * Returns the interface's name.
+     *
+     * @return the interface's name
+     */
+    public String getName() {
+        return mName;
+    }
+
+    /**
      * Returns the interface's class field.
      * Some useful constants for USB classes can be found in {@link UsbConstants}
      *
@@ -109,22 +135,42 @@
         return (UsbEndpoint)mEndpoints[index];
     }
 
+    /**
+     * Only used by UsbService implementation
+     * @hide
+     */
+    public void setEndpoints(Parcelable[] endpoints) {
+        mEndpoints = endpoints;
+    }
+
     @Override
     public String toString() {
-        return "UsbInterface[mId=" + mId + ",mClass=" + mClass +
+        StringBuilder builder = new StringBuilder("UsbInterface[mId=" + mId +
+                ",mAlternateSetting=" + mAlternateSetting +
+                ",mName=" + mName + ",mClass=" + mClass +
                 ",mSubclass=" + mSubclass + ",mProtocol=" + mProtocol +
-                ",mEndpoints=" + mEndpoints + "]";
+                ",mEndpoints=[");
+        for (int i = 0; i < mEndpoints.length; i++) {
+            builder.append("\n");
+            builder.append(mEndpoints[i].toString());
+        }
+        builder.append("]");
+        return builder.toString();
     }
 
     public static final Parcelable.Creator<UsbInterface> CREATOR =
         new Parcelable.Creator<UsbInterface>() {
         public UsbInterface createFromParcel(Parcel in) {
             int id = in.readInt();
+            int alternateSetting = in.readInt();
+            String name = in.readString();
             int Class = in.readInt();
             int subClass = in.readInt();
             int protocol = in.readInt();
             Parcelable[] endpoints = in.readParcelableArray(UsbEndpoint.class.getClassLoader());
-            return new UsbInterface(id, Class, subClass, protocol, endpoints);
+            UsbInterface intf = new UsbInterface(id, alternateSetting, name, Class, subClass, protocol);
+            intf.setEndpoints(endpoints);
+            return intf;
         }
 
         public UsbInterface[] newArray(int size) {
@@ -138,6 +184,8 @@
 
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeInt(mId);
+        parcel.writeInt(mAlternateSetting);
+        parcel.writeString(mName);
         parcel.writeInt(mClass);
         parcel.writeInt(mSubclass);
         parcel.writeInt(mProtocol);
diff --git a/core/java/android/net/CaptivePortalTracker.java b/core/java/android/net/CaptivePortalTracker.java
index 5b6f154..89c17c7 100644
--- a/core/java/android/net/CaptivePortalTracker.java
+++ b/core/java/android/net/CaptivePortalTracker.java
@@ -421,6 +421,13 @@
             case ConnectivityManager.TYPE_WIFI:
                 WifiInfo currentWifiInfo = mWifiManager.getConnectionInfo();
                 if (currentWifiInfo != null) {
+                    // NOTE: getSSID()'s behavior changed in API 17; before that, SSIDs were not
+                    // surrounded by double quotation marks (thus violating the Javadoc), but this
+                    // was changed to match the Javadoc in API 17. Since clients may have started
+                    // sanitizing the output of this method since API 17 was released, we should
+                    // not change it here as it would become impossible to tell whether the SSID is
+                    // simply being surrounded by quotes due to the API, or whether those quotes
+                    // are actually part of the SSID.
                     latencyBroadcast.putExtra(EXTRA_SSID, currentWifiInfo.getSSID());
                     latencyBroadcast.putExtra(EXTRA_BSSID, currentWifiInfo.getBSSID());
                 } else {
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 3a35cb9..5b2a29e 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -23,9 +23,14 @@
 import android.content.Context;
 import android.os.Binder;
 import android.os.Build.VERSION_CODES;
+import android.os.IBinder;
+import android.os.INetworkActivityListener;
+import android.os.INetworkManagementService;
 import android.os.Messenger;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.provider.Settings;
+import android.util.ArrayMap;
 
 import java.net.InetAddress;
 
@@ -76,7 +81,7 @@
 
     /**
      * Identical to {@link #CONNECTIVITY_ACTION} broadcast, but sent without any
-     * applicable {@link Settings.Secure#CONNECTIVITY_CHANGE_DELAY}.
+     * applicable {@link Settings.Global#CONNECTIVITY_CHANGE_DELAY}.
      *
      * @hide
      */
@@ -400,6 +405,10 @@
 
     private final IConnectivityManager mService;
 
+    private final String mPackageName;
+
+    private INetworkManagementService mNMService;
+
     /**
      * Tests if a given integer represents a valid network type.
      * @param networkType the type to be tested
@@ -811,7 +820,7 @@
     public boolean requestRouteToHostAddress(int networkType, InetAddress hostAddress) {
         byte[] address = hostAddress.getAddress();
         try {
-            return mService.requestRouteToHostAddress(networkType, address);
+            return mService.requestRouteToHostAddress(networkType, address, mPackageName);
         } catch (RemoteException e) {
             return false;
         }
@@ -905,10 +914,97 @@
     }
 
     /**
+     * Callback for use with {@link ConnectivityManager#registerNetworkActiveListener} to
+     * find out when the current network has gone in to a high power state.
+     */
+    public interface OnNetworkActiveListener {
+        /**
+         * Called on the main thread of the process to report that the current data network
+         * has become active, and it is now a good time to perform any pending network
+         * operations.  Note that this listener only tells you when the network becomes
+         * active; if at any other time you want to know whether it is active (and thus okay
+         * to initiate network traffic), you can retrieve its instantaneous state with
+         * {@link ConnectivityManager#isNetworkActive}.
+         */
+        public void onNetworkActive();
+    }
+
+    private INetworkManagementService getNetworkManagementService() {
+        synchronized (this) {
+            if (mNMService != null) {
+                return mNMService;
+            }
+            IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+            mNMService = INetworkManagementService.Stub.asInterface(b);
+            return mNMService;
+        }
+    }
+
+    private final ArrayMap<OnNetworkActiveListener, INetworkActivityListener>
+            mNetworkActivityListeners
+                    = new ArrayMap<OnNetworkActiveListener, INetworkActivityListener>();
+
+    /**
+     * Start listening to reports when the data network is active, meaning it is
+     * a good time to perform network traffic.  Use {@link #isNetworkActive()}
+     * to determine the current state of the network after registering the listener.
+     *
+     * @param l The listener to be told when the network is active.
+     */
+    public void registerNetworkActiveListener(final OnNetworkActiveListener l) {
+        INetworkActivityListener rl = new INetworkActivityListener.Stub() {
+            @Override
+            public void onNetworkActive() throws RemoteException {
+                l.onNetworkActive();
+            }
+        };
+
+        try {
+            getNetworkManagementService().registerNetworkActivityListener(rl);
+            mNetworkActivityListeners.put(l, rl);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Remove network active listener previously registered with
+     * {@link #registerNetworkActiveListener}.
+     *
+     * @param l Previously registered listener.
+     */
+    public void unregisterNetworkActiveListener(OnNetworkActiveListener l) {
+        INetworkActivityListener rl = mNetworkActivityListeners.get(l);
+        if (rl == null) {
+            throw new IllegalArgumentException("Listener not registered: " + l);
+        }
+        try {
+            getNetworkManagementService().unregisterNetworkActivityListener(rl);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Return whether the data network is currently active.  An active network means that
+     * it is currently in a high power state for performing data transmission.  On some
+     * types of networks, it may be expensive to move and stay in such a state, so it is
+     * more power efficient to batch network traffic together when the radio is already in
+     * this state.  This method tells you whether right now is currently a good time to
+     * initiate network traffic, as the network is already active.
+     */
+    public boolean isNetworkActive() {
+        try {
+            return getNetworkManagementService().isNetworkActive();
+        } catch (RemoteException e) {
+        }
+        return false;
+    }
+
+    /**
      * {@hide}
      */
-    public ConnectivityManager(IConnectivityManager service) {
+    public ConnectivityManager(IConnectivityManager service, String packageName) {
         mService = checkNotNull(service, "missing IConnectivityManager");
+        mPackageName = checkNotNull(packageName, "missing package name");
     }
 
     /** {@hide} */
@@ -1018,7 +1114,7 @@
 
     /**
      * Check if the device allows for tethering.  It may be disabled via
-     * {@code ro.tether.denied} system property, {@link Settings#TETHER_SUPPORTED} or
+     * {@code ro.tether.denied} system property, Settings.TETHER_SUPPORTED or
      * due to device configuration.
      *
      * @return a boolean - {@code true} indicating Tethering is supported.
@@ -1206,7 +1302,7 @@
      * doing something unusual like general internal filtering this may be useful.  On
      * a private network where the proxy is not accessible, you may break HTTP using this.
      *
-     * @param proxyProperties The a {@link ProxyProperites} object defining the new global
+     * @param p The a {@link ProxyProperties} object defining the new global
      *        HTTP proxy.  A {@code null} value will clear the global HTTP proxy.
      *
      * <p>This method requires the call to hold the permission
@@ -1359,7 +1455,7 @@
     /**
      * Supply the backend messenger for a network tracker
      *
-     * @param type NetworkType to set
+     * @param networkType NetworkType to set
      * @param messenger {@link Messenger}
      * {@hide}
      */
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index b3217eb..381a817 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -71,9 +71,9 @@
 
     int stopUsingNetworkFeature(int networkType, in String feature);
 
-    boolean requestRouteToHost(int networkType, int hostAddress);
+    boolean requestRouteToHost(int networkType, int hostAddress, String packageName);
 
-    boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress);
+    boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress, String packageName);
 
     boolean getMobileDataEnabled();
     void setMobileDataEnabled(boolean enabled);
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index a7aae2a..54d43d3 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -44,6 +44,8 @@
     public static final String IFACE_ALL = null;
     /** {@link #uid} value when UID details unavailable. */
     public static final int UID_ALL = -1;
+    /** {@link #tag} value matching any tag. */
+    public static final int TAG_ALL = -1;
     /** {@link #set} value when all sets combined. */
     public static final int SET_ALL = -1;
     /** {@link #set} value where background data is accounted. */
@@ -59,8 +61,9 @@
      * {@link SystemClock#elapsedRealtime()} timestamp when this data was
      * generated.
      */
-    private final long elapsedRealtime;
+    private long elapsedRealtime;
     private int size;
+    private int capacity;
     private String[] iface;
     private int[] uid;
     private int[] set;
@@ -152,20 +155,27 @@
     public NetworkStats(long elapsedRealtime, int initialSize) {
         this.elapsedRealtime = elapsedRealtime;
         this.size = 0;
-        this.iface = new String[initialSize];
-        this.uid = new int[initialSize];
-        this.set = new int[initialSize];
-        this.tag = new int[initialSize];
-        this.rxBytes = new long[initialSize];
-        this.rxPackets = new long[initialSize];
-        this.txBytes = new long[initialSize];
-        this.txPackets = new long[initialSize];
-        this.operations = new long[initialSize];
+        if (initialSize >= 0) {
+            this.capacity = initialSize;
+            this.iface = new String[initialSize];
+            this.uid = new int[initialSize];
+            this.set = new int[initialSize];
+            this.tag = new int[initialSize];
+            this.rxBytes = new long[initialSize];
+            this.rxPackets = new long[initialSize];
+            this.txBytes = new long[initialSize];
+            this.txPackets = new long[initialSize];
+            this.operations = new long[initialSize];
+        } else {
+            // Special case for use by NetworkStatsFactory to start out *really* empty.
+            this.capacity = 0;
+        }
     }
 
     public NetworkStats(Parcel parcel) {
         elapsedRealtime = parcel.readLong();
         size = parcel.readInt();
+        capacity = parcel.readInt();
         iface = parcel.createStringArray();
         uid = parcel.createIntArray();
         set = parcel.createIntArray();
@@ -181,6 +191,7 @@
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeLong(elapsedRealtime);
         dest.writeInt(size);
+        dest.writeInt(capacity);
         dest.writeStringArray(iface);
         dest.writeIntArray(uid);
         dest.writeIntArray(set);
@@ -222,8 +233,8 @@
      * object can be recycled across multiple calls.
      */
     public NetworkStats addValues(Entry entry) {
-        if (size >= this.iface.length) {
-            final int newLength = Math.max(iface.length, 10) * 3 / 2;
+        if (size >= capacity) {
+            final int newLength = Math.max(size, 10) * 3 / 2;
             iface = Arrays.copyOf(iface, newLength);
             uid = Arrays.copyOf(uid, newLength);
             set = Arrays.copyOf(set, newLength);
@@ -233,6 +244,7 @@
             txBytes = Arrays.copyOf(txBytes, newLength);
             txPackets = Arrays.copyOf(txPackets, newLength);
             operations = Arrays.copyOf(operations, newLength);
+            capacity = newLength;
         }
 
         iface[size] = entry.iface;
@@ -270,6 +282,10 @@
         return elapsedRealtime;
     }
 
+    public void setElapsedRealtime(long time) {
+        elapsedRealtime = time;
+    }
+
     /**
      * Return age of this {@link NetworkStats} object with respect to
      * {@link SystemClock#elapsedRealtime()}.
@@ -284,7 +300,7 @@
 
     @VisibleForTesting
     public int internalSize() {
-        return iface.length;
+        return capacity;
     }
 
     @Deprecated
@@ -491,6 +507,17 @@
     }
 
     /**
+     * Fast path for battery stats.
+     */
+    public long getTotalPackets() {
+        long total = 0;
+        for (int i = size-1; i >= 0; i--) {
+            total += rxPackets[i] + txPackets[i];
+        }
+        return total;
+    }
+
+    /**
      * Subtract the given {@link NetworkStats}, effectively leaving the delta
      * between two snapshots in time. Assumes that statistics rows collect over
      * time, and that none of them have disappeared.
@@ -507,8 +534,25 @@
      * If counters have rolled backwards, they are clamped to {@code 0} and
      * reported to the given {@link NonMonotonicObserver}.
      */
-    public static <C> NetworkStats subtract(
-            NetworkStats left, NetworkStats right, NonMonotonicObserver<C> observer, C cookie) {
+    public static <C> NetworkStats subtract(NetworkStats left, NetworkStats right,
+            NonMonotonicObserver<C> observer, C cookie) {
+        return subtract(left, right, observer, cookie, null);
+    }
+
+    /**
+     * Subtract the two given {@link NetworkStats} objects, returning the delta
+     * between two snapshots in time. Assumes that statistics rows collect over
+     * time, and that none of them have disappeared.
+     * <p>
+     * If counters have rolled backwards, they are clamped to {@code 0} and
+     * reported to the given {@link NonMonotonicObserver}.
+     * <p>
+     * If <var>recycle</var> is supplied, this NetworkStats object will be
+     * reused (and returned) as the result if it is large enough to contain
+     * the data.
+     */
+    public static <C> NetworkStats subtract(NetworkStats left, NetworkStats right,
+            NonMonotonicObserver<C> observer, C cookie, NetworkStats recycle) {
         long deltaRealtime = left.elapsedRealtime - right.elapsedRealtime;
         if (deltaRealtime < 0) {
             if (observer != null) {
@@ -519,7 +563,14 @@
 
         // result will have our rows, and elapsed time between snapshots
         final Entry entry = new Entry();
-        final NetworkStats result = new NetworkStats(deltaRealtime, left.size);
+        final NetworkStats result;
+        if (recycle != null && recycle.capacity >= left.size) {
+            result = recycle;
+            result.size = 0;
+            result.elapsedRealtime = deltaRealtime;
+        } else {
+            result = new NetworkStats(deltaRealtime, left.size);
+        }
         for (int i = 0; i < left.size; i++) {
             entry.iface = left.iface[i];
             entry.uid = left.uid[i];
diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java
index c3e1438..033332c 100644
--- a/core/java/android/net/Proxy.java
+++ b/core/java/android/net/Proxy.java
@@ -66,6 +66,19 @@
     /** {@hide} **/
     public static final String EXTRA_PROXY_INFO = "proxy";
 
+    /** @hide */
+    public static final int PROXY_VALID             = 0;
+    /** @hide */
+    public static final int PROXY_HOSTNAME_EMPTY    = 1;
+    /** @hide */
+    public static final int PROXY_HOSTNAME_INVALID  = 2;
+    /** @hide */
+    public static final int PROXY_PORT_EMPTY        = 3;
+    /** @hide */
+    public static final int PROXY_PORT_INVALID      = 4;
+    /** @hide */
+    public static final int PROXY_EXCLLIST_INVALID  = 5;
+
     private static ConnectivityManager sConnectivityManager = null;
 
     // Hostname / IP REGEX validation
@@ -77,8 +90,10 @@
 
     private static final Pattern HOSTNAME_PATTERN;
 
-    private static final String EXCLLIST_REGEXP = "$|^(.?" + NAME_IP_REGEX
-        + ")+(,(.?" + NAME_IP_REGEX + "))*$";
+    private static final String EXCL_REGEX =
+        "[a-zA-Z0-9*]+(\\-[a-zA-Z0-9*]+)*(\\.[a-zA-Z0-9*]+(\\-[a-zA-Z0-9*]+)*)*";
+
+    private static final String EXCLLIST_REGEXP = "^$|^" + EXCL_REGEX + "(," + EXCL_REGEX + ")*$";
 
     private static final Pattern EXCLLIST_PATTERN;
 
@@ -236,36 +251,27 @@
      * Validate syntax of hostname, port and exclusion list entries
      * {@hide}
      */
-    public static void validate(String hostname, String port, String exclList) {
+    public static int validate(String hostname, String port, String exclList) {
         Matcher match = HOSTNAME_PATTERN.matcher(hostname);
         Matcher listMatch = EXCLLIST_PATTERN.matcher(exclList);
 
-        if (!match.matches()) {
-            throw new IllegalArgumentException();
-        }
+        if (!match.matches()) return PROXY_HOSTNAME_INVALID;
 
-        if (!listMatch.matches()) {
-            throw new IllegalArgumentException();
-        }
+        if (!listMatch.matches()) return PROXY_EXCLLIST_INVALID;
 
-        if (hostname.length() > 0 && port.length() == 0) {
-            throw new IllegalArgumentException();
-        }
+        if (hostname.length() > 0 && port.length() == 0) return PROXY_PORT_EMPTY;
 
         if (port.length() > 0) {
-            if (hostname.length() == 0) {
-                throw new IllegalArgumentException();
-            }
+            if (hostname.length() == 0) return PROXY_HOSTNAME_EMPTY;
             int portVal = -1;
             try {
                 portVal = Integer.parseInt(port);
             } catch (NumberFormatException ex) {
-                throw new IllegalArgumentException();
+                return PROXY_PORT_INVALID;
             }
-            if (portVal <= 0 || portVal > 0xFFFF) {
-                throw new IllegalArgumentException();
-            }
+            if (portVal <= 0 || portVal > 0xFFFF) return PROXY_PORT_INVALID;
         }
+        return PROXY_VALID;
     }
 
     static class AndroidProxySelectorRoutePlanner
diff --git a/core/java/android/net/ProxyDataTracker.java b/core/java/android/net/ProxyDataTracker.java
index a7d287b..461e8b8 100644
--- a/core/java/android/net/ProxyDataTracker.java
+++ b/core/java/android/net/ProxyDataTracker.java
@@ -16,13 +16,24 @@
 
 package android.net;
 
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.os.Bundle;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.os.UserHandle;
 import android.util.Log;
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -31,27 +42,70 @@
  * {@hide}
  */
 public class ProxyDataTracker extends BaseNetworkStateTracker {
-    private static final String NETWORK_TYPE = "PROXY";
     private static final String TAG = "ProxyDataTracker";
+    private static final String NETWORK_TYPE = "PROXY";
 
     // TODO: investigate how to get these DNS addresses from the system.
     private static final String DNS1 = "8.8.8.8";
     private static final String DNS2 = "8.8.4.4";
     private static final String REASON_ENABLED = "enabled";
+    private static final String REASON_DISABLED = "disabled";
+    private static final String REASON_PROXY_DOWN = "proxy_down";
 
+    private static final int MSG_TEAR_DOWN_REQUEST = 1;
+    private static final int MSG_SETUP_REQUEST = 2;
+
+    private static final String PERMISSION_PROXY_STATUS_SENDER =
+            "android.permission.ACCESS_NETWORK_CONDITIONS";
+    private static final String ACTION_PROXY_STATUS_CHANGE =
+            "com.android.net.PROXY_STATUS_CHANGE";
+    private static final String KEY_IS_PROXY_AVAILABLE = "is_proxy_available";
+    private static final String KEY_REPLY_TO_MESSENGER_BINDER = "reply_to_messenger_binder";
+    private static final String KEY_REPLY_TO_MESSENGER_BINDER_BUNDLE =
+            "reply_to_messenger_binder_bundle";
+
+    private Handler mTarget;
+    private Messenger mProxyStatusService;
+    private AtomicBoolean mReconnectRequested = new AtomicBoolean(false);
+    private AtomicBoolean mIsProxyAvailable = new AtomicBoolean(false);
     private final AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
-    private final AtomicInteger mReconnectGeneration = new AtomicInteger(0);
+
+    private final BroadcastReceiver mProxyStatusServiceListener = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().equals(ACTION_PROXY_STATUS_CHANGE)) {
+                mIsProxyAvailable.set(intent.getBooleanExtra(KEY_IS_PROXY_AVAILABLE, false));
+                if (mIsProxyAvailable.get()) {
+                    Bundle bundle = intent.getBundleExtra(KEY_REPLY_TO_MESSENGER_BINDER_BUNDLE);
+                    if (bundle == null || bundle.getBinder(KEY_REPLY_TO_MESSENGER_BINDER) == null) {
+                        Log.e(TAG, "no messenger binder in the intent to send future requests");
+                        mIsProxyAvailable.set(false);
+                        return;
+                    }
+                    mProxyStatusService =
+                            new Messenger(bundle.getBinder(KEY_REPLY_TO_MESSENGER_BINDER));
+                    // If there is a pending reconnect request, do it now.
+                    if (mReconnectRequested.get()) {
+                        reconnect();
+                    }
+                } else {
+                    setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
+                            REASON_PROXY_DOWN, null);
+                }
+            } else {
+                Log.d(TAG, "Unrecognized broadcast intent");
+            }
+        }
+    };
 
     /**
      * Create a new ProxyDataTracker
      */
     public ProxyDataTracker() {
         mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_PROXY, 0, NETWORK_TYPE, "");
-        // TODO: update available state according to proxy state.
-        mNetworkInfo.setIsAvailable(true);
         mLinkProperties = new LinkProperties();
         mLinkCapabilities = new LinkCapabilities();
-
+        mNetworkInfo.setIsAvailable(true);
         try {
           mLinkProperties.addDns(InetAddress.getByName(DNS1));
           mLinkProperties.addDns(InetAddress.getByName(DNS2));
@@ -64,11 +118,31 @@
         throw new CloneNotSupportedException();
     }
 
+    @Override
+    public void startMonitoring(Context context, Handler target) {
+        mContext = context;
+        mTarget = target;
+        mContext.registerReceiver(mProxyStatusServiceListener,
+                new IntentFilter(ACTION_PROXY_STATUS_CHANGE),
+                PERMISSION_PROXY_STATUS_SENDER,
+                null);
+    }
+
     /**
      * Disable connectivity to the network.
      */
     public boolean teardown() {
-        // TODO: tell relevant service to tear down proxy.
+        setTeardownRequested(true);
+        mReconnectRequested.set(false);
+        try {
+            if (mIsProxyAvailable.get() && mProxyStatusService != null) {
+                mProxyStatusService.send(Message.obtain(null, MSG_TEAR_DOWN_REQUEST));
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Unable to connect to proxy status service", e);
+            return false;
+        }
+        setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, REASON_DISABLED, null);
         return true;
     }
 
@@ -76,16 +150,24 @@
      * Re-enable proxy data connectivity after a {@link #teardown()}.
      */
     public boolean reconnect() {
-        if (!isAvailable()) {
-            Log.w(TAG, "Reconnect requested even though network is disabled. Bailing.");
+        mReconnectRequested.set(true);
+        setTeardownRequested(false);
+        if (!mIsProxyAvailable.get()) {
+            Log.w(TAG, "Reconnect requested even though proxy service is not up. Bailing.");
             return false;
         }
-        setTeardownRequested(false);
-        mReconnectGeneration.incrementAndGet();
-        // TODO: tell relevant service to setup proxy. Set state to connected only if setup
-        // succeeds.
-        setDetailedState(NetworkInfo.DetailedState.CONNECTED, REASON_ENABLED, null);
+        setDetailedState(NetworkInfo.DetailedState.CONNECTING, REASON_ENABLED, null);
 
+        try {
+            mProxyStatusService.send(Message.obtain(null, MSG_SETUP_REQUEST));
+        } catch (RemoteException e) {
+            Log.e(TAG, "Unable to connect to proxy status service", e);
+            setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, REASON_PROXY_DOWN, null);
+            return false;
+        }
+        // We'll assume proxy is set up successfully. If not, a status change broadcast will be
+        // received afterwards to indicate any failure.
+        setDetailedState(NetworkInfo.DetailedState.CONNECTED, REASON_ENABLED, null);
         return true;
     }
 
@@ -116,7 +198,7 @@
     private void setDetailedState(NetworkInfo.DetailedState state, String reason,
             String extraInfo) {
         mNetworkInfo.setDetailedState(state, reason, extraInfo);
-        Message msg = getTargetHandler().obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
+        Message msg = mTarget.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
         msg.sendToTarget();
     }
 }
diff --git a/core/java/android/net/ProxyProperties.java b/core/java/android/net/ProxyProperties.java
index 54fc01d..50f45e8 100644
--- a/core/java/android/net/ProxyProperties.java
+++ b/core/java/android/net/ProxyProperties.java
@@ -140,13 +140,9 @@
 
     public boolean isValid() {
         if (!TextUtils.isEmpty(mPacFileUrl)) return true;
-        try {
-            Proxy.validate(mHost == null ? "" : mHost, mPort == 0 ? "" : Integer.toString(mPort),
-                    mExclusionList == null ? "" : mExclusionList);
-        } catch (IllegalArgumentException e) {
-            return false;
-        }
-        return true;
+        return Proxy.PROXY_VALID == Proxy.validate(mHost == null ? "" : mHost,
+                                                mPort == 0 ? "" : Integer.toString(mPort),
+                                                mExclusionList == null ? "" : mExclusionList);
     }
 
     public java.net.Proxy makeProxy() {
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index d7dc7f5..7385dff 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -151,9 +151,10 @@
     }
 
     /**
-     * Protect a socket from VPN connections. The socket will be bound to the
-     * current default network interface, so its traffic will not be forwarded
-     * through VPN. This method is useful if some connections need to be kept
+     * Protect a socket from VPN connections. After protecting, data sent
+     * through this socket will go directly to the underlying network,
+     * so its traffic will not be forwarded through the VPN.
+     * This method is useful if some connections need to be kept
      * outside of VPN. For example, a VPN tunnel should protect itself if its
      * destination is covered by VPN routes. Otherwise its outgoing packets
      * will be sent back to the VPN interface and cause an infinite loop. This
diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java
index 6840207..d8e8e2c 100644
--- a/core/java/android/net/nsd/NsdManager.java
+++ b/core/java/android/net/nsd/NsdManager.java
@@ -299,27 +299,36 @@
 
         @Override
         public void handleMessage(Message message) {
-            Object listener = getListener(message.arg2);
-            boolean listenerRemove = true;
             switch (message.what) {
                 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
                     mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
-                    break;
+                    return;
                 case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
                     mConnected.countDown();
-                    break;
+                    return;
                 case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
                     Log.e(TAG, "Channel lost");
+                    return;
+                default:
                     break;
+            }
+            Object listener = getListener(message.arg2);
+            if (listener == null) {
+                Log.d(TAG, "Stale key " + message.arg2);
+                return;
+            }
+            boolean listenerRemove = true;
+            NsdServiceInfo ns = getNsdService(message.arg2);
+            switch (message.what) {
                 case DISCOVER_SERVICES_STARTED:
-                    String s = ((NsdServiceInfo) message.obj).getServiceType();
+                    String s = getNsdServiceInfoType((NsdServiceInfo) message.obj);
                     ((DiscoveryListener) listener).onDiscoveryStarted(s);
                     // Keep listener until stop discovery
                     listenerRemove = false;
                     break;
                 case DISCOVER_SERVICES_FAILED:
-                    ((DiscoveryListener) listener).onStartDiscoveryFailed(
-                            getNsdService(message.arg2).getServiceType(), message.arg1);
+                    ((DiscoveryListener) listener).onStartDiscoveryFailed(getNsdServiceInfoType(ns),
+                            message.arg1);
                     break;
                 case SERVICE_FOUND:
                     ((DiscoveryListener) listener).onServiceFound((NsdServiceInfo) message.obj);
@@ -332,16 +341,14 @@
                     listenerRemove = false;
                     break;
                 case STOP_DISCOVERY_FAILED:
-                    ((DiscoveryListener) listener).onStopDiscoveryFailed(
-                            getNsdService(message.arg2).getServiceType(), message.arg1);
+                    ((DiscoveryListener) listener).onStopDiscoveryFailed(getNsdServiceInfoType(ns),
+                            message.arg1);
                     break;
                 case STOP_DISCOVERY_SUCCEEDED:
-                    ((DiscoveryListener) listener).onDiscoveryStopped(
-                            getNsdService(message.arg2).getServiceType());
+                    ((DiscoveryListener) listener).onDiscoveryStopped(getNsdServiceInfoType(ns));
                     break;
                 case REGISTER_SERVICE_FAILED:
-                    ((RegistrationListener) listener).onRegistrationFailed(
-                            getNsdService(message.arg2), message.arg1);
+                    ((RegistrationListener) listener).onRegistrationFailed(ns, message.arg1);
                     break;
                 case REGISTER_SERVICE_SUCCEEDED:
                     ((RegistrationListener) listener).onServiceRegistered(
@@ -350,16 +357,13 @@
                     listenerRemove = false;
                     break;
                 case UNREGISTER_SERVICE_FAILED:
-                    ((RegistrationListener) listener).onUnregistrationFailed(
-                            getNsdService(message.arg2), message.arg1);
+                    ((RegistrationListener) listener).onUnregistrationFailed(ns, message.arg1);
                     break;
                 case UNREGISTER_SERVICE_SUCCEEDED:
-                    ((RegistrationListener) listener).onServiceUnregistered(
-                            getNsdService(message.arg2));
+                    ((RegistrationListener) listener).onServiceUnregistered(ns);
                     break;
                 case RESOLVE_SERVICE_FAILED:
-                    ((ResolveListener) listener).onResolveFailed(
-                            getNsdService(message.arg2), message.arg1);
+                    ((ResolveListener) listener).onResolveFailed(ns, message.arg1);
                     break;
                 case RESOLVE_SERVICE_SUCCEEDED:
                     ((ResolveListener) listener).onServiceResolved((NsdServiceInfo) message.obj);
@@ -419,6 +423,11 @@
     }
 
 
+    private String getNsdServiceInfoType(NsdServiceInfo s) {
+        if (s == null) return "?";
+        return s.getServiceType();
+    }
+
     /**
      * Initialize AsyncChannel
      */
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index 10988c6..635a50f 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -48,6 +48,7 @@
     void setForegroundDispatch(in PendingIntent intent,
             in IntentFilter[] filters, in TechListParcel techLists);
     void setAppCallback(in IAppCallback callback);
+    void invokeBeam();
 
     void dispatch(in Tag tag);
 
diff --git a/core/java/android/nfc/NdefRecord.java b/core/java/android/nfc/NdefRecord.java
index de481cf..83d17ba 100644
--- a/core/java/android/nfc/NdefRecord.java
+++ b/core/java/android/nfc/NdefRecord.java
@@ -20,6 +20,7 @@
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
+
 import java.nio.BufferUnderflowException;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
@@ -474,6 +475,45 @@
     }
 
     /**
+     * Create a new NDEF record containing UTF-8 text data.<p>
+     *
+     * The caller can either specify the language code for the provided text,
+     * or otherwise the language code corresponding to the current default
+     * locale will be used.
+     *
+     * Reference specification: NFCForum-TS-RTD_Text_1.0
+     * @param languageCode The languageCode for the record. If locale is empty or null,
+     *                     the language code of the current default locale will be used.
+     * @param text   The text to be encoded in the record. Will be represented in UTF-8 format.
+     * @throws IllegalArgumentException if text is null
+     */
+    public static NdefRecord createTextRecord(String languageCode, String text) {
+        if (text == null) throw new NullPointerException("text is null");
+
+        byte[] textBytes = text.getBytes(StandardCharsets.UTF_8);
+
+        byte[] languageCodeBytes = null;
+        if (languageCode != null && !languageCode.isEmpty()) {
+            languageCodeBytes = languageCode.getBytes(StandardCharsets.US_ASCII);
+        } else {
+            languageCodeBytes = Locale.getDefault().getLanguage().
+                    getBytes(StandardCharsets.US_ASCII);
+        }
+        // We only have 6 bits to indicate ISO/IANA language code.
+        if (languageCodeBytes.length >= 64) {
+            throw new IllegalArgumentException("language code is too long, must be <64 bytes.");
+        }
+        ByteBuffer buffer = ByteBuffer.allocate(1 + languageCodeBytes.length + textBytes.length);
+
+        byte status = (byte) (languageCodeBytes.length & 0xFF);
+        buffer.put(status);
+        buffer.put(languageCodeBytes);
+        buffer.put(textBytes);
+
+        return new NdefRecord(TNF_WELL_KNOWN, RTD_TEXT, null, buffer.array());
+    }
+
+    /**
      * Construct an NDEF Record from its component fields.<p>
      * Recommend to use helpers such as {#createUri} or
      * {{@link #createExternal} where possible, since they perform
@@ -775,7 +815,7 @@
                     throw new FormatException("expected TNF_UNCHANGED in non-leading chunk");
                 } else if (!inChunk && tnf == NdefRecord.TNF_UNCHANGED) {
                     throw new FormatException("" +
-                    		"unexpected TNF_UNCHANGED in first chunk or unchunked record");
+                            "unexpected TNF_UNCHANGED in first chunk or unchunked record");
                 }
 
                 int typeLength = buffer.get() & 0xFF;
diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java
index 77c0234..8643f2e 100644
--- a/core/java/android/nfc/NfcActivityManager.java
+++ b/core/java/android/nfc/NfcActivityManager.java
@@ -18,6 +18,7 @@
 
 import android.app.Activity;
 import android.app.Application;
+import android.content.Intent;
 import android.net.Uri;
 import android.nfc.NfcAdapter.ReaderCallback;
 import android.os.Binder;
@@ -327,6 +328,7 @@
         NfcAdapter.CreateNdefMessageCallback ndefCallback;
         NfcAdapter.CreateBeamUrisCallback urisCallback;
         NdefMessage message;
+        Activity activity;
         Uri[] uris;
         int flags;
         synchronized (NfcActivityManager.this) {
@@ -338,6 +340,7 @@
             message = state.ndefMessage;
             uris = state.uris;
             flags = state.flags;
+            activity = state.activity;
         }
 
         // Make callbacks without lock
@@ -362,7 +365,13 @@
                 }
             }
         }
-
+        if (uris != null && uris.length > 0) {
+            for (Uri uri : uris) {
+                // Grant the NFC process permission to read these URIs
+                activity.grantUriPermission("com.android.nfc", uri,
+                        Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            }
+        }
         return new BeamShareData(message, uris, flags);
     }
 
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index e8b7437..96a3947 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -1249,6 +1249,45 @@
     }
 
     /**
+     * Manually invoke Android Beam to share data.
+     *
+     * <p>The Android Beam animation is normally only shown when two NFC-capable
+     * devices come into range.
+     * By calling this method, an Activity can invoke the Beam animation directly
+     * even if no other NFC device is in range yet. The Beam animation will then
+     * prompt the user to tap another NFC-capable device to complete the data
+     * transfer.
+     *
+     * <p>The main advantage of using this method is that it avoids the need for the
+     * user to tap the screen to complete the transfer, as this method already
+     * establishes the direction of the transfer and the consent of the user to
+     * share data. Callers are responsible for making sure that the user has
+     * consented to sharing data on NFC tap.
+     *
+     * <p>Note that to use this method, the passed in Activity must have already
+     * set data to share over Beam by using method calls such as
+     * {@link #setNdefPushMessageCallback} or
+     * {@link #setBeamPushUrisCallback}.
+     *
+     * @param activity the current foreground Activity that has registered data to share
+     * @return whether the Beam animation was successfully invoked
+     */
+    public boolean invokeBeam(Activity activity) {
+        if (activity == null) {
+            throw new NullPointerException("activity may not be null.");
+        }
+        enforceResumed(activity);
+        try {
+            sService.invokeBeam();
+            return true;
+        } catch (RemoteException e) {
+            Log.e(TAG, "invokeBeam: NFC process has died.");
+            attemptDeadServiceRecovery(e);
+            return false;
+        }
+    }
+
+    /**
      * Enable NDEF message push over NFC while this Activity is in the foreground.
      *
      * <p>You must explicitly call this method every time the activity is
diff --git a/core/java/android/nfc/tech/Ndef.java b/core/java/android/nfc/tech/Ndef.java
index 8240ea6..5852ce4 100644
--- a/core/java/android/nfc/tech/Ndef.java
+++ b/core/java/android/nfc/tech/Ndef.java
@@ -277,6 +277,8 @@
                     throw new TagLostException();
                 }
                 return msg;
+            } else if (!tagService.isPresent(serviceHandle)) {
+                throw new TagLostException();
             } else {
                 return null;
             }
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index 26e09b6..4f91d19 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -40,7 +40,7 @@
  * and does not constitute a generic threading framework. AsyncTasks should ideally be
  * used for short operations (a few seconds at the most.) If you need to keep threads
  * running for long periods of time, it is highly recommended you use the various APIs
- * provided by the <code>java.util.concurrent</code> pacakge such as {@link Executor},
+ * provided by the <code>java.util.concurrent</code> package such as {@link Executor},
  * {@link ThreadPoolExecutor} and {@link FutureTask}.</p>
  *
  * <p>An asynchronous task is defined by a computation that runs on a background thread and
diff --git a/core/java/android/os/BatteryProperties.java b/core/java/android/os/BatteryProperties.java
index 2d67264..8f5cf8b 100644
--- a/core/java/android/os/BatteryProperties.java
+++ b/core/java/android/os/BatteryProperties.java
@@ -15,9 +15,6 @@
 
 package android.os;
 
-import android.os.Parcel;
-import android.os.Parcelable;
-
 /**
  * {@hide}
  */
@@ -33,6 +30,22 @@
     public int batteryTemperature;
     public String batteryTechnology;
 
+    public BatteryProperties() {
+    }
+
+    public void set(BatteryProperties other) {
+        chargerAcOnline = other.chargerAcOnline;
+        chargerUsbOnline = other.chargerUsbOnline;
+        chargerWirelessOnline = other.chargerWirelessOnline;
+        batteryStatus = other.batteryStatus;
+        batteryHealth = other.batteryHealth;
+        batteryPresent = other.batteryPresent;
+        batteryLevel = other.batteryLevel;
+        batteryVoltage = other.batteryVoltage;
+        batteryTemperature = other.batteryTemperature;
+        batteryTechnology = other.batteryTechnology;
+    }
+
     /*
      * Parcel read/write code must be kept in sync with
      * frameworks/native/services/batteryservice/BatteryProperties.cpp
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index dfba208..0da77ea 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -217,11 +217,11 @@
          * Returns the total time in microseconds associated with this Timer for the
          * selected type of statistics.
          *
-         * @param batteryRealtime system realtime on  battery in microseconds
+         * @param elapsedRealtimeUs current elapsed realtime of system in microseconds
          * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
          * @return a time in microseconds
          */
-        public abstract long getTotalTimeLocked(long batteryRealtime, int which);
+        public abstract long getTotalTimeLocked(long elapsedRealtimeUs, int which);
 
         /**
          * Temporary for debugging.
@@ -295,14 +295,13 @@
         public abstract void noteVideoTurnedOffLocked(long elapsedRealtime);
         public abstract void noteActivityResumedLocked(long elapsedRealtime);
         public abstract void noteActivityPausedLocked(long elapsedRealtime);
-        public abstract long getWifiRunningTime(long batteryRealtime, int which);
-        public abstract long getFullWifiLockTime(long batteryRealtime, int which);
-        public abstract long getWifiScanTime(long batteryRealtime, int which);
-        public abstract long getWifiBatchedScanTime(int csphBin, long batteryRealtime, int which);
-        public abstract long getWifiMulticastTime(long batteryRealtime,
-                                                  int which);
-        public abstract long getAudioTurnedOnTime(long batteryRealtime, int which);
-        public abstract long getVideoTurnedOnTime(long batteryRealtime, int which);
+        public abstract long getWifiRunningTime(long elapsedRealtimeUs, int which);
+        public abstract long getFullWifiLockTime(long elapsedRealtimeUs, int which);
+        public abstract long getWifiScanTime(long elapsedRealtimeUs, int which);
+        public abstract long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which);
+        public abstract long getWifiMulticastTime(long elapsedRealtimeUs, int which);
+        public abstract long getAudioTurnedOnTime(long elapsedRealtimeUs, int which);
+        public abstract long getVideoTurnedOnTime(long elapsedRealtimeUs, int which);
         public abstract Timer getForegroundActivityTimer();
         public abstract Timer getVibratorOnTimer();
 
@@ -326,6 +325,8 @@
         public abstract boolean hasNetworkActivity();
         public abstract long getNetworkActivityBytes(int type, int which);
         public abstract long getNetworkActivityPackets(int type, int which);
+        public abstract long getMobileRadioActiveTime(int which);
+        public abstract int getMobileRadioActiveCount(int which);
 
         public static abstract class Sensor {
             /*
@@ -577,6 +578,9 @@
         // The wake lock that was acquired at this point.
         public HistoryTag wakelockTag;
 
+        // Kernel wakeup reason at this point.
+        public HistoryTag wakeReasonTag;
+
         public static final int EVENT_FLAG_START = 0x8000;
         public static final int EVENT_FLAG_FINISH = 0x4000;
 
@@ -588,8 +592,10 @@
         public static final int EVENT_FOREGROUND = 0x0002;
         // Event is about an application package that is at the top of the screen.
         public static final int EVENT_TOP = 0x0003;
+        // Event is about an application package that is at the top of the screen.
+        public static final int EVENT_SYNC = 0x0004;
         // Number of event types.
-        public static final int EVENT_COUNT = 0x0004;
+        public static final int EVENT_COUNT = 0x0005;
 
         public static final int EVENT_PROC_START = EVENT_PROC | EVENT_FLAG_START;
         public static final int EVENT_PROC_FINISH = EVENT_PROC | EVENT_FLAG_FINISH;
@@ -597,6 +603,8 @@
         public static final int EVENT_FOREGROUND_FINISH = EVENT_FOREGROUND | EVENT_FLAG_FINISH;
         public static final int EVENT_TOP_START = EVENT_TOP | EVENT_FLAG_START;
         public static final int EVENT_TOP_FINISH = EVENT_TOP | EVENT_FLAG_FINISH;
+        public static final int EVENT_SYNC_START = EVENT_SYNC | EVENT_FLAG_START;
+        public static final int EVENT_SYNC_FINISH = EVENT_SYNC | EVENT_FLAG_FINISH;
 
         // For CMD_EVENT.
         public int eventCode;
@@ -607,6 +615,7 @@
 
         // Pre-allocated objects.
         public final HistoryTag localWakelockTag = new HistoryTag();
+        public final HistoryTag localWakeReasonTag = new HistoryTag();
         public final HistoryTag localEventTag = new HistoryTag();
 
         public HistoryItem() {
@@ -640,6 +649,12 @@
             } else {
                 dest.writeInt(0);
             }
+            if (wakeReasonTag != null) {
+                dest.writeInt(1);
+                wakeReasonTag.writeToParcel(dest, flags);
+            } else {
+                dest.writeInt(0);
+            }
             dest.writeInt(eventCode);
             if (eventCode != EVENT_NONE) {
                 dest.writeInt(eventCode);
@@ -665,6 +680,12 @@
             } else {
                 wakelockTag = null;
             }
+            if (src.readInt() != 0) {
+                wakeReasonTag = localWakeReasonTag;
+                wakeReasonTag.readFromParcel(src);
+            } else {
+                wakeReasonTag = null;
+            }
             eventCode = src.readInt();
             if (eventCode != EVENT_NONE) {
                 eventTag = localEventTag;
@@ -684,6 +705,7 @@
             batteryVoltage = 0;
             states = 0;
             wakelockTag = null;
+            wakeReasonTag = null;
             eventCode = EVENT_NONE;
             eventTag = null;
         }
@@ -714,6 +736,12 @@
             } else {
                 wakelockTag = null;
             }
+            if (o.wakeReasonTag != null) {
+                wakeReasonTag = localWakeReasonTag;
+                wakeReasonTag.setTo(o.wakeReasonTag);
+            } else {
+                wakeReasonTag = null;
+            }
             eventCode = o.eventCode;
             if (o.eventTag != null) {
                 eventTag = localEventTag;
@@ -745,6 +773,14 @@
                     return false;
                 }
             }
+            if (wakeReasonTag != o.wakeReasonTag) {
+                if (wakeReasonTag == null || o.wakeReasonTag == null) {
+                    return false;
+                }
+                if (!wakeReasonTag.equals(o.wakeReasonTag)) {
+                    return false;
+                }
+            }
             if (eventTag != o.eventTag) {
                 if (eventTag == null || o.eventTag == null) {
                     return false;
@@ -825,8 +861,15 @@
      * 
      * {@hide}
      */
-    public abstract long getScreenOnTime(long batteryRealtime, int which);
+    public abstract long getScreenOnTime(long elapsedRealtimeUs, int which);
     
+    /**
+     * Returns the number of times the screen was turned on.
+     *
+     * {@hide}
+     */
+    public abstract int getScreenOnCount(int which);
+
     public static final int SCREEN_BRIGHTNESS_DARK = 0;
     public static final int SCREEN_BRIGHTNESS_DIM = 1;
     public static final int SCREEN_BRIGHTNESS_MEDIUM = 2;
@@ -850,7 +893,7 @@
      * {@hide}
      */
     public abstract long getScreenBrightnessTime(int brightnessBin,
-            long batteryRealtime, int which);
+            long elapsedRealtimeUs, int which);
 
     public abstract int getInputEventCount(int which);
     
@@ -860,16 +903,23 @@
      * 
      * {@hide}
      */
-    public abstract long getPhoneOnTime(long batteryRealtime, int which);
+    public abstract long getPhoneOnTime(long elapsedRealtimeUs, int which);
     
     /**
+     * Returns the number of times a phone call was activated.
+     *
+     * {@hide}
+     */
+    public abstract int getPhoneOnCount(int which);
+
+    /**
      * Returns the time in microseconds that the phone has been running with
      * the given signal strength.
      * 
      * {@hide}
      */
     public abstract long getPhoneSignalStrengthTime(int strengthBin,
-            long batteryRealtime, int which);
+            long elapsedRealtimeUs, int which);
 
     /**
      * Returns the time in microseconds that the phone has been trying to
@@ -878,7 +928,7 @@
      * {@hide}
      */
     public abstract long getPhoneSignalScanningTime(
-            long batteryRealtime, int which);
+            long elapsedRealtimeUs, int which);
 
     /**
      * Returns the number of times the phone has entered the given signal strength.
@@ -893,8 +943,30 @@
      *
      * {@hide}
      */
-    public abstract long getMobileRadioActiveTime(long batteryRealtime, int which);
+    public abstract long getMobileRadioActiveTime(long elapsedRealtimeUs, int which);
 
+    /**
+     * Returns the number of times that the mobile network has transitioned to the
+     * active state.
+     *
+     * {@hide}
+     */
+    public abstract int getMobileRadioActiveCount(int which);
+
+    /**
+     * Returns the time in microseconds that the mobile network has been active
+     * (in a high power state) but not being able to blame on an app.
+     *
+     * {@hide}
+     */
+    public abstract long getMobileRadioActiveUnknownTime(int which);
+
+    /**
+     * Return count of number of times radio was up that could not be blamed on apps.
+     *
+     * {@hide}
+     */
+    public abstract int getMobileRadioActiveUnknownCount(int which);
 
     public static final int DATA_CONNECTION_NONE = 0;
     public static final int DATA_CONNECTION_GPRS = 1;
@@ -929,7 +1001,7 @@
      * {@hide}
      */
     public abstract long getPhoneDataConnectionTime(int dataType,
-            long batteryRealtime, int which);
+            long elapsedRealtimeUs, int which);
 
     /**
      * Returns the number of times the phone has entered the given data
@@ -975,11 +1047,11 @@
     };
 
     public static final String[] HISTORY_EVENT_NAMES = new String[] {
-            "null", "proc", "fg", "top"
+            "null", "proc", "fg", "top", "sync"
     };
 
     public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
-            "Nl", "Pr", "Fg", "Tp"
+            "Enl", "Epr", "Efg", "Etp", "Esy"
     };
 
     /**
@@ -988,7 +1060,7 @@
      * 
      * {@hide}
      */
-    public abstract long getWifiOnTime(long batteryRealtime, int which);
+    public abstract long getWifiOnTime(long elapsedRealtimeUs, int which);
 
     /**
      * Returns the time in microseconds that wifi has been on and the driver has
@@ -996,7 +1068,7 @@
      *
      * {@hide}
      */
-    public abstract long getGlobalWifiRunningTime(long batteryRealtime, int which);
+    public abstract long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which);
 
     public static final int WIFI_STATE_OFF = 0;
     public static final int WIFI_STATE_OFF_SCANNING = 1;
@@ -1020,7 +1092,7 @@
      * {@hide}
      */
     public abstract long getWifiStateTime(int wifiState,
-            long batteryRealtime, int which);
+            long elapsedRealtimeUs, int which);
 
     /**
      * Returns the number of times that WiFi has entered the given state.
@@ -1035,7 +1107,7 @@
      * 
      * {@hide}
      */
-    public abstract long getBluetoothOnTime(long batteryRealtime, int which);
+    public abstract long getBluetoothOnTime(long elapsedRealtimeUs, int which);
     
     public abstract int getBluetoothPingCount();
 
@@ -1057,7 +1129,7 @@
      * {@hide}
      */
     public abstract long getBluetoothStateTime(int bluetoothState,
-            long batteryRealtime, int which);
+            long elapsedRealtimeUs, int which);
 
     /**
      * Returns the number of times that Bluetooth has entered the given active state.
@@ -1170,6 +1242,22 @@
     public abstract long computeBatteryRealtime(long curTime, int which);
 
     /**
+     * Returns the total, last, or current battery screen off uptime in microseconds.
+     *
+     * @param curTime the elapsed realtime in microseconds.
+     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
+     */
+    public abstract long computeBatteryScreenOffUptime(long curTime, int which);
+
+    /**
+     * Returns the total, last, or current battery screen off realtime in microseconds.
+     *
+     * @param curTime the current elapsed realtime in microseconds.
+     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
+     */
+    public abstract long computeBatteryScreenOffRealtime(long curTime, int which);
+
+    /**
      * Returns the total, last, or current uptime in microseconds.
      *
      * @param curTime the current elapsed realtime in microseconds.
@@ -1220,21 +1308,28 @@
         }
     }
 
-    private final static void formatTime(StringBuilder sb, long time) {
+    public final static void formatTime(StringBuilder sb, long time) {
         long sec = time / 100;
         formatTimeRaw(sb, sec);
         sb.append((time - (sec * 100)) * 10);
         sb.append("ms ");
     }
 
-    private final static void formatTimeMs(StringBuilder sb, long time) {
+    public final static void formatTimeMs(StringBuilder sb, long time) {
         long sec = time / 1000;
         formatTimeRaw(sb, sec);
         sb.append(time - (sec * 1000));
         sb.append("ms ");
     }
 
-    private final String formatRatioLocked(long num, long den) {
+    public final static void formatTimeMsNoSpace(StringBuilder sb, long time) {
+        long sec = time / 1000;
+        formatTimeRaw(sb, sec);
+        sb.append(time - (sec * 1000));
+        sb.append("ms");
+    }
+
+    public final String formatRatioLocked(long num, long den) {
         if (den == 0L) {
             return "--%";
         }
@@ -1244,7 +1339,7 @@
         return mFormatBuilder.toString();
     }
 
-    private final String formatBytesLocked(long bytes) {
+    final String formatBytesLocked(long bytes) {
         mFormatBuilder.setLength(0);
         
         if (bytes < BYTES_PER_KB) {
@@ -1261,10 +1356,10 @@
         }
     }
 
-    private static long computeWakeLock(Timer timer, long batteryRealtime, int which) {
+    private static long computeWakeLock(Timer timer, long elapsedRealtimeUs, int which) {
         if (timer != null) {
             // Convert from microseconds to milliseconds with rounding
-            long totalTimeMicros = timer.getTotalTimeLocked(batteryRealtime, which);
+            long totalTimeMicros = timer.getTotalTimeLocked(elapsedRealtimeUs, which);
             long totalTimeMillis = (totalTimeMicros + 500) / 1000;
             return totalTimeMillis;
         }
@@ -1275,17 +1370,17 @@
      *
      * @param sb a StringBuilder object.
      * @param timer a Timer object contining the wakelock times.
-     * @param batteryRealtime the current on-battery time in microseconds.
+     * @param elapsedRealtimeUs the current on-battery time in microseconds.
      * @param name the name of the wakelock.
      * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
      * @param linePrefix a String to be prepended to each line of output.
      * @return the line prefix
      */
     private static final String printWakeLock(StringBuilder sb, Timer timer,
-            long batteryRealtime, String name, int which, String linePrefix) {
+            long elapsedRealtimeUs, String name, int which, String linePrefix) {
         
         if (timer != null) {
-            long totalTimeMillis = computeWakeLock(timer, batteryRealtime, which);
+            long totalTimeMillis = computeWakeLock(timer, elapsedRealtimeUs, which);
             
             int count = timer.getCountLocked(which);
             if (totalTimeMillis != 0) {
@@ -1309,18 +1404,18 @@
      * 
      * @param sb a StringBuilder object.
      * @param timer a Timer object contining the wakelock times.
-     * @param now the current time in microseconds.
+     * @param elapsedRealtimeUs the current time in microseconds.
      * @param name the name of the wakelock.
      * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
      * @param linePrefix a String to be prepended to each line of output.
      * @return the line prefix
      */
-    private static final String printWakeLockCheckin(StringBuilder sb, Timer timer, long now,
-            String name, int which, String linePrefix) {
+    private static final String printWakeLockCheckin(StringBuilder sb, Timer timer,
+            long elapsedRealtimeUs, String name, int which, String linePrefix) {
         long totalTimeMicros = 0;
         int count = 0;
         if (timer != null) {
-            totalTimeMicros = timer.getTotalTimeLocked(now, which);
+            totalTimeMicros = timer.getTotalTimeLocked(elapsedRealtimeUs, which);
             count = timer.getCountLocked(which); 
         }
         sb.append(linePrefix);
@@ -1362,16 +1457,18 @@
         final long rawUptime = SystemClock.uptimeMillis() * 1000;
         final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
         final long batteryUptime = getBatteryUptime(rawUptime);
-        final long batteryRealtime = getBatteryRealtime(rawRealtime);
         final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
         final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
+        final long whichBatteryScreenOffUptime = computeBatteryScreenOffUptime(rawUptime, which);
+        final long whichBatteryScreenOffRealtime = computeBatteryScreenOffRealtime(rawRealtime,
+                which);
         final long totalRealtime = computeRealtime(rawRealtime, which);
         final long totalUptime = computeUptime(rawUptime, which);
-        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
-        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
-        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
-        final long wifiRunningTime = getGlobalWifiRunningTime(batteryRealtime, which);
-        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
+        final long screenOnTime = getScreenOnTime(rawRealtime, which);
+        final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
+        final long wifiOnTime = getWifiOnTime(rawRealtime, which);
+        final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
+        final long bluetoothOnTime = getBluetoothOnTime(rawRealtime, which);
        
         StringBuilder sb = new StringBuilder(128);
         
@@ -1385,7 +1482,8 @@
                 which == STATS_SINCE_CHARGED ? getStartCount() : "N/A",
                 whichBatteryRealtime / 1000, whichBatteryUptime / 1000,
                 totalRealtime / 1000, totalUptime / 1000,
-                getStartClockTime());
+                getStartClockTime(),
+                whichBatteryScreenOffRealtime / 1000, whichBatteryScreenOffUptime / 1000);
         
         // Calculate wakelock times across all uids.
         long fullWakeLockTimeTotal = 0;
@@ -1402,13 +1500,14 @@
                     
                     Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
                     if (fullWakeTimer != null) {
-                        fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(batteryRealtime, which);
+                        fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(rawRealtime,
+                                which);
                     }
 
                     Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
                     if (partialWakeTimer != null) {
                         partialWakeLockTimeTotal += partialWakeTimer.getTotalTimeLocked(
-                            batteryRealtime, which);
+                            rawRealtime, which);
                     }
                 }
             }
@@ -1434,23 +1533,23 @@
                 wifiRunningTime / 1000, bluetoothOnTime / 1000,
                 mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes,
                 fullWakeLockTimeTotal, partialWakeLockTimeTotal,
-                getInputEventCount(which), getMobileRadioActiveTime(batteryRealtime, which));
+                getInputEventCount(which), getMobileRadioActiveTime(rawRealtime, which));
         
         // Dump screen brightness stats
         Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
-            args[i] = getScreenBrightnessTime(i, batteryRealtime, which) / 1000;
+            args[i] = getScreenBrightnessTime(i, rawRealtime, which) / 1000;
         }
         dumpLine(pw, 0 /* uid */, category, SCREEN_BRIGHTNESS_DATA, args);
         
         // Dump signal strength stats
         args = new Object[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
-            args[i] = getPhoneSignalStrengthTime(i, batteryRealtime, which) / 1000;
+            args[i] = getPhoneSignalStrengthTime(i, rawRealtime, which) / 1000;
         }
         dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_TIME_DATA, args);
         dumpLine(pw, 0 /* uid */, category, SIGNAL_SCANNING_TIME_DATA,
-                getPhoneSignalScanningTime(batteryRealtime, which) / 1000);
+                getPhoneSignalScanningTime(rawRealtime, which) / 1000);
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
             args[i] = getPhoneSignalStrengthCount(i, which);
         }
@@ -1459,7 +1558,7 @@
         // Dump network type stats
         args = new Object[NUM_DATA_CONNECTION_TYPES];
         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
-            args[i] = getPhoneDataConnectionTime(i, batteryRealtime, which) / 1000;
+            args[i] = getPhoneDataConnectionTime(i, rawRealtime, which) / 1000;
         }
         dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_TIME_DATA, args);
         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
@@ -1470,7 +1569,7 @@
         // Dump wifi state stats
         args = new Object[NUM_WIFI_STATES];
         for (int i=0; i<NUM_WIFI_STATES; i++) {
-            args[i] = getWifiStateTime(i, batteryRealtime, which) / 1000;
+            args[i] = getWifiStateTime(i, rawRealtime, which) / 1000;
         }
         dumpLine(pw, 0 /* uid */, category, WIFI_STATE_TIME_DATA, args);
         for (int i=0; i<NUM_WIFI_STATES; i++) {
@@ -1481,7 +1580,7 @@
         // Dump bluetooth state stats
         args = new Object[NUM_BLUETOOTH_STATES];
         for (int i=0; i<NUM_BLUETOOTH_STATES; i++) {
-            args[i] = getBluetoothStateTime(i, batteryRealtime, which) / 1000;
+            args[i] = getBluetoothStateTime(i, rawRealtime, which) / 1000;
         }
         dumpLine(pw, 0 /* uid */, category, BLUETOOTH_STATE_TIME_DATA, args);
         for (int i=0; i<NUM_BLUETOOTH_STATES; i++) {
@@ -1510,7 +1609,7 @@
             if (kernelWakelocks.size() > 0) {
                 for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
                     sb.setLength(0);
-                    printWakeLockCheckin(sb, ent.getValue(), batteryRealtime, null, which, "");
+                    printWakeLockCheckin(sb, ent.getValue(), rawRealtime, null, which, "");
     
                     dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(), 
                             sb.toString());
@@ -1586,19 +1685,22 @@
             long wifiBytesTx = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
             long mobilePacketsRx = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
             long mobilePacketsTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
+            long mobileActiveTime = u.getMobileRadioActiveTime(which);
+            int mobileActiveCount = u.getMobileRadioActiveCount(which);
             long wifiPacketsRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
             long wifiPacketsTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
-            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
-            long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
-            long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
+            long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
+            long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
+            long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
 
             if (mobileBytesRx > 0 || mobileBytesTx > 0 || wifiBytesRx > 0 || wifiBytesTx > 0
                     || mobilePacketsRx > 0 || mobilePacketsTx > 0 || wifiPacketsRx > 0
-                    || wifiPacketsTx > 0) {
+                    || wifiPacketsTx > 0 || mobileActiveTime > 0 || mobileActiveCount > 0) {
                 dumpLine(pw, uid, category, NETWORK_DATA, mobileBytesRx, mobileBytesTx,
                         wifiBytesRx, wifiBytesTx,
                         mobilePacketsRx, mobilePacketsTx,
-                        wifiPacketsRx, wifiPacketsTx);
+                        wifiPacketsRx, wifiPacketsTx,
+                        mobileActiveTime, mobileActiveCount);
             }
 
             if (fullWifiLockOnTime != 0 || wifiScanTime != 0
@@ -1628,11 +1730,11 @@
                     String linePrefix = "";
                     sb.setLength(0);
                     linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL), 
-                            batteryRealtime, "f", which, linePrefix);
+                            rawRealtime, "f", which, linePrefix);
                     linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), 
-                            batteryRealtime, "p", which, linePrefix);
+                            rawRealtime, "p", which, linePrefix);
                     linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), 
-                            batteryRealtime, "w", which, linePrefix);
+                            rawRealtime, "w", which, linePrefix);
                     
                     // Only log if we had at lease one wakelock...
                     if (sb.length() > 0) {
@@ -1654,7 +1756,7 @@
                     Timer timer = se.getSensorTime();
                     if (timer != null) {
                         // Convert from microseconds to milliseconds with rounding
-                        long totalTime = (timer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
+                        long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
                         int count = timer.getCountLocked(which);
                         if (totalTime != 0) {
                             dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count);
@@ -1666,7 +1768,7 @@
             Timer vibTimer = u.getVibratorOnTimer();
             if (vibTimer != null) {
                 // Convert from microseconds to milliseconds with rounding
-                long totalTime = (vibTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
+                long totalTime = (vibTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
                 int count = vibTimer.getCountLocked(which);
                 if (totalTime != 0) {
                     dumpLine(pw, uid, category, VIBRATOR_DATA, totalTime, count);
@@ -1676,7 +1778,7 @@
             Timer fgTimer = u.getForegroundActivityTimer();
             if (fgTimer != null) {
                 // Convert from microseconds to milliseconds with rounding
-                long totalTime = (fgTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
+                long totalTime = (fgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
                 int count = fgTimer.getCountLocked(which);
                 if (totalTime != 0) {
                     dumpLine(pw, uid, category, FOREGROUND_DATA, totalTime, count);
@@ -1754,13 +1856,15 @@
         final long rawUptime = SystemClock.uptimeMillis() * 1000;
         final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
         final long batteryUptime = getBatteryUptime(rawUptime);
-        final long batteryRealtime = getBatteryRealtime(rawRealtime);
 
         final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
         final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
         final long totalRealtime = computeRealtime(rawRealtime, which);
         final long totalUptime = computeUptime(rawUptime, which);
-        
+        final long whichBatteryScreenOffUptime = computeBatteryScreenOffUptime(rawUptime, which);
+        final long whichBatteryScreenOffRealtime = computeBatteryScreenOffRealtime(rawRealtime,
+                which);
+
         StringBuilder sb = new StringBuilder(128);
         
         SparseArray<? extends Uid> uidStats = getUidStats();
@@ -1778,39 +1882,56 @@
         pw.println(sb.toString());
         sb.setLength(0);
         sb.append(prefix);
+                sb.append("  Time on battery screen off: ");
+                formatTimeMs(sb, whichBatteryScreenOffRealtime / 1000); sb.append("(");
+                sb.append(formatRatioLocked(whichBatteryScreenOffRealtime, totalRealtime));
+                sb.append(") realtime, ");
+                formatTimeMs(sb, whichBatteryScreenOffUptime / 1000);
+                sb.append("(");
+                sb.append(formatRatioLocked(whichBatteryScreenOffUptime, totalRealtime));
+                sb.append(") uptime");
+        pw.println(sb.toString());
+        sb.setLength(0);
+        sb.append(prefix);
                 sb.append("  Total run time: ");
                 formatTimeMs(sb, totalRealtime / 1000);
                 sb.append("realtime, ");
                 formatTimeMs(sb, totalUptime / 1000);
-                sb.append("uptime, ");
+                sb.append("uptime");
         pw.println(sb.toString());
         pw.print("  Start clock time: ");
         pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss", getStartClockTime()).toString());
 
-        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
-        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
-        final long wifiRunningTime = getGlobalWifiRunningTime(batteryRealtime, which);
-        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
-        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
+        final long screenOnTime = getScreenOnTime(rawRealtime, which);
+        final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
+        final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
+        final long wifiOnTime = getWifiOnTime(rawRealtime, which);
+        final long bluetoothOnTime = getBluetoothOnTime(rawRealtime, which);
         sb.setLength(0);
         sb.append(prefix);
                 sb.append("  Screen on: "); formatTimeMs(sb, screenOnTime / 1000);
                 sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime));
-                sb.append("), Input events: "); sb.append(getInputEventCount(which));
-                sb.append(", Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
-                sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
-                sb.append(")");
+                sb.append(") "); sb.append(getScreenOnCount(which));
+                sb.append("x, Input events: "); sb.append(getInputEventCount(which));
         pw.println(sb.toString());
+        if (phoneOnTime != 0) {
+            sb.setLength(0);
+            sb.append(prefix);
+                    sb.append("  Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
+                    sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
+                    sb.append(") "); sb.append(getPhoneOnCount(which));
+        }
         sb.setLength(0);
         sb.append(prefix);
-        sb.append("  Screen brightnesses: ");
+        sb.append("  Screen brightnesses:");
         boolean didOne = false;
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
-            final long time = getScreenBrightnessTime(i, batteryRealtime, which);
+            final long time = getScreenBrightnessTime(i, rawRealtime, which);
             if (time == 0) {
                 continue;
             }
-            if (didOne) sb.append(", ");
+            sb.append("\n    ");
+            sb.append(prefix);
             didOne = true;
             sb.append(SCREEN_BRIGHTNESS_NAMES[i]);
             sb.append(" ");
@@ -1819,58 +1940,13 @@
             sb.append(formatRatioLocked(time, screenOnTime));
             sb.append(")");
         }
-        if (!didOne) sb.append("No activity");
+        if (!didOne) sb.append(" (no activity)");
         pw.println(sb.toString());
         
         // Calculate wakelock times across all uids.
         long fullWakeLockTimeTotalMicros = 0;
         long partialWakeLockTimeTotalMicros = 0;
 
-        final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {
-            @Override
-            public int compare(TimerEntry lhs, TimerEntry rhs) {
-                long lhsTime = lhs.mTime;
-                long rhsTime = rhs.mTime;
-                if (lhsTime < rhsTime) {
-                    return 1;
-                }
-                if (lhsTime > rhsTime) {
-                    return -1;
-                }
-                return 0;
-            }
-        };
-
-        if (reqUid < 0) {
-            Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
-            if (kernelWakelocks.size() > 0) {
-                final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
-                for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
-                    BatteryStats.Timer timer = ent.getValue();
-                    long totalTimeMillis = computeWakeLock(timer, batteryRealtime, which);
-                    if (totalTimeMillis > 0) {
-                        timers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
-                    }
-                }
-                Collections.sort(timers, timerComparator);
-                for (int i=0; i<timers.size(); i++) {
-                    TimerEntry timer = timers.get(i);
-                    String linePrefix = ": ";
-                    sb.setLength(0);
-                    sb.append(prefix);
-                    sb.append("  Kernel Wake lock ");
-                    sb.append(timer.mName);
-                    linePrefix = printWakeLock(sb, timer.mTimer, batteryRealtime, null,
-                            which, linePrefix);
-                    if (!linePrefix.equals(": ")) {
-                        sb.append(" realtime");
-                        // Only print out wake locks that were held
-                        pw.println(sb.toString());
-                    }
-                }
-            }
-        }
-
         final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
 
         for (int iu = 0; iu < NU; iu++) {
@@ -1885,13 +1961,13 @@
                     Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
                     if (fullWakeTimer != null) {
                         fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked(
-                                batteryRealtime, which);
+                                rawRealtime, which);
                     }
 
                     Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
                     if (partialWakeTimer != null) {
                         long totalTimeMicros = partialWakeTimer.getTotalTimeLocked(
-                                batteryRealtime, which);
+                                rawRealtime, which);
                         if (totalTimeMicros > 0) {
                             if (reqUid < 0) {
                                 // Only show the ordered list of all wake
@@ -1916,34 +1992,38 @@
         long wifiRxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
         long wifiTxTotalPackets = getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
 
+        if (fullWakeLockTimeTotalMicros != 0) {
+            sb.setLength(0);
+            sb.append(prefix);
+                    sb.append("  Total full wakelock time: "); formatTimeMsNoSpace(sb,
+                            (fullWakeLockTimeTotalMicros + 500) / 1000);
+            pw.println(sb.toString());
+        }
+
+        if (partialWakeLockTimeTotalMicros != 0) {
+            sb.setLength(0);
+            sb.append(prefix);
+                    sb.append("  Total partial wakelock time: "); formatTimeMsNoSpace(sb,
+                            (partialWakeLockTimeTotalMicros + 500) / 1000);
+            pw.println(sb.toString());
+        }
+
         pw.print(prefix);
                 pw.print("  Mobile total received: "); pw.print(formatBytesLocked(mobileRxTotalBytes));
                 pw.print(", sent: "); pw.print(formatBytesLocked(mobileTxTotalBytes));
                 pw.print(" (packets received "); pw.print(mobileRxTotalPackets);
                 pw.print(", sent "); pw.print(mobileTxTotalPackets); pw.println(")");
-        pw.print(prefix);
-                pw.print("  Wi-Fi total received: "); pw.print(formatBytesLocked(wifiRxTotalBytes));
-                pw.print(", sent: "); pw.print(formatBytesLocked(wifiTxTotalBytes));
-                pw.print(" (packets received "); pw.print(wifiRxTotalPackets);
-                pw.print(", sent "); pw.print(wifiTxTotalPackets); pw.println(")");
-        sb.setLength(0);
-        sb.append(prefix);
-                sb.append("  Total full wakelock time: "); formatTimeMs(sb,
-                        (fullWakeLockTimeTotalMicros + 500) / 1000);
-                sb.append(", Total partial wakelock time: "); formatTimeMs(sb,
-                        (partialWakeLockTimeTotalMicros + 500) / 1000);
-        pw.println(sb.toString());
-        
         sb.setLength(0);
         sb.append(prefix);
         sb.append("  Signal levels:");
         didOne = false;
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
-            final long time = getPhoneSignalStrengthTime(i, batteryRealtime, which);
+            final long time = getPhoneSignalStrengthTime(i, rawRealtime, which);
             if (time == 0) {
                 continue;
             }
             sb.append("\n    ");
+            sb.append(prefix);
             didOne = true;
             sb.append(SignalStrength.SIGNAL_STRENGTH_NAMES[i]);
             sb.append(" ");
@@ -1960,7 +2040,7 @@
         sb.setLength(0);
         sb.append(prefix);
         sb.append("  Signal scanning time: ");
-        formatTimeMs(sb, getPhoneSignalScanningTime(batteryRealtime, which) / 1000);
+        formatTimeMsNoSpace(sb, getPhoneSignalScanningTime(rawRealtime, which) / 1000);
         pw.println(sb.toString());
 
         sb.setLength(0);
@@ -1968,11 +2048,12 @@
         sb.append("  Radio types:");
         didOne = false;
         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
-            final long time = getPhoneDataConnectionTime(i, batteryRealtime, which);
+            final long time = getPhoneDataConnectionTime(i, rawRealtime, which);
             if (time == 0) {
                 continue;
             }
             sb.append("\n    ");
+            sb.append(prefix);
             didOne = true;
             sb.append(DATA_CONNECTION_NAMES[i]);
             sb.append(" ");
@@ -1989,9 +2070,31 @@
         sb.setLength(0);
         sb.append(prefix);
         sb.append("  Mobile radio active time: ");
-        formatTimeMs(sb, getMobileRadioActiveTime(batteryRealtime, which) / 1000);
+        final long mobileActiveTime = getMobileRadioActiveTime(rawRealtime, which);
+        formatTimeMs(sb, mobileActiveTime / 1000);
+        sb.append("("); sb.append(formatRatioLocked(mobileActiveTime, whichBatteryRealtime));
+        sb.append(") "); sb.append(getMobileRadioActiveCount(which));
+        sb.append("x");
         pw.println(sb.toString());
 
+        final long mobileActiveUnknownTime = getMobileRadioActiveUnknownTime(which);
+        if (mobileActiveUnknownTime != 0) {
+            sb.setLength(0);
+            sb.append(prefix);
+            sb.append("  Mobile radio active unknown time: ");
+            formatTimeMs(sb, mobileActiveUnknownTime / 1000);
+            sb.append("(");
+            sb.append(formatRatioLocked(mobileActiveUnknownTime, whichBatteryRealtime));
+            sb.append(") "); sb.append(getMobileRadioActiveUnknownCount(which));
+            sb.append("x");
+            pw.println(sb.toString());
+        }
+
+        pw.print(prefix);
+                pw.print("  Wi-Fi total received: "); pw.print(formatBytesLocked(wifiRxTotalBytes));
+                pw.print(", sent: "); pw.print(formatBytesLocked(wifiTxTotalBytes));
+                pw.print(" (packets received "); pw.print(wifiRxTotalPackets);
+                pw.print(", sent "); pw.print(wifiTxTotalPackets); pw.println(")");
         sb.setLength(0);
         sb.append(prefix);
                 sb.append("  Wifi on: "); formatTimeMs(sb, wifiOnTime / 1000);
@@ -2006,7 +2109,7 @@
         sb.append("  Wifi states:");
         didOne = false;
         for (int i=0; i<NUM_WIFI_STATES; i++) {
-            final long time = getWifiStateTime(i, batteryRealtime, which);
+            final long time = getWifiStateTime(i, rawRealtime, which);
             if (time == 0) {
                 continue;
             }
@@ -2036,7 +2139,7 @@
         sb.append("  Bluetooth states:");
         didOne = false;
         for (int i=0; i<NUM_BLUETOOTH_STATES; i++) {
-            final long time = getBluetoothStateTime(i, batteryRealtime, which);
+            final long time = getBluetoothStateTime(i, rawRealtime, which);
             if (time == 0) {
                 continue;
             }
@@ -2128,7 +2231,8 @@
                         pw.println();
                         break;
                     case APP:
-                        pw.print(prefix); pw.print("    Uid "); pw.print(bs.uidObj.getUid());
+                        pw.print(prefix); pw.print("    Uid ");
+                        UserHandle.formatUid(pw, bs.uidObj.getUid());
                         pw.print(": "); printmAh(pw, bs.value); pw.println();
                         break;
                     case USER:
@@ -2148,6 +2252,81 @@
             pw.println();
         }
 
+        sippers = helper.getMobilemsppList();
+        if (sippers != null && sippers.size() > 0) {
+            pw.print(prefix); pw.println("  Per-app mobile ms per packet:");
+            long totalTime = 0;
+            for (int i=0; i<sippers.size(); i++) {
+                BatterySipper bs = sippers.get(i);
+                sb.setLength(0);
+                sb.append(prefix); sb.append("    Uid ");
+                UserHandle.formatUid(sb, bs.uidObj.getUid());
+                sb.append(": "); sb.append(BatteryStatsHelper.makemAh(bs.mobilemspp));
+                sb.append(" ("); sb.append(bs.mobileRxPackets+bs.mobileTxPackets);
+                sb.append(" packets over "); formatTimeMsNoSpace(sb, bs.mobileActive);
+                sb.append(") "); sb.append(bs.mobileActiveCount); sb.append("x");
+                pw.println(sb.toString());
+                totalTime += bs.mobileActive;
+            }
+            sb.setLength(0);
+            sb.append(prefix);
+            sb.append("    TOTAL TIME: ");
+            formatTimeMs(sb, totalTime);
+            sb.append("("); sb.append(formatRatioLocked(totalTime, whichBatteryRealtime));
+            sb.append(")");
+            pw.println(sb.toString());
+            pw.println();
+        }
+
+        final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {
+            @Override
+            public int compare(TimerEntry lhs, TimerEntry rhs) {
+                long lhsTime = lhs.mTime;
+                long rhsTime = rhs.mTime;
+                if (lhsTime < rhsTime) {
+                    return 1;
+                }
+                if (lhsTime > rhsTime) {
+                    return -1;
+                }
+                return 0;
+            }
+        };
+
+        if (reqUid < 0) {
+            Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
+            if (kernelWakelocks.size() > 0) {
+                final ArrayList<TimerEntry> ktimers = new ArrayList<TimerEntry>();
+                for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
+                    BatteryStats.Timer timer = ent.getValue();
+                    long totalTimeMillis = computeWakeLock(timer, rawRealtime, which);
+                    if (totalTimeMillis > 0) {
+                        ktimers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
+                    }
+                }
+                if (ktimers.size() > 0) {
+                    Collections.sort(ktimers, timerComparator);
+                    pw.print(prefix); pw.println("  All kernel wake locks:");
+                    for (int i=0; i<ktimers.size(); i++) {
+                        TimerEntry timer = ktimers.get(i);
+                        String linePrefix = ": ";
+                        sb.setLength(0);
+                        sb.append(prefix);
+                        sb.append("  Kernel Wake lock ");
+                        sb.append(timer.mName);
+                        linePrefix = printWakeLock(sb, timer.mTimer, rawRealtime, null,
+                                which, linePrefix);
+                        if (!linePrefix.equals(": ")) {
+                            sb.append(" realtime");
+                            // Only print out wake locks that were held
+                            pw.println(sb.toString());
+                        }
+                    }
+                    pw.println();
+                }
+            }
+        }
+
         if (timers.size() > 0) {
             Collections.sort(timers, timerComparator);
             pw.print(prefix); pw.println("  All partial wake locks:");
@@ -2158,7 +2337,7 @@
                 UserHandle.formatUid(sb, timer.mId);
                 sb.append(" ");
                 sb.append(timer.mName);
-                printWakeLock(sb, timer.mTimer, batteryRealtime, null, which, ": ");
+                printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": ");
                 sb.append(" realtime");
                 pw.println(sb.toString());
             }
@@ -2179,18 +2358,20 @@
             UserHandle.formatUid(pw, uid);
             pw.println(":");
             boolean uidActivity = false;
-            
+
             long mobileRxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
             long mobileTxBytes = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
             long wifiRxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
             long wifiTxBytes = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which);
             long mobileRxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which);
             long mobileTxPackets = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which);
+            long uidMobileActiveTime = u.getMobileRadioActiveTime(which);
+            int uidMobileActiveCount = u.getMobileRadioActiveCount(which);
             long wifiRxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which);
             long wifiTxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which);
-            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
-            long wifiScanTime = u.getWifiScanTime(batteryRealtime, which);
-            long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which);
+            long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which);
+            long wifiScanTime = u.getWifiScanTime(rawRealtime, which);
+            long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which);
 
             if (mobileRxBytes > 0 || mobileTxBytes > 0
                     || mobileRxPackets > 0 || mobileTxPackets > 0) {
@@ -2200,6 +2381,23 @@
                         pw.print(" sent (packets "); pw.print(mobileRxPackets);
                         pw.print(" received, "); pw.print(mobileTxPackets); pw.println(" sent)");
             }
+            if (uidMobileActiveTime > 0 || uidMobileActiveCount > 0) {
+                sb.setLength(0);
+                sb.append(prefix); sb.append("    Mobile radio active: ");
+                formatTimeMs(sb, uidMobileActiveTime / 1000);
+                sb.append("(");
+                sb.append(formatRatioLocked(uidMobileActiveTime, mobileActiveTime));
+                sb.append(") "); sb.append(uidMobileActiveCount); sb.append("x");
+                long packets = mobileRxPackets + mobileTxPackets;
+                if (packets == 0) {
+                    packets = 1;
+                }
+                sb.append(" @ ");
+                sb.append(BatteryStatsHelper.makemAh(uidMobileActiveTime / 1000 / (double)packets));
+                sb.append(" mspp");
+                pw.println(sb.toString());
+            }
+
             if (wifiRxBytes > 0 || wifiTxBytes > 0 || wifiRxPackets > 0 || wifiTxPackets > 0) {
                 pw.print(prefix); pw.print("    Wi-Fi network: ");
                         pw.print(formatBytesLocked(wifiRxBytes)); pw.print(" received, ");
@@ -2208,6 +2406,24 @@
                         pw.print(" received, "); pw.print(wifiTxPackets); pw.println(" sent)");
             }
 
+            if (fullWifiLockOnTime != 0 || wifiScanTime != 0
+                    || uidWifiRunningTime != 0) {
+                sb.setLength(0);
+                sb.append(prefix); sb.append("    Wifi Running: ");
+                        formatTimeMs(sb, uidWifiRunningTime / 1000);
+                        sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
+                                whichBatteryRealtime)); sb.append(")\n");
+                sb.append(prefix); sb.append("    Full Wifi Lock: "); 
+                        formatTimeMs(sb, fullWifiLockOnTime / 1000);
+                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
+                                whichBatteryRealtime)); sb.append(")\n");
+                sb.append(prefix); sb.append("    Wifi Scan: ");
+                        formatTimeMs(sb, wifiScanTime / 1000);
+                        sb.append("("); sb.append(formatRatioLocked(wifiScanTime,
+                                whichBatteryRealtime)); sb.append(")");
+                pw.println(sb.toString());
+            }
+
             if (u.hasUserActivity()) {
                 boolean hasData = false;
                 for (int i=0; i<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
@@ -2229,24 +2445,6 @@
                     pw.println(sb.toString());
                 }
             }
-            
-            if (fullWifiLockOnTime != 0 || wifiScanTime != 0
-                    || uidWifiRunningTime != 0) {
-                sb.setLength(0);
-                sb.append(prefix); sb.append("    Wifi Running: ");
-                        formatTimeMs(sb, uidWifiRunningTime / 1000);
-                        sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
-                                whichBatteryRealtime)); sb.append(")\n");
-                sb.append(prefix); sb.append("    Full Wifi Lock: "); 
-                        formatTimeMs(sb, fullWifiLockOnTime / 1000);
-                        sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
-                                whichBatteryRealtime)); sb.append(")\n");
-                sb.append(prefix); sb.append("    Wifi Scan: ");
-                        formatTimeMs(sb, wifiScanTime / 1000);
-                        sb.append("("); sb.append(formatRatioLocked(wifiScanTime,
-                                whichBatteryRealtime)); sb.append(")");
-                pw.println(sb.toString());
-            }
 
             Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
             if (wakelocks.size() > 0) {
@@ -2260,11 +2458,11 @@
                     sb.append(prefix);
                     sb.append("    Wake lock ");
                     sb.append(ent.getKey());
-                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime,
+                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), rawRealtime,
                             "full", which, linePrefix);
-                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime,
+                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), rawRealtime,
                             "partial", which, linePrefix);
-                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime,
+                    linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime,
                             "window", which, linePrefix);
                     if (!linePrefix.equals(": ")) {
                         sb.append(" realtime");
@@ -2274,11 +2472,11 @@
                         count++;
                     }
                     totalFull += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL),
-                            batteryRealtime, which);
+                            rawRealtime, which);
                     totalPartial += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL),
-                            batteryRealtime, which);
+                            rawRealtime, which);
                     totalWindow += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW),
-                            batteryRealtime, which);
+                            rawRealtime, which);
                 }
                 if (count > 1) {
                     if (totalFull != 0 || totalPartial != 0 || totalWindow != 0) {
@@ -2334,7 +2532,7 @@
                     if (timer != null) {
                         // Convert from microseconds to milliseconds with rounding
                         long totalTime = (timer.getTotalTimeLocked(
-                                batteryRealtime, which) + 500) / 1000;
+                                rawRealtime, which) + 500) / 1000;
                         int count = timer.getCountLocked(which);
                         //timer.logState();
                         if (totalTime != 0) {
@@ -2358,7 +2556,7 @@
             if (vibTimer != null) {
                 // Convert from microseconds to milliseconds with rounding
                 long totalTime = (vibTimer.getTotalTimeLocked(
-                        batteryRealtime, which) + 500) / 1000;
+                        rawRealtime, which) + 500) / 1000;
                 int count = vibTimer.getCountLocked(which);
                 //timer.logState();
                 if (totalTime != 0) {
@@ -2377,7 +2575,7 @@
             Timer fgTimer = u.getForegroundActivityTimer();
             if (fgTimer != null) {
                 // Convert from microseconds to milliseconds with rounding
-                long totalTime = (fgTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000;
+                long totalTime = (fgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
                 int count = fgTimer.getCountLocked(which);
                 if (totalTime != 0) {
                     sb.setLength(0);
@@ -2564,14 +2762,22 @@
         public void printNextItem(PrintWriter pw, HistoryItem rec, long now, boolean checkin) {
             if (!checkin) {
                 pw.print("  ");
-                TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
+                if (now >= 0) {
+                    TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
+                } else {
+                    TimeUtils.formatDuration(rec.time, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
+                }
                 pw.print(" (");
                 pw.print(rec.numReadInts);
                 pw.print(") ");
             } else {
                 if (lastTime < 0) {
-                    pw.print("@");
-                    pw.print(rec.time-now);
+                    if (now >= 0) {
+                        pw.print("@");
+                        pw.print(rec.time-now);
+                    } else {
+                        pw.print(rec.time);
+                    }
                 } else {
                     pw.print(rec.time-lastTime);
                 }
@@ -2695,6 +2901,18 @@
                 }
                 printBitDescriptions(pw, oldState, rec.states, rec.wakelockTag,
                         HISTORY_STATE_DESCRIPTIONS, !checkin);
+                if (rec.wakeReasonTag != null) {
+                    if (checkin) {
+                        pw.print(",Wr=");
+                        pw.print(rec.wakeReasonTag.poolIdx);
+                    } else {
+                        pw.print(" wake_reason=");
+                        pw.print(rec.wakeReasonTag.uid);
+                        pw.print(":\"");
+                        pw.print(rec.wakeReasonTag.string);
+                        pw.print("\"");
+                    }
+                }
                 if (rec.eventCode != HistoryItem.EVENT_NONE) {
                     pw.print(checkin ? "," : " ");
                     if ((rec.eventCode&HistoryItem.EVENT_FLAG_START) != 0) {
@@ -2755,108 +2973,130 @@
         pw.print(suffix);
     }
 
+    public static final int DUMP_UNPLUGGED_ONLY = 1<<0;
+    public static final int DUMP_CHARGED_ONLY = 1<<1;
+    public static final int DUMP_HISTORY_ONLY = 1<<2;
+    public static final int DUMP_INCLUDE_HISTORY = 1<<3;
+
     /**
      * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
      *
      * @param pw a Printer to receive the dump output.
      */
     @SuppressWarnings("unused")
-    public void dumpLocked(Context context, PrintWriter pw, boolean isUnpluggedOnly, int reqUid,
-            boolean historyOnly) {
+    public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
         prepareForDumpLocked();
 
-        long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
+        final boolean filtering =
+                (flags&(DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) != 0;
 
-        final HistoryItem rec = new HistoryItem();
-        final long historyTotalSize = getHistoryTotalSize();
-        final long historyUsedSize = getHistoryUsedSize();
-        if (startIteratingHistoryLocked()) {
-            try {
-                pw.print("Battery History (");
-                pw.print((100*historyUsedSize)/historyTotalSize);
-                pw.print("% used, ");
-                printSizeValue(pw, historyUsedSize);
-                pw.print(" used of ");
-                printSizeValue(pw, historyTotalSize);
-                pw.print(", ");
-                pw.print(getHistoryStringPoolSize());
-                pw.print(" strings using ");
-                printSizeValue(pw, getHistoryStringPoolBytes());
-                pw.println("):");
-                HistoryPrinter hprinter = new HistoryPrinter();
-                while (getNextHistoryLocked(rec)) {
-                    hprinter.printNextItem(pw, rec, now, false);
+        if ((flags&DUMP_HISTORY_ONLY) != 0 || !filtering) {
+            long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
+
+            final HistoryItem rec = new HistoryItem();
+            final long historyTotalSize = getHistoryTotalSize();
+            final long historyUsedSize = getHistoryUsedSize();
+            if (startIteratingHistoryLocked()) {
+                try {
+                    pw.print("Battery History (");
+                    pw.print((100*historyUsedSize)/historyTotalSize);
+                    pw.print("% used, ");
+                    printSizeValue(pw, historyUsedSize);
+                    pw.print(" used of ");
+                    printSizeValue(pw, historyTotalSize);
+                    pw.print(", ");
+                    pw.print(getHistoryStringPoolSize());
+                    pw.print(" strings using ");
+                    printSizeValue(pw, getHistoryStringPoolBytes());
+                    pw.println("):");
+                    HistoryPrinter hprinter = new HistoryPrinter();
+                    long lastTime = -1;
+                    while (getNextHistoryLocked(rec)) {
+                        lastTime = rec.time;
+                        if (rec.time >= histStart) {
+                            hprinter.printNextItem(pw, rec, histStart >= 0 ? -1 : now, false);
+                        }
+                    }
+                    if (histStart >= 0) {
+                        pw.print("  NEXT: "); pw.println(lastTime+1);
+                    }
+                    pw.println();
+                } finally {
+                    finishIteratingHistoryLocked();
                 }
-                pw.println();
-            } finally {
-                finishIteratingHistoryLocked();
+            }
+
+            if (startIteratingOldHistoryLocked()) {
+                try {
+                    pw.println("Old battery History:");
+                    HistoryPrinter hprinter = new HistoryPrinter();
+                    while (getNextOldHistoryLocked(rec)) {
+                        hprinter.printNextItem(pw, rec, now, false);
+                    }
+                    pw.println();
+                } finally {
+                    finishIteratingOldHistoryLocked();
+                }
             }
         }
 
-        if (startIteratingOldHistoryLocked()) {
-            try {
-                pw.println("Old battery History:");
-                HistoryPrinter hprinter = new HistoryPrinter();
-                while (getNextOldHistoryLocked(rec)) {
-                    hprinter.printNextItem(pw, rec, now, false);
-                }
-                pw.println();
-            } finally {
-                finishIteratingOldHistoryLocked();
-            }
-        }
-
-        if (historyOnly) {
+        if (filtering && (flags&(DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) == 0) {
             return;
         }
 
-        SparseArray<? extends Uid> uidStats = getUidStats();
-        final int NU = uidStats.size();
-        boolean didPid = false;
-        long nowRealtime = SystemClock.elapsedRealtime();
-        for (int i=0; i<NU; i++) {
-            Uid uid = uidStats.valueAt(i);
-            SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
-            if (pids != null) {
-                for (int j=0; j<pids.size(); j++) {
-                    Uid.Pid pid = pids.valueAt(j);
-                    if (!didPid) {
-                        pw.println("Per-PID Stats:");
-                        didPid = true;
+        if (!filtering) {
+            SparseArray<? extends Uid> uidStats = getUidStats();
+            final int NU = uidStats.size();
+            boolean didPid = false;
+            long nowRealtime = SystemClock.elapsedRealtime();
+            for (int i=0; i<NU; i++) {
+                Uid uid = uidStats.valueAt(i);
+                SparseArray<? extends Uid.Pid> pids = uid.getPidStats();
+                if (pids != null) {
+                    for (int j=0; j<pids.size(); j++) {
+                        Uid.Pid pid = pids.valueAt(j);
+                        if (!didPid) {
+                            pw.println("Per-PID Stats:");
+                            didPid = true;
+                        }
+                        long time = pid.mWakeSum + (pid.mWakeStart != 0
+                                ? (nowRealtime - pid.mWakeStart) : 0);
+                        pw.print("  PID "); pw.print(pids.keyAt(j));
+                                pw.print(" wake time: ");
+                                TimeUtils.formatDuration(time, pw);
+                                pw.println("");
                     }
-                    long time = pid.mWakeSum + (pid.mWakeStart != 0
-                            ? (nowRealtime - pid.mWakeStart) : 0);
-                    pw.print("  PID "); pw.print(pids.keyAt(j));
-                            pw.print(" wake time: ");
-                            TimeUtils.formatDuration(time, pw);
-                            pw.println("");
                 }
             }
-        }
-        if (didPid) {
-            pw.println("");
+            if (didPid) {
+                pw.println("");
+            }
         }
 
-        if (!isUnpluggedOnly) {
+        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
             pw.println("Statistics since last charge:");
             pw.println("  System starts: " + getStartCount()
                     + ", currently on battery: " + getIsOnBattery());
             dumpLocked(context, pw, "", STATS_SINCE_CHARGED, reqUid);
             pw.println("");
         }
-        pw.println("Statistics since last unplugged:");
-        dumpLocked(context, pw, "", STATS_SINCE_UNPLUGGED, reqUid);
+        if (!filtering || (flags&DUMP_UNPLUGGED_ONLY) != 0) {
+            pw.println("Statistics since last unplugged:");
+            dumpLocked(context, pw, "", STATS_SINCE_UNPLUGGED, reqUid);
+        }
     }
     
     @SuppressWarnings("unused")
-    public void dumpCheckinLocked(Context context,
-            PrintWriter pw, List<ApplicationInfo> apps, boolean isUnpluggedOnly,
-            boolean includeHistory, boolean historyOnly) {
+    public void dumpCheckinLocked(Context context, PrintWriter pw,
+            List<ApplicationInfo> apps, int flags, long histStart) {
         prepareForDumpLocked();
         
         long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
 
-        if (includeHistory || historyOnly) {
+        final boolean filtering =
+                (flags&(DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) != 0;
+
+        if ((flags&DUMP_INCLUDE_HISTORY) != 0 || (flags&DUMP_HISTORY_ONLY) != 0) {
             final HistoryItem rec = new HistoryItem();
             if (startIteratingHistoryLocked()) {
                 try {
@@ -2871,10 +3111,17 @@
                         pw.println();
                     }
                     HistoryPrinter hprinter = new HistoryPrinter();
+                    long lastTime = -1;
                     while (getNextHistoryLocked(rec)) {
-                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
-                        pw.print(HISTORY_DATA); pw.print(',');
-                        hprinter.printNextItem(pw, rec, now, true);
+                        lastTime = rec.time;
+                        if (rec.time >= histStart) {
+                            pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
+                            pw.print(HISTORY_DATA); pw.print(',');
+                            hprinter.printNextItem(pw, rec, histStart >= 0 ? -1 : now, true);
+                        }
+                    }
+                    if (histStart >= 0) {
+                        pw.print("NEXT: "); pw.println(lastTime+1);
                     }
                 } finally {
                     finishIteratingHistoryLocked();
@@ -2882,7 +3129,7 @@
             }
         }
 
-        if (historyOnly) {
+        if (filtering && (flags&(DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) == 0) {
             return;
         }
 
@@ -2913,11 +3160,10 @@
                 }
             }
         }
-        if (isUnpluggedOnly) {
-            dumpCheckinLocked(context, pw, STATS_SINCE_UNPLUGGED, -1);
-        }
-        else {
+        if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
             dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1);
+        }
+        if (!filtering || (flags&DUMP_UNPLUGGED_ONLY) != 0) {
             dumpCheckinLocked(context, pw, STATS_SINCE_UNPLUGGED, -1);
         }
     }
diff --git a/core/java/android/os/Broadcaster.java b/core/java/android/os/Broadcaster.java
index 96dc61a..70dcdd8 100644
--- a/core/java/android/os/Broadcaster.java
+++ b/core/java/android/os/Broadcaster.java
@@ -171,10 +171,10 @@
     public void broadcast(Message msg)
     {
         synchronized (this) {
-        	if (mReg == null) {
-        		return;
-        	}
-        	
+            if (mReg == null) {
+                return;
+            }
+            
             int senderWhat = msg.what;
             Registration start = mReg;
             Registration r = start;
diff --git a/core/java/android/os/INetworkActivityListener.aidl b/core/java/android/os/INetworkActivityListener.aidl
new file mode 100644
index 0000000..24e6e55
--- /dev/null
+++ b/core/java/android/os/INetworkActivityListener.aidl
@@ -0,0 +1,24 @@
+/* Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.os;
+
+/**
+ * @hide
+ */
+oneway interface INetworkActivityListener
+{
+    void onNetworkActive();
+}
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 21b8ae5..e6a4c5a 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -23,6 +23,7 @@
 import android.net.NetworkStats;
 import android.net.RouteInfo;
 import android.net.wifi.WifiConfiguration;
+import android.os.INetworkActivityListener;
 
 /**
  * @hide
@@ -306,14 +307,12 @@
      * reference-counting if an idletimer already exists for given
      * {@code iface}.
      *
-     * {@code label} usually represents the network type of {@code iface}.
-     * Caller should ensure that {@code label} for an {@code iface} remains the
-     * same for all calls to addIdleTimer.
+     * {@code type} is the type of the interface, such as TYPE_MOBILE.
      *
      * Every {@code addIdleTimer} should be paired with a
      * {@link removeIdleTimer} to cleanup when the network disconnects.
      */
-    void addIdleTimer(String iface, int timeout, String label);
+    void addIdleTimer(String iface, int timeout, int type);
 
     /**
      * Removes idletimer for an interface.
@@ -441,4 +440,19 @@
      * Determine whether the clatd (464xlat) service has been started
      */
     boolean isClatdStarted();
+
+    /**
+     * Start listening for mobile activity state changes.
+     */
+    void registerNetworkActivityListener(INetworkActivityListener listener);
+
+    /**
+     * Stop listening for mobile activity state changes.
+     */
+    void unregisterNetworkActivityListener(INetworkActivityListener listener);
+
+    /**
+     * Check whether the mobile radio is currently active.
+     */
+    boolean isNetworkActive();
 }
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 56176a4..069285a 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -25,8 +25,10 @@
 {
     // WARNING: The first four methods must remain the first three methods because their
     // transaction numbers must not change unless IPowerManager.cpp is also updated.
-    void acquireWakeLock(IBinder lock, int flags, String tag, String packageName, in WorkSource ws);
-    void acquireWakeLockWithUid(IBinder lock, int flags, String tag, String packageName, int uidtoblame);
+    void acquireWakeLock(IBinder lock, int flags, String tag, String packageName, in WorkSource ws,
+            String historyTag);
+    void acquireWakeLockWithUid(IBinder lock, int flags, String tag, String packageName,
+            int uidtoblame);
     void releaseWakeLock(IBinder lock, int flags);
     void updateWakeLockUids(IBinder lock, in int[] uids);
 
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index ff31130..6d7c9cf 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -149,7 +149,7 @@
                         + msg.callback + " what=" + msg.what);
             }
 
-            msg.recycle();
+            msg.recycleUnchecked();
         }
     }
 
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index 51203a48..d30bbc1 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -71,7 +71,14 @@
      */
     public Messenger replyTo;
 
-    /** If set message is in use */
+    /** If set message is in use.
+     * This flag is set when the message is enqueued and remains set while it
+     * is delivered and afterwards when it is recycled.  The flag is only cleared
+     * when a new message is created or obtained since that is the only time that
+     * applications are allowed to modify the contents of the message.
+     *
+     * It is an error to attempt to enqueue or recycle a message that is already in use.
+     */
     /*package*/ static final int FLAG_IN_USE = 1 << 0;
 
     /** If set message is asynchronous */
@@ -86,9 +93,9 @@
     
     /*package*/ Bundle data;
     
-    /*package*/ Handler target;     
+    /*package*/ Handler target;
     
-    /*package*/ Runnable callback;   
+    /*package*/ Runnable callback;
     
     // sometimes we store linked lists of these things
     /*package*/ Message next;
@@ -109,6 +116,7 @@
                 Message m = sPool;
                 sPool = m.next;
                 m.next = null;
+                m.flags = 0; // clear in-use flag
                 sPoolSize--;
                 return m;
             }
@@ -241,12 +249,38 @@
     }
 
     /**
-     * Return a Message instance to the global pool.  You MUST NOT touch
-     * the Message after calling this function -- it has effectively been
-     * freed.
+     * Return a Message instance to the global pool.
+     * <p>
+     * You MUST NOT touch the Message after calling this function because it has
+     * effectively been freed.  It is an error to recycle a message that is currently
+     * enqueued or that is in the process of being delivered to a Handler.
+     * </p>
      */
     public void recycle() {
-        clearForRecycle();
+        if (isInUse()) {
+            throw new IllegalStateException("This message cannot be recycled because it "
+                    + "is still in use.");
+        }
+        recycleUnchecked();
+    }
+
+    /**
+     * Recycles a Message that may be in-use.
+     * Used internally by the MessageQueue and Looper when disposing of queued Messages.
+     */
+    void recycleUnchecked() {
+        // Mark the message as in use while it remains in the recycled object pool.
+        // Clear out all other details.
+        flags = FLAG_IN_USE;
+        what = 0;
+        arg1 = 0;
+        arg2 = 0;
+        obj = null;
+        replyTo = null;
+        when = 0;
+        target = null;
+        callback = null;
+        data = null;
 
         synchronized (sPoolSync) {
             if (sPoolSize < MAX_POOL_SIZE) {
@@ -402,19 +436,6 @@
         }
     }
 
-    /*package*/ void clearForRecycle() {
-        flags = 0;
-        what = 0;
-        arg1 = 0;
-        arg2 = 0;
-        obj = null;
-        replyTo = null;
-        when = 0;
-        target = null;
-        callback = null;
-        data = null;
-    }
-
     /*package*/ boolean isInUse() {
         return ((flags & FLAG_IN_USE) == FLAG_IN_USE);
     }
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
index 7ca5d49..01a23ce 100644
--- a/core/java/android/os/MessageQueue.java
+++ b/core/java/android/os/MessageQueue.java
@@ -16,7 +16,6 @@
 
 package android.os;
 
-import android.util.AndroidRuntimeException;
 import android.util.Log;
 import android.util.Printer;
 
@@ -169,7 +168,6 @@
                         }
                         msg.next = null;
                         if (false) Log.v("MessageQueue", "Returning message: " + msg);
-                        msg.markInUse();
                         return msg;
                     }
                 } else {
@@ -233,7 +231,7 @@
 
     void quit(boolean safe) {
         if (!mQuitAllowed) {
-            throw new RuntimeException("Main thread not allowed to quit.");
+            throw new IllegalStateException("Main thread not allowed to quit.");
         }
 
         synchronized (this) {
@@ -259,6 +257,7 @@
         synchronized (this) {
             final int token = mNextBarrierToken++;
             final Message msg = Message.obtain();
+            msg.markInUse();
             msg.when = when;
             msg.arg1 = token;
 
@@ -303,7 +302,7 @@
                 mMessages = p.next;
                 needWake = mMessages == null || mMessages.target != null;
             }
-            p.recycle();
+            p.recycleUnchecked();
 
             // If the loop is quitting then it is already awake.
             // We can assume mPtr != 0 when mQuitting is false.
@@ -314,21 +313,23 @@
     }
 
     boolean enqueueMessage(Message msg, long when) {
-        if (msg.isInUse()) {
-            throw new AndroidRuntimeException(msg + " This message is already in use.");
-        }
         if (msg.target == null) {
-            throw new AndroidRuntimeException("Message must have a target.");
+            throw new IllegalArgumentException("Message must have a target.");
+        }
+        if (msg.isInUse()) {
+            throw new IllegalStateException(msg + " This message is already in use.");
         }
 
         synchronized (this) {
             if (mQuitting) {
-                RuntimeException e = new RuntimeException(
+                IllegalStateException e = new IllegalStateException(
                         msg.target + " sending message to a Handler on a dead thread");
                 Log.w("MessageQueue", e.getMessage(), e);
+                msg.recycle();
                 return false;
             }
 
+            msg.markInUse();
             msg.when = when;
             Message p = mMessages;
             boolean needWake;
@@ -424,7 +425,7 @@
                    && (object == null || p.obj == object)) {
                 Message n = p.next;
                 mMessages = n;
-                p.recycle();
+                p.recycleUnchecked();
                 p = n;
             }
 
@@ -435,7 +436,7 @@
                     if (n.target == h && n.what == what
                         && (object == null || n.obj == object)) {
                         Message nn = n.next;
-                        n.recycle();
+                        n.recycleUnchecked();
                         p.next = nn;
                         continue;
                     }
@@ -458,7 +459,7 @@
                    && (object == null || p.obj == object)) {
                 Message n = p.next;
                 mMessages = n;
-                p.recycle();
+                p.recycleUnchecked();
                 p = n;
             }
 
@@ -469,7 +470,7 @@
                     if (n.target == h && n.callback == r
                         && (object == null || n.obj == object)) {
                         Message nn = n.next;
-                        n.recycle();
+                        n.recycleUnchecked();
                         p.next = nn;
                         continue;
                     }
@@ -492,7 +493,7 @@
                     && (object == null || p.obj == object)) {
                 Message n = p.next;
                 mMessages = n;
-                p.recycle();
+                p.recycleUnchecked();
                 p = n;
             }
 
@@ -502,7 +503,7 @@
                 if (n != null) {
                     if (n.target == h && (object == null || n.obj == object)) {
                         Message nn = n.next;
-                        n.recycle();
+                        n.recycleUnchecked();
                         p.next = nn;
                         continue;
                     }
@@ -516,7 +517,7 @@
         Message p = mMessages;
         while (p != null) {
             Message n = p.next;
-            p.recycle();
+            p.recycleUnchecked();
             p = n;
         }
         mMessages = null;
@@ -544,7 +545,7 @@
                 do {
                     p = n;
                     n = p.next;
-                    p.recycle();
+                    p.recycleUnchecked();
                 } while (n != null);
             }
         }
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index c3f4807..8e0ff08 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -1460,10 +1460,11 @@
     }
 
     /**
-     * Use this function for customized exception handling.
-     * customized method call this method for all unknown case
-     * @param code exception code
-     * @param msg exception message
+     * Throw an exception with the given message. Not intended for use
+     * outside the Parcel class.
+     *
+     * @param code Used to determine which exception class to throw.
+     * @param msg The exception message.
      */
     public final void readException(int code, String msg) {
         switch (code) {
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 4d4c337..74ca3bb 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -662,6 +662,7 @@
         private boolean mRefCounted = true;
         private boolean mHeld;
         private WorkSource mWorkSource;
+        private String mHistoryTag;
 
         private final Runnable mReleaser = new Runnable() {
             public void run() {
@@ -748,7 +749,8 @@
                 // been explicitly released by the keyguard.
                 mHandler.removeCallbacks(mReleaser);
                 try {
-                    mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource);
+                    mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource,
+                            mHistoryTag);
                 } catch (RemoteException e) {
                 }
                 mHeld = true;
@@ -855,6 +857,11 @@
         }
 
         /** @hide */
+        public void setHistoryTag(String tag) {
+            mHistoryTag = tag;
+        }
+
+        /** @hide */
         public void setUnimportantForLogging(boolean state) {
             if (state) mFlags |= UNIMPORTANT_FOR_LOGGING;
             else mFlags &= ~UNIMPORTANT_FOR_LOGGING;
diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java
index 729c64b..672df6d 100644
--- a/core/java/android/os/SystemClock.java
+++ b/core/java/android/os/SystemClock.java
@@ -16,6 +16,9 @@
 
 package android.os;
 
+import android.app.IAlarmManager;
+import android.content.Context;
+import android.util.Slog;
 
 /**
  * Core timekeeping facilities.
@@ -89,6 +92,8 @@
  * </ul>
  */
 public final class SystemClock {
+    private static final String TAG = "SystemClock";
+
     /**
      * This class is uninstantiable.
      */
@@ -134,7 +139,23 @@
      *
      * @return if the clock was successfully set to the specified time.
      */
-    native public static boolean setCurrentTimeMillis(long millis);
+    public static boolean setCurrentTimeMillis(long millis) {
+        IBinder b = ServiceManager.getService(Context.ALARM_SERVICE);
+        IAlarmManager mgr = IAlarmManager.Stub.asInterface(b);
+        if (mgr == null) {
+            return false;
+        }
+
+        try {
+            return mgr.setTime(millis);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Unable to set RTC", e);
+        } catch (SecurityException e) {
+            Slog.e(TAG, "Unable to set RTC", e);
+        }
+
+        return false;
+    }
 
     /**
      * Returns milliseconds since boot, not counting time spent in deep sleep.
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 8f6dda1..1ec5cd5 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -164,11 +164,13 @@
 
     /**
      * Returns whether the system supports multiple users.
-     * @return true if multiple users can be created, false if it is a single user device.
+     * @return true if multiple users can be created by user, false if it is a single user device.
      * @hide
      */
     public static boolean supportsMultipleUsers() {
-        return getMaxSupportedUsers() > 1;
+        return getMaxSupportedUsers() > 1
+                && SystemProperties.getBoolean("fw.show_multiuserui",
+                Resources.getSystem().getBoolean(R.bool.config_enableMultiUserUI));
     }
 
     /**
@@ -601,6 +603,26 @@
     }
 
     /**
+     * Returns true if the user switcher should be shown, this will be if there
+     * are multiple users that aren't managed profiles.
+     * @hide
+     * @return true if user switcher should be shown.
+     */
+    public boolean isUserSwitcherEnabled() {
+        List<UserInfo> users = getUsers(true);
+        if (users == null) {
+           return false;
+        }
+        int switchableUserCount = 0;
+        for (UserInfo user : users) {
+            if (user.supportsSwitchTo()) {
+                ++switchableUserCount;
+            }
+        }
+        return switchableUserCount > 1;
+    }
+
+    /**
      * Returns a serial number on this device for a given userHandle. User handles can be recycled
      * when deleting and creating users, but serial numbers are not reused until the device is wiped.
      * @param userHandle
diff --git a/core/java/android/preference/GenericInflater.java b/core/java/android/preference/GenericInflater.java
index 3003290..7de7d1c 100644
--- a/core/java/android/preference/GenericInflater.java
+++ b/core/java/android/preference/GenericInflater.java
@@ -191,7 +191,7 @@
     public void setFactory(Factory<T> factory) {
         if (mFactorySet) {
             throw new IllegalStateException("" +
-            		"A factory has already been set on this inflater");
+                    "A factory has already been set on this inflater");
         }
         if (factory == null) {
             throw new NullPointerException("Given factory can not be null");
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 1b5cc68..11678a6 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -901,6 +901,14 @@
         public static final String PHOTO_THUMBNAIL_URI = "photo_thumb_uri";
 
         /**
+         * Flag that reflects whether the contact exists inside the default directory.
+         * Ie, whether the contact is designed to only be visible outside search.
+         *
+         * @hide
+         */
+        public static final String IN_DEFAULT_DIRECTORY = "in_default_directory";
+
+        /**
          * Flag that reflects the {@link Groups#GROUP_VISIBLE} state of any
          * {@link CommonDataKinds.GroupMembership} for this contact.
          */
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 76ada09..7777334 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -749,6 +749,14 @@
     public static final String ACTION_PRINT_SETTINGS =
             "android.settings.ACTION_PRINT_SETTINGS";
 
+    /**
+     * Activity Action: Show Zen Mode configuration settings.
+     *
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_ZEN_MODE_SETTINGS = "android.settings.ZEN_MODE_SETTINGS";
+
     // End of Intent actions for Settings
 
     /**
@@ -3352,21 +3360,29 @@
         public static final String INSTALL_NON_MARKET_APPS = Global.INSTALL_NON_MARKET_APPS;
 
         /**
-         * Comma-separated list of location providers that activities may access.
+         * Comma-separated list of location providers that activities may access. Do not rely on
+         * this value being present in settings.db or on ContentObserver notifications on the
+         * corresponding Uri.
          *
-         * @deprecated use {@link #LOCATION_MODE}
+         * @deprecated use {@link #LOCATION_MODE} and
+         * {@link LocationManager#MODE_CHANGED_ACTION} (or
+         * {@link LocationManager#PROVIDERS_CHANGED_ACTION})
          */
         @Deprecated
         public static final String LOCATION_PROVIDERS_ALLOWED = "location_providers_allowed";
 
         /**
          * The degree of location access enabled by the user.
-         * <p/>
+         * <p>
          * When used with {@link #putInt(ContentResolver, String, int)}, must be one of {@link
          * #LOCATION_MODE_HIGH_ACCURACY}, {@link #LOCATION_MODE_SENSORS_ONLY}, {@link
          * #LOCATION_MODE_BATTERY_SAVING}, or {@link #LOCATION_MODE_OFF}. When used with {@link
          * #getInt(ContentResolver, String)}, the caller must gracefully handle additional location
          * modes that might be added in the future.
+         * <p>
+         * Note: do not rely on this value being present in settings.db or on ContentObserver
+         * notifications for the corresponding Uri. Use {@link LocationManager#MODE_CHANGED_ACTION}
+         * to receive changes in this value.
          */
         public static final String LOCATION_MODE = "location_mode";
 
@@ -5254,6 +5270,12 @@
         public static final String SMS_SHORT_CODE_RULE = "sms_short_code_rule";
 
        /**
+        * Used to select TCP's default initial receiver window size in segments - defaults to a build config value
+        * @hide
+        */
+       public static final String TCP_DEFAULT_INIT_RWND = "tcp_default_init_rwnd";
+
+       /**
         * Used to disable Tethering on a device - defaults to true
         * @hide
         */
@@ -6076,6 +6098,35 @@
                 "lock_screen_show_notifications";
 
         /**
+         * Defines global zen mode.  One of ZEN_MODE_OFF, ZEN_MODE_LIMITED, ZEN_MODE_FULL.
+         *
+         * @hide
+         */
+        public static final String ZEN_MODE = "zen_mode";
+
+        /** @hide */ public static final int ZEN_MODE_OFF = 0;
+        /** @hide */ public static final int ZEN_MODE_LIMITED = 1;
+        /** @hide */ public static final int ZEN_MODE_FULL = 2;
+
+        /** @hide */ public static String zenModeToString(int mode) {
+            if (mode == ZEN_MODE_OFF) return "ZEN_MODE_OFF";
+            if (mode == ZEN_MODE_LIMITED) return "ZEN_MODE_LIMITED";
+            if (mode == ZEN_MODE_FULL) return "ZEN_MODE_FULL";
+            throw new IllegalArgumentException("Invalid zen mode: " + mode);
+        }
+
+        /**
+         * Defines global heads up toggle.  One of HEADS_UP_OFF, HEADS_UP_ON.
+         *
+         * @hide
+         */
+        public static final String HEADS_UP_NOTIFICATIONS_ENABLED =
+                "heads_up_notifications_enabled";
+
+        /** @hide */ public static final int HEADS_UP_OFF = 0;
+        /** @hide */ public static final int HEADS_UP_ON = 1;
+
+        /**
          * Settings to backup. This is here so that it's in the same place as the settings
          * keys and easy to update.
          *
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 1abb1d7..7647c22 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -300,6 +300,10 @@
     public void onDetachedFromWindow() {
     }
 
+    @Override
+    public void onWindowDismissed() {
+    }
+
     /** {@inheritDoc} */
     @Override
     public void onPanelClosed(int featureId, Menu menu) {
diff --git a/core/java/android/text/style/BackgroundColorSpan.java b/core/java/android/text/style/BackgroundColorSpan.java
index 580a369..cda8015 100644
--- a/core/java/android/text/style/BackgroundColorSpan.java
+++ b/core/java/android/text/style/BackgroundColorSpan.java
@@ -26,9 +26,9 @@
 
     private final int mColor;
 
-	public BackgroundColorSpan(int color) {
-		mColor = color;
-	}
+    public BackgroundColorSpan(int color) {
+        mColor = color;
+    }
 
     public BackgroundColorSpan(Parcel src) {
         mColor = src.readInt();
@@ -46,12 +46,12 @@
         dest.writeInt(mColor);
     }
 
-	public int getBackgroundColor() {
-		return mColor;
-	}
+    public int getBackgroundColor() {
+        return mColor;
+    }
 
-	@Override
-	public void updateDrawState(TextPaint ds) {
-		ds.bgColor = mColor;
-	}
+    @Override
+    public void updateDrawState(TextPaint ds) {
+        ds.bgColor = mColor;
+    }
 }
diff --git a/core/java/android/text/style/CharacterStyle.java b/core/java/android/text/style/CharacterStyle.java
index 14dfddd..5b95f1a 100644
--- a/core/java/android/text/style/CharacterStyle.java
+++ b/core/java/android/text/style/CharacterStyle.java
@@ -24,7 +24,7 @@
  * ones may just implement {@link UpdateAppearance}.
  */
 public abstract class CharacterStyle {
-	public abstract void updateDrawState(TextPaint tp);
+    public abstract void updateDrawState(TextPaint tp);
 
     /**
      * A given CharacterStyle can only applied to a single region of a given
diff --git a/core/java/android/text/style/ForegroundColorSpan.java b/core/java/android/text/style/ForegroundColorSpan.java
index 476124d..c9e09bd 100644
--- a/core/java/android/text/style/ForegroundColorSpan.java
+++ b/core/java/android/text/style/ForegroundColorSpan.java
@@ -26,9 +26,9 @@
 
     private final int mColor;
 
-	public ForegroundColorSpan(int color) {
-		mColor = color;
-	}
+    public ForegroundColorSpan(int color) {
+        mColor = color;
+    }
 
     public ForegroundColorSpan(Parcel src) {
         mColor = src.readInt();
@@ -46,12 +46,12 @@
         dest.writeInt(mColor);
     }
 
-	public int getForegroundColor() {
-		return mColor;
-	}
+    public int getForegroundColor() {
+        return mColor;
+    }
 
-	@Override
-	public void updateDrawState(TextPaint ds) {
-		ds.setColor(mColor);
-	}
+    @Override
+    public void updateDrawState(TextPaint ds) {
+        ds.setColor(mColor);
+    }
 }
diff --git a/core/java/android/text/style/MaskFilterSpan.java b/core/java/android/text/style/MaskFilterSpan.java
index 64ab0d8..2ff52a8f 100644
--- a/core/java/android/text/style/MaskFilterSpan.java
+++ b/core/java/android/text/style/MaskFilterSpan.java
@@ -21,18 +21,18 @@
 
 public class MaskFilterSpan extends CharacterStyle implements UpdateAppearance {
 
-	private MaskFilter mFilter;
+    private MaskFilter mFilter;
 
-	public MaskFilterSpan(MaskFilter filter) {
-		mFilter = filter;
-	}
+    public MaskFilterSpan(MaskFilter filter) {
+        mFilter = filter;
+    }
 
-	public MaskFilter getMaskFilter() {
-		return mFilter;
-	}
+    public MaskFilter getMaskFilter() {
+        return mFilter;
+    }
 
-	@Override
-	public void updateDrawState(TextPaint ds) {
-		ds.setMaskFilter(mFilter);
-	}
+    @Override
+    public void updateDrawState(TextPaint ds) {
+        ds.setMaskFilter(mFilter);
+    }
 }
diff --git a/core/java/android/text/style/MetricAffectingSpan.java b/core/java/android/text/style/MetricAffectingSpan.java
index a02b276..853ecc6 100644
--- a/core/java/android/text/style/MetricAffectingSpan.java
+++ b/core/java/android/text/style/MetricAffectingSpan.java
@@ -26,7 +26,7 @@
 extends CharacterStyle
 implements UpdateLayout {
 
-	public abstract void updateMeasureState(TextPaint p);
+    public abstract void updateMeasureState(TextPaint p);
 
     /**
      * Returns "this" for most MetricAffectingSpans, but for 
diff --git a/core/java/android/text/style/RasterizerSpan.java b/core/java/android/text/style/RasterizerSpan.java
index 75b5bcc..cae9640 100644
--- a/core/java/android/text/style/RasterizerSpan.java
+++ b/core/java/android/text/style/RasterizerSpan.java
@@ -21,18 +21,18 @@
 
 public class RasterizerSpan extends CharacterStyle implements UpdateAppearance {
 
-	private Rasterizer mRasterizer;
+    private Rasterizer mRasterizer;
 
-	public RasterizerSpan(Rasterizer r) {
-		mRasterizer = r;
-	}
+    public RasterizerSpan(Rasterizer r) {
+        mRasterizer = r;
+    }
 
-	public Rasterizer getRasterizer() {
-		return mRasterizer;
-	}
+    public Rasterizer getRasterizer() {
+        return mRasterizer;
+    }
 
-	@Override
-	public void updateDrawState(TextPaint ds) {
-		ds.setRasterizer(mRasterizer);
-	}
+    @Override
+    public void updateDrawState(TextPaint ds) {
+        ds.setRasterizer(mRasterizer);
+    }
 }
diff --git a/core/java/android/text/style/RelativeSizeSpan.java b/core/java/android/text/style/RelativeSizeSpan.java
index 9717362..632dbd4 100644
--- a/core/java/android/text/style/RelativeSizeSpan.java
+++ b/core/java/android/text/style/RelativeSizeSpan.java
@@ -23,11 +23,11 @@
 
 public class RelativeSizeSpan extends MetricAffectingSpan implements ParcelableSpan {
 
-	private final float mProportion;
+    private final float mProportion;
 
-	public RelativeSizeSpan(float proportion) {
-		mProportion = proportion;
-	}
+    public RelativeSizeSpan(float proportion) {
+        mProportion = proportion;
+    }
 
     public RelativeSizeSpan(Parcel src) {
         mProportion = src.readFloat();
@@ -45,17 +45,17 @@
         dest.writeFloat(mProportion);
     }
 
-	public float getSizeChange() {
-		return mProportion;
-	}
+    public float getSizeChange() {
+        return mProportion;
+    }
 
-	@Override
-	public void updateDrawState(TextPaint ds) {
-		ds.setTextSize(ds.getTextSize() * mProportion);
-	}
+    @Override
+    public void updateDrawState(TextPaint ds) {
+        ds.setTextSize(ds.getTextSize() * mProportion);
+    }
 
-	@Override
-	public void updateMeasureState(TextPaint ds) {
-		ds.setTextSize(ds.getTextSize() * mProportion);
-	}
+    @Override
+    public void updateMeasureState(TextPaint ds) {
+        ds.setTextSize(ds.getTextSize() * mProportion);
+    }
 }
diff --git a/core/java/android/text/style/ScaleXSpan.java b/core/java/android/text/style/ScaleXSpan.java
index 655064b..a22a5a1 100644
--- a/core/java/android/text/style/ScaleXSpan.java
+++ b/core/java/android/text/style/ScaleXSpan.java
@@ -23,11 +23,11 @@
 
 public class ScaleXSpan extends MetricAffectingSpan implements ParcelableSpan {
 
-	private final float mProportion;
+    private final float mProportion;
 
-	public ScaleXSpan(float proportion) {
-		mProportion = proportion;
-	}
+    public ScaleXSpan(float proportion) {
+        mProportion = proportion;
+    }
 
     public ScaleXSpan(Parcel src) {
         mProportion = src.readFloat();
@@ -45,17 +45,17 @@
         dest.writeFloat(mProportion);
     }
 
-	public float getScaleX() {
-		return mProportion;
-	}
+    public float getScaleX() {
+        return mProportion;
+    }
 
-	@Override
-	public void updateDrawState(TextPaint ds) {
-		ds.setTextScaleX(ds.getTextScaleX() * mProportion);
-	}
+    @Override
+    public void updateDrawState(TextPaint ds) {
+        ds.setTextScaleX(ds.getTextScaleX() * mProportion);
+    }
 
-	@Override
-	public void updateMeasureState(TextPaint ds) {
-		ds.setTextScaleX(ds.getTextScaleX() * mProportion);
-	}
+    @Override
+    public void updateMeasureState(TextPaint ds) {
+        ds.setTextScaleX(ds.getTextScaleX() * mProportion);
+    }
 }
diff --git a/core/java/android/text/style/StrikethroughSpan.java b/core/java/android/text/style/StrikethroughSpan.java
index b51363a..303e41574 100644
--- a/core/java/android/text/style/StrikethroughSpan.java
+++ b/core/java/android/text/style/StrikethroughSpan.java
@@ -40,8 +40,8 @@
     public void writeToParcel(Parcel dest, int flags) {
     }
 
-	@Override
-	public void updateDrawState(TextPaint ds) {
-		ds.setStrikeThruText(true);
-	}
+    @Override
+    public void updateDrawState(TextPaint ds) {
+        ds.setStrikeThruText(true);
+    }
 }
diff --git a/core/java/android/text/style/StyleSpan.java b/core/java/android/text/style/StyleSpan.java
index 8e6147c..b08f70e 100644
--- a/core/java/android/text/style/StyleSpan.java
+++ b/core/java/android/text/style/StyleSpan.java
@@ -33,17 +33,17 @@
  */
 public class StyleSpan extends MetricAffectingSpan implements ParcelableSpan {
 
-	private final int mStyle;
+    private final int mStyle;
 
-	/**
-	 * 
-	 * @param style An integer constant describing the style for this span. Examples
-	 * include bold, italic, and normal. Values are constants defined 
-	 * in {@link android.graphics.Typeface}.
-	 */
-	public StyleSpan(int style) {
-		mStyle = style;
-	}
+    /**
+     * 
+     * @param style An integer constant describing the style for this span. Examples
+     * include bold, italic, and normal. Values are constants defined 
+     * in {@link android.graphics.Typeface}.
+     */
+    public StyleSpan(int style) {
+        mStyle = style;
+    }
 
     public StyleSpan(Parcel src) {
         mStyle = src.readInt();
@@ -61,19 +61,19 @@
         dest.writeInt(mStyle);
     }
 
-	/**
-	 * Returns the style constant defined in {@link android.graphics.Typeface}. 
-	 */
-	public int getStyle() {
-		return mStyle;
-	}
+    /**
+     * Returns the style constant defined in {@link android.graphics.Typeface}. 
+     */
+    public int getStyle() {
+        return mStyle;
+    }
 
-	@Override
+    @Override
     public void updateDrawState(TextPaint ds) {
         apply(ds, mStyle);
     }
 
-	@Override
+    @Override
     public void updateMeasureState(TextPaint paint) {
         apply(paint, mStyle);
     }
diff --git a/core/java/android/text/style/UnderlineSpan.java b/core/java/android/text/style/UnderlineSpan.java
index b0cb0e8..80b2427 100644
--- a/core/java/android/text/style/UnderlineSpan.java
+++ b/core/java/android/text/style/UnderlineSpan.java
@@ -40,8 +40,8 @@
     public void writeToParcel(Parcel dest, int flags) {
     }
 
-	@Override
-	public void updateDrawState(TextPaint ds) {
-		ds.setUnderlineText(true);
-	}
+    @Override
+    public void updateDrawState(TextPaint ds) {
+        ds.setUnderlineText(true);
+    }
 }
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index fd3f9b3..c88b4c0 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -28,6 +28,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewOverlay;
+import android.view.WindowId;
 import android.widget.ListView;
 import android.widget.Spinner;
 
@@ -496,7 +497,8 @@
                             view = (start != null) ? start.view : null;
                         }
                         if (animator != null) {
-                            AnimationInfo info = new AnimationInfo(view, getName(), infoValues);
+                            AnimationInfo info = new AnimationInfo(view, getName(),
+                                    sceneRoot.getWindowId(), infoValues);
                             runningAnimators.put(animator, info);
                             mAnimators.add(animator);
                         }
@@ -552,8 +554,7 @@
         return false;
     }
 
-    /** @hide */
-    public static ArrayMap<Animator, AnimationInfo> getRunningAnimators() {
+    private static ArrayMap<Animator, AnimationInfo> getRunningAnimators() {
         ArrayMap<Animator, AnimationInfo> runningAnimators = sRunningAnimators.get();
         if (runningAnimators == null) {
             runningAnimators = new ArrayMap<Animator, AnimationInfo>();
@@ -1113,30 +1114,32 @@
                 }
             }
         }
-        TransitionValues values = new TransitionValues();
-        values.view = view;
-        if (start) {
-            captureStartValues(values);
-        } else {
-            captureEndValues(values);
-        }
-        if (start) {
-            if (!isListViewItem) {
-                mStartValues.viewValues.put(view, values);
-                if (id >= 0) {
-                    mStartValues.idValues.put((int) id, values);
-                }
+        if (view.getParent() instanceof ViewGroup) {
+            TransitionValues values = new TransitionValues();
+            values.view = view;
+            if (start) {
+                captureStartValues(values);
             } else {
-                mStartValues.itemIdValues.put(itemId, values);
+                captureEndValues(values);
             }
-        } else {
-            if (!isListViewItem) {
-                mEndValues.viewValues.put(view, values);
-                if (id >= 0) {
-                    mEndValues.idValues.put((int) id, values);
+            if (start) {
+                if (!isListViewItem) {
+                    mStartValues.viewValues.put(view, values);
+                    if (id >= 0) {
+                        mStartValues.idValues.put((int) id, values);
+                    }
+                } else {
+                    mStartValues.itemIdValues.put(itemId, values);
                 }
             } else {
-                mEndValues.itemIdValues.put(itemId, values);
+                if (!isListViewItem) {
+                    mEndValues.viewValues.put(view, values);
+                    if (id >= 0) {
+                        mEndValues.idValues.put((int) id, values);
+                    }
+                } else {
+                    mEndValues.itemIdValues.put(itemId, values);
+                }
             }
         }
         if (view instanceof ViewGroup) {
@@ -1198,13 +1201,17 @@
      *
      * @hide
      */
-    public void pause() {
+    public void pause(View sceneRoot) {
         if (!mEnded) {
             ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
             int numOldAnims = runningAnimators.size();
+            WindowId windowId = sceneRoot.getWindowId();
             for (int i = numOldAnims - 1; i >= 0; i--) {
-                Animator anim = runningAnimators.keyAt(i);
-                anim.pause();
+                AnimationInfo info = runningAnimators.valueAt(i);
+                if (info.view != null && windowId.equals(info.windowId)) {
+                    Animator anim = runningAnimators.keyAt(i);
+                    anim.pause();
+                }
             }
             if (mListeners != null && mListeners.size() > 0) {
                 ArrayList<TransitionListener> tmpListeners =
@@ -1225,14 +1232,18 @@
      *
      * @hide
      */
-    public void resume() {
+    public void resume(View sceneRoot) {
         if (mPaused) {
             if (!mEnded) {
                 ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
                 int numOldAnims = runningAnimators.size();
+                WindowId windowId = sceneRoot.getWindowId();
                 for (int i = numOldAnims - 1; i >= 0; i--) {
-                    Animator anim = runningAnimators.keyAt(i);
-                    anim.resume();
+                    AnimationInfo info = runningAnimators.valueAt(i);
+                    if (info.view != null && windowId.equals(info.windowId)) {
+                        Animator anim = runningAnimators.keyAt(i);
+                        anim.resume();
+                    }
                 }
                 if (mListeners != null && mListeners.size() > 0) {
                     ArrayList<TransitionListener> tmpListeners =
@@ -1643,11 +1654,13 @@
         public View view;
         String name;
         TransitionValues values;
+        WindowId windowId;
 
-        AnimationInfo(View view, String name, TransitionValues values) {
+        AnimationInfo(View view, String name, WindowId windowId, TransitionValues values) {
             this.view = view;
             this.name = name;
             this.values = values;
+            this.windowId = windowId;
         }
     }
 
diff --git a/core/java/android/transition/TransitionInflater.java b/core/java/android/transition/TransitionInflater.java
index 9fa554c..912f2ed 100644
--- a/core/java/android/transition/TransitionInflater.java
+++ b/core/java/android/transition/TransitionInflater.java
@@ -285,46 +285,27 @@
                 com.android.internal.R.styleable.TransitionManager);
         int transitionId = a.getResourceId(
                 com.android.internal.R.styleable.TransitionManager_transition, -1);
-        Scene fromScene = null, toScene = null;
         int fromId = a.getResourceId(
                 com.android.internal.R.styleable.TransitionManager_fromScene, -1);
-        if (fromId >= 0) fromScene = Scene.getSceneForLayout(sceneRoot, fromId, mContext);
+        Scene fromScene = (fromId < 0) ? null: Scene.getSceneForLayout(sceneRoot, fromId, mContext);
         int toId = a.getResourceId(
                 com.android.internal.R.styleable.TransitionManager_toScene, -1);
-        if (toId >= 0) toScene = Scene.getSceneForLayout(sceneRoot, toId, mContext);
-        String fromName = a.getString(
-                com.android.internal.R.styleable.TransitionManager_fromSceneName);
-        String toName = a.getString(
-                com.android.internal.R.styleable.TransitionManager_toSceneName);
+        Scene toScene = (toId < 0) ? null : Scene.getSceneForLayout(sceneRoot, toId, mContext);
+
         if (transitionId >= 0) {
             Transition transition = inflateTransition(transitionId);
             if (transition != null) {
-                if (fromScene != null) {
-                    boolean hasDest = false;
-                    if (toScene != null) {
-                        transitionManager.setTransition(fromScene, toScene, transition);
-                        hasDest = true;
-                    }
-
-                    if (!TextUtils.isEmpty(toName)) {
-                        transitionManager.setTransition(fromScene, toName, transition);
-                        hasDest = true;
-                    }
-
-                    if (!hasDest) {
-                        throw new RuntimeException("No matching toScene or toSceneName for given " +
-                                "fromScene for transition ID " + transitionId);
-                    }
-                } else if (toId >= 0) {
-                    transitionManager.setTransition(toScene, transition);
-                }
-                if (fromName != null) {
-                    if (toScene != null) {
-                        transitionManager.setTransition(fromName, toScene, transition);
-                    } else {
-                        throw new RuntimeException("No matching toScene for given fromSceneName " +
+                if (fromScene == null) {
+                    if (toScene == null) {
+                        throw new RuntimeException("No matching fromScene or toScene " +
                                 "for transition ID " + transitionId);
+                    } else {
+                        transitionManager.setTransition(toScene, transition);
                     }
+                } else if (toScene == null) {
+                    transitionManager.setExitTransition(fromScene, transition);
+                } else {
+                    transitionManager.setTransition(fromScene, toScene, transition);
                 }
             }
         }
diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java
index 0106f7fb..1614d34 100644
--- a/core/java/android/transition/TransitionManager.java
+++ b/core/java/android/transition/TransitionManager.java
@@ -70,12 +70,9 @@
     private static final String[] EMPTY_STRINGS = new String[0];
 
     ArrayMap<Scene, Transition> mSceneTransitions = new ArrayMap<Scene, Transition>();
+    ArrayMap<Scene, Transition> mExitSceneTransitions = new ArrayMap<Scene, Transition>();
     ArrayMap<Scene, ArrayMap<Scene, Transition>> mScenePairTransitions =
             new ArrayMap<Scene, ArrayMap<Scene, Transition>>();
-    ArrayMap<Scene, ArrayMap<String, Transition>> mSceneNameTransitions =
-            new ArrayMap<Scene, ArrayMap<String, Transition>>();
-    ArrayMap<String, ArrayMap<Scene, Transition>> mNameSceneTransitions =
-            new ArrayMap<String, ArrayMap<Scene, Transition>>();
     private static ThreadLocal<WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>>>
             sRunningTransitions =
             new ThreadLocal<WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>>>();
@@ -122,6 +119,21 @@
     }
 
     /**
+     * Sets a specific transition to occur when the given scene is exited. This
+     * has the lowest priority -- if a Scene-to-Scene transition or
+     * Scene enter transition can be applied, it will.
+     *
+     * @param scene The scene which, when exited, will cause the given
+     * transition to run.
+     * @param transition The transition that will play when the given scene is
+     * exited. A value of null will result in the default behavior of
+     * using the default transition instead.
+     */
+    public void setExitTransition(Scene scene, Transition transition) {
+        mExitSceneTransitions.put(scene, transition);
+    }
+
+    /**
      * Sets a specific transition to occur when the given pair of scenes is
      * exited/entered.
      *
@@ -169,6 +181,9 @@
             }
         }
         transition = mSceneTransitions.get(scene);
+        if (transition == null && sceneRoot != null) {
+            transition = mExitSceneTransitions.get(Scene.getCurrentScene(sceneRoot));
+        }
         return (transition != null) ? transition : sDefaultTransition;
     }
 
@@ -224,138 +239,31 @@
     }
 
     /**
-     * Retrieve the transition from a named scene to a target defined scene if one has been
+     * Retrieve the transition to a target defined scene if one has been
      * associated with this TransitionManager.
      *
-     * <p>A named scene is an indirect link for a transition. Fundamentally a named
-     * scene represents a potentially arbitrary intersection point of two otherwise independent
-     * transitions. Activity A may define a transition from scene X to "com.example.scene.FOO"
-     * while activity B may define a transition from scene "com.example.scene.FOO" to scene Y.
-     * In this way applications may define an API for more sophisticated transitions between
-     * caller and called activities very similar to the way that <code>Intent</code> extras
-     * define APIs for arguments and data propagation between activities.</p>
-     *
-     * @param fromName Named scene that this transition corresponds to
      * @param toScene Target scene that this transition will move to
-     * @return Transition corresponding to the given fromName and toScene or null
+     * @return Transition corresponding to the given toScene or null
      *         if no association exists in this TransitionManager
      *
-     * @see #setTransition(String, Scene, Transition)
+     * @see #setTransition(Scene, Transition)
+     * @hide
      */
-    public Transition getNamedTransition(String fromName, Scene toScene) {
-        ArrayMap<Scene, Transition> m = mNameSceneTransitions.get(fromName);
-        if (m != null) {
-            return m.get(toScene);
-        }
-        return null;
+    public Transition getEnterTransition(Scene toScene) {
+        return mSceneTransitions.get(toScene);
     }
 
     /**
      * Retrieve the transition from a defined scene to a target named scene if one has been
      * associated with this TransitionManager.
      *
-     * <p>A named scene is an indirect link for a transition. Fundamentally a named
-     * scene represents a potentially arbitrary intersection point of two otherwise independent
-     * transitions. Activity A may define a transition from scene X to "com.example.scene.FOO"
-     * while activity B may define a transition from scene "com.example.scene.FOO" to scene Y.
-     * In this way applications may define an API for more sophisticated transitions between
-     * caller and called activities very similar to the way that <code>Intent</code> extras
-     * define APIs for arguments and data propagation between activities.</p>
-     *
      * @param fromScene Scene that this transition starts from
-     * @param toName Name of the target scene
-     * @return Transition corresponding to the given fromScene and toName or null
+     * @return Transition corresponding to the given fromScene or null
      *         if no association exists in this TransitionManager
+     * @hide
      */
-    public Transition getNamedTransition(Scene fromScene, String toName) {
-        ArrayMap<String, Transition> m = mSceneNameTransitions.get(fromScene);
-        if (m != null) {
-            return m.get(toName);
-        }
-        return null;
-    }
-
-    /**
-     * Retrieve the supported target named scenes when transitioning away from the given scene.
-     *
-     * <p>A named scene is an indirect link for a transition. Fundamentally a named
-     * scene represents a potentially arbitrary intersection point of two otherwise independent
-     * transitions. Activity A may define a transition from scene X to "com.example.scene.FOO"
-     * while activity B may define a transition from scene "com.example.scene.FOO" to scene Y.
-     * In this way applications may define an API for more sophisticated transitions between
-     * caller and called activities very similar to the way that <code>Intent</code> extras
-     * define APIs for arguments and data propagation between activities.</p>
-     *
-     * @param fromScene Scene to transition from
-     * @return An array of Strings naming each supported transition starting from
-     *         <code>fromScene</code>. If no transitions to a named scene from the given
-     *         scene are supported this function will return a String[] of length 0.
-     *
-     * @see #setTransition(Scene, String, Transition)
-     */
-    public String[] getTargetSceneNames(Scene fromScene) {
-        final ArrayMap<String, Transition> m = mSceneNameTransitions.get(fromScene);
-        if (m == null) {
-            return EMPTY_STRINGS;
-        }
-        final int count = m.size();
-        final String[] result = new String[count];
-        for (int i = 0; i < count; i++) {
-            result[i] = m.keyAt(i);
-        }
-        return result;
-    }
-
-    /**
-     * Set a transition from a specific scene to a named scene.
-     *
-     * <p>A named scene is an indirect link for a transition. Fundamentally a named
-     * scene represents a potentially arbitrary intersection point of two otherwise independent
-     * transitions. Activity A may define a transition from scene X to "com.example.scene.FOO"
-     * while activity B may define a transition from scene "com.example.scene.FOO" to scene Y.
-     * In this way applications may define an API for more sophisticated transitions between
-     * caller and called activities very similar to the way that <code>Intent</code> extras
-     * define APIs for arguments and data propagation between activities.</p>
-     *
-     * @param fromScene Scene to transition from
-     * @param toName Named scene to transition to
-     * @param transition Transition to use
-     *
-     * @see #getTargetSceneNames(Scene)
-     */
-    public void setTransition(Scene fromScene, String toName, Transition transition) {
-        ArrayMap<String, Transition> m = mSceneNameTransitions.get(fromScene);
-        if (m == null) {
-            m = new ArrayMap<String, Transition>();
-            mSceneNameTransitions.put(fromScene, m);
-        }
-        m.put(toName, transition);
-    }
-
-    /**
-     * Set a transition from a named scene to a concrete scene.
-     *
-     * <p>A named scene is an indirect link for a transition. Fundamentally a named
-     * scene represents a potentially arbitrary intersection point of two otherwise independent
-     * transitions. Activity A may define a transition from scene X to "com.example.scene.FOO"
-     * while activity B may define a transition from scene "com.example.scene.FOO" to scene Y.
-     * In this way applications may define an API for more sophisticated transitions between
-     * caller and called activities very similar to the way that <code>Intent</code> extras
-     * define APIs for arguments and data propagation between activities.</p>
-     *
-     * @param fromName Named scene to transition from
-     * @param toScene Scene to transition to
-     * @param transition Transition to use
-     *
-     * @see #getNamedTransition(String, Scene)
-     */
-    public void setTransition(String fromName, Scene toScene, Transition transition) {
-        ArrayMap<Scene, Transition> m = mNameSceneTransitions.get(fromName);
-        if (m == null) {
-            m = new ArrayMap<Scene, Transition>();
-            mNameSceneTransitions.put(fromName, m);
-        }
-        m.put(toScene, transition);
+    public Transition getExitTransition(Scene fromScene) {
+        return mExitSceneTransitions.get(fromScene);
     }
 
     /**
@@ -394,7 +302,7 @@
             ArrayList<Transition> runningTransitions = getRunningTransitions().get(mSceneRoot);
             if (runningTransitions != null && runningTransitions.size() > 0) {
                 for (Transition runningTransition : runningTransitions) {
-                    runningTransition.resume();
+                    runningTransition.resume(mSceneRoot);
                 }
             }
             mTransition.clearValues(true);
@@ -427,7 +335,7 @@
             mTransition.captureValues(mSceneRoot, false);
             if (previousRunningTransitions != null) {
                 for (Transition runningTransition : previousRunningTransitions) {
-                    runningTransition.resume();
+                    runningTransition.resume(mSceneRoot);
                 }
             }
             mTransition.playTransition(mSceneRoot);
@@ -443,7 +351,7 @@
 
         if (runningTransitions != null && runningTransitions.size() > 0) {
             for (Transition runningTransition : runningTransitions) {
-                runningTransition.pause();
+                runningTransition.pause(sceneRoot);
             }
         }
 
diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java
index 4545e3b..19d6b3d 100644
--- a/core/java/android/transition/TransitionSet.java
+++ b/core/java/android/transition/TransitionSet.java
@@ -317,21 +317,21 @@
 
     /** @hide */
     @Override
-    public void pause() {
-        super.pause();
+    public void pause(View sceneRoot) {
+        super.pause(sceneRoot);
         int numTransitions = mTransitions.size();
         for (int i = 0; i < numTransitions; ++i) {
-            mTransitions.get(i).pause();
+            mTransitions.get(i).pause(sceneRoot);
         }
     }
 
     /** @hide */
     @Override
-    public void resume() {
-        super.resume();
+    public void resume(View sceneRoot) {
+        super.resume(sceneRoot);
         int numTransitions = mTransitions.size();
         for (int i = 0; i < numTransitions; ++i) {
-            mTransitions.get(i).resume();
+            mTransitions.get(i).resume(sceneRoot);
         }
     }
 
diff --git a/core/java/android/util/LruCache.java b/core/java/android/util/LruCache.java
index dd504c1..4015488 100644
--- a/core/java/android/util/LruCache.java
+++ b/core/java/android/util/LruCache.java
@@ -87,9 +87,8 @@
 
     /**
      * Sets the size of the cache.
-     * @param maxSize The new maximum size.
      *
-     * @hide
+     * @param maxSize The new maximum size.
      */
     public void resize(int maxSize) {
         if (maxSize <= 0) {
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index dfc74ea..0ae36c1 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -19,8 +19,6 @@
 import android.graphics.Matrix;
 import android.graphics.Path;
 
-import java.util.ArrayList;
-
 /**
  * <p>A display list records a series of graphics related operations and can replay
  * them later. Display lists are usually built by recording operations on a
@@ -124,18 +122,8 @@
  * @hide
  */
 public class DisplayList {
-    private boolean mDirty;
-    private ArrayList<DisplayList> mChildDisplayLists;
-
-    private GLES20RecordingCanvas mCanvas;
     private boolean mValid;
-
-    // Used for debugging
-    private final String mName;
-
-    // The native display list will be destroyed when this object dies.
-    // DO NOT overwrite this reference once it is set.
-    private DisplayListFinalizer mFinalizer;
+    private final long mNativeDisplayList;
 
     /**
      * Flag used when calling
@@ -188,7 +176,8 @@
     public static final int STATUS_DREW = 0x4;
 
     private DisplayList(String name) {
-        mName = name;
+        mNativeDisplayList = nCreate();
+        nSetDisplayListName(mNativeDisplayList, name);
     }
 
     /**
@@ -221,19 +210,11 @@
      * @see #isValid()
      */
     public HardwareCanvas start(int width, int height) {
-        if (mCanvas != null) {
-            throw new IllegalStateException("Recording has already started");
-        }
-
-        mValid = false;
-        mCanvas = GLES20RecordingCanvas.obtain(this);
-        mCanvas.start();
-
-        mCanvas.setViewport(width, height);
+        HardwareCanvas canvas = GLES20RecordingCanvas.obtain();
+        canvas.setViewport(width, height);
         // The dirty rect should always be null for a display list
-        mCanvas.onPreDraw(null);
-
-        return mCanvas;
+        canvas.onPreDraw(null);
+        return canvas;
     }
 
     /**
@@ -244,47 +225,17 @@
      * @see #start(int, int)
      * @see #isValid()
      */
-    public void end() {
-        if (mCanvas != null) {
-            mCanvas.onPostDraw();
-            if (mFinalizer != null) {
-                mCanvas.end(mFinalizer.mNativeDisplayList);
-            } else {
-                mFinalizer = new DisplayListFinalizer(mCanvas.end(0));
-                nSetDisplayListName(mFinalizer.mNativeDisplayList, mName);
-            }
-            mCanvas.recycle();
-            mCanvas = null;
-            mValid = true;
+    public void end(HardwareRenderer renderer, HardwareCanvas endCanvas) {
+        if (!(endCanvas instanceof GLES20RecordingCanvas)) {
+            throw new IllegalArgumentException("Passed an invalid canvas to end!");
         }
-    }
 
-    /**
-     * Clears resources held onto by this display list. After calling this method
-     * {@link #isValid()} will return false.
-     *
-     * @see #isValid()
-     * @see #reset()
-     */
-    public void clear() {
-        clearDirty();
-
-        if (mCanvas != null) {
-            mCanvas.recycle();
-            mCanvas = null;
-        }
-        mValid = false;
-
-        clearReferences();
-    }
-
-    void clearReferences() {
-        if (mChildDisplayLists != null) mChildDisplayLists.clear();
-    }
-
-    ArrayList<DisplayList> getChildDisplayLists() {
-        if (mChildDisplayLists == null) mChildDisplayLists = new ArrayList<DisplayList>();
-        return mChildDisplayLists;
+        GLES20RecordingCanvas canvas = (GLES20RecordingCanvas) endCanvas;
+        canvas.onPostDraw();
+        long displayListData = canvas.finishRecording();
+        renderer.swapDisplayListData(mNativeDisplayList, displayListData);
+        canvas.recycle();
+        mValid = true;
     }
 
     /**
@@ -292,53 +243,14 @@
      * during destruction of hardware resources, to ensure that we do not hold onto
      * obsolete resources after related resources are gone.
      *
-     * @see #clear()
-     *
      * @hide
      */
-    public void reset() {
-        if (hasNativeDisplayList()) {
-            nReset(mFinalizer.mNativeDisplayList);
+    public void destroyDisplayListData(HardwareRenderer renderer) {
+        if (renderer == null) {
+            throw new IllegalArgumentException("Cannot destroyDisplayListData with a null renderer");
         }
-        clear();
-    }
-
-    /**
-     * Sets the dirty flag. When a display list is dirty, {@link #clear()} should
-     * be invoked whenever possible.
-     *
-     * @see #isDirty()
-     * @see #clear()
-     *
-     * @hide
-     */
-    public void markDirty() {
-        mDirty = true;
-    }
-
-    /**
-     * Removes the dirty flag. This method can be used to cancel a cleanup
-     * previously scheduled by setting the dirty flag.
-     *
-     * @see #isDirty()
-     * @see #clear()
-     *
-     * @hide
-     */
-    protected void clearDirty() {
-        mDirty = false;
-    }
-
-    /**
-     * Indicates whether the display list is dirty.
-     *
-     * @see #markDirty()
-     * @see #clear()
-     *
-     * @hide
-     */
-    public boolean isDirty() {
-        return mDirty;
+        renderer.swapDisplayListData(mNativeDisplayList, 0);
+        mValid = false;
     }
 
     /**
@@ -349,27 +261,11 @@
      */
     public boolean isValid() { return mValid; }
 
-    /**
-     * Return the amount of memory used by this display list.
-     *
-     * @return The size of this display list in bytes
-     *
-     * @hide
-     */
-    public int getSize() {
-        if (mFinalizer == null) return 0;
-        return nGetDisplayListSize(mFinalizer.mNativeDisplayList);
-    }
-
-    boolean hasNativeDisplayList() {
-        return mValid && mFinalizer != null;
-    }
-
     long getNativeDisplayList() {
-        if (!mValid || mFinalizer == null) {
+        if (!mValid) {
             throw new IllegalStateException("The display list is not valid.");
         }
-        return mFinalizer.mNativeDisplayList;
+        return mNativeDisplayList;
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -386,9 +282,7 @@
      * @hide
      */
     public void setCaching(boolean caching) {
-        if (hasNativeDisplayList()) {
-            nSetCaching(mFinalizer.mNativeDisplayList, caching);
-        }
+        nSetCaching(mNativeDisplayList, caching);
     }
 
     /**
@@ -398,9 +292,7 @@
      * @param clipToBounds true if the display list should clip to its bounds
      */
     public void setClipToBounds(boolean clipToBounds) {
-        if (hasNativeDisplayList()) {
-            nSetClipToBounds(mFinalizer.mNativeDisplayList, clipToBounds);
-        }
+        nSetClipToBounds(mNativeDisplayList, clipToBounds);
     }
 
     /**
@@ -410,9 +302,7 @@
      * @param isolatedZVolume true if the display list should collect and Z order descendents.
      */
     public void setIsolatedZVolume(boolean isolatedZVolume) {
-        if (hasNativeDisplayList()) {
-            nSetIsolatedZVolume(mFinalizer.mNativeDisplayList, isolatedZVolume);
-        }
+        nSetIsolatedZVolume(mNativeDisplayList, isolatedZVolume);
     }
 
     /**
@@ -425,9 +315,7 @@
      *            containing volume.
      */
     public void setProjectBackwards(boolean shouldProject) {
-        if (hasNativeDisplayList()) {
-            nSetProjectBackwards(mFinalizer.mNativeDisplayList, shouldProject);
-        }
+        nSetProjectBackwards(mNativeDisplayList, shouldProject);
     }
 
     /**
@@ -436,9 +324,7 @@
      * ProjectBackwards=true directly on top of it. Default value is false.
      */
     public void setProjectionReceiver(boolean shouldRecieve) {
-        if (hasNativeDisplayList()) {
-            nSetProjectionReceiver(mFinalizer.mNativeDisplayList, shouldRecieve);
-        }
+        nSetProjectionReceiver(mNativeDisplayList, shouldRecieve);
     }
 
     /**
@@ -450,10 +336,8 @@
      * @param outline Convex, CW Path to store in the DisplayList. May be null.
      */
     public void setOutline(Path outline) {
-        if (hasNativeDisplayList()) {
-            long nativePath = (outline == null) ? 0 : outline.mNativePath;
-            nSetOutline(mFinalizer.mNativeDisplayList, nativePath);
-        }
+        long nativePath = (outline == null) ? 0 : outline.mNativePath;
+        nSetOutline(mNativeDisplayList, nativePath);
     }
 
     /**
@@ -462,9 +346,7 @@
      * @param clipToOutline true if clipping to the outline.
      */
     public void setClipToOutline(boolean clipToOutline) {
-        if (hasNativeDisplayList()) {
-            nSetClipToOutline(mFinalizer.mNativeDisplayList, clipToOutline);
-        }
+        nSetClipToOutline(mNativeDisplayList, clipToOutline);
     }
 
     /**
@@ -474,9 +356,7 @@
      * and non-empty, otherwise it will be the bounds rect.
      */
     public void setCastsShadow(boolean castsShadow) {
-        if (hasNativeDisplayList()) {
-            nSetCastsShadow(mFinalizer.mNativeDisplayList, castsShadow);
-        }
+        nSetCastsShadow(mNativeDisplayList, castsShadow);
     }
 
     /**
@@ -485,9 +365,7 @@
      * If set to true, camera distance will be ignored. Defaults to false.
      */
     public void setUsesGlobalCamera(boolean usesGlobalCamera) {
-        if (hasNativeDisplayList()) {
-            nSetUsesGlobalCamera(mFinalizer.mNativeDisplayList, usesGlobalCamera);
-        }
+        nSetUsesGlobalCamera(mNativeDisplayList, usesGlobalCamera);
     }
 
     /**
@@ -499,41 +377,8 @@
      * @see #getMatrix(android.graphics.Matrix)
      * @see #getMatrix()
      */
-    public void setMatrix(Matrix matrix) {
-        if (hasNativeDisplayList()) {
-            nSetStaticMatrix(mFinalizer.mNativeDisplayList, matrix.native_instance);
-        }
-    }
-
-    /**
-     * Returns the static matrix set on this display list.
-     *
-     * @return A new {@link Matrix} instance populated with this display list's static
-     *         matrix
-     *
-     * @see #getMatrix(android.graphics.Matrix)
-     * @see #setMatrix(android.graphics.Matrix)
-     */
-    public Matrix getMatrix() {
-        return getMatrix(new Matrix());
-    }
-
-    /**
-     * Copies this display list's static matrix into the specified matrix.
-     *
-     * @param matrix The {@link Matrix} instance in which to copy this display
-     *               list's static matrix. Cannot be null
-     *
-     * @return The <code>matrix</code> parameter, for convenience
-     *
-     * @see #getMatrix()
-     * @see #setMatrix(android.graphics.Matrix)
-     */
-    public Matrix getMatrix(Matrix matrix) {
-        if (hasNativeDisplayList()) {
-            nGetMatrix(mFinalizer.mNativeDisplayList, matrix.native_instance);
-        }
-        return matrix;
+    public void setStaticMatrix(Matrix matrix) {
+        nSetStaticMatrix(mNativeDisplayList, matrix.native_instance);
     }
 
     /**
@@ -547,10 +392,8 @@
      * @hide
      */
     public void setAnimationMatrix(Matrix matrix) {
-        if (hasNativeDisplayList()) {
-            nSetAnimationMatrix(mFinalizer.mNativeDisplayList,
-                    (matrix != null) ? matrix.native_instance : 0);
-        }
+        nSetAnimationMatrix(mNativeDisplayList,
+                (matrix != null) ? matrix.native_instance : 0);
     }
 
     /**
@@ -562,9 +405,7 @@
      * @see #getAlpha()
      */
     public void setAlpha(float alpha) {
-        if (hasNativeDisplayList()) {
-            nSetAlpha(mFinalizer.mNativeDisplayList, alpha);
-        }
+        nSetAlpha(mNativeDisplayList, alpha);
     }
 
     /**
@@ -575,10 +416,7 @@
      * @see #setAlpha(float)
      */
     public float getAlpha() {
-        if (hasNativeDisplayList()) {
-            return nGetAlpha(mFinalizer.mNativeDisplayList);
-        }
-        return 1.0f;
+        return nGetAlpha(mNativeDisplayList);
     }
 
     /**
@@ -593,9 +431,7 @@
      * @see #hasOverlappingRendering()
      */
     public void setHasOverlappingRendering(boolean hasOverlappingRendering) {
-        if (hasNativeDisplayList()) {
-            nSetHasOverlappingRendering(mFinalizer.mNativeDisplayList, hasOverlappingRendering);
-        }
+        nSetHasOverlappingRendering(mNativeDisplayList, hasOverlappingRendering);
     }
 
     /**
@@ -607,10 +443,7 @@
      */
     public boolean hasOverlappingRendering() {
         //noinspection SimplifiableIfStatement
-        if (hasNativeDisplayList()) {
-            return nHasOverlappingRendering(mFinalizer.mNativeDisplayList);
-        }
-        return true;
+        return nHasOverlappingRendering(mNativeDisplayList);
     }
 
     /**
@@ -622,9 +455,7 @@
      * @see #getTranslationX()
      */
     public void setTranslationX(float translationX) {
-        if (hasNativeDisplayList()) {
-            nSetTranslationX(mFinalizer.mNativeDisplayList, translationX);
-        }
+        nSetTranslationX(mNativeDisplayList, translationX);
     }
 
     /**
@@ -633,10 +464,7 @@
      * @see #setTranslationX(float)
      */
     public float getTranslationX() {
-        if (hasNativeDisplayList()) {
-            return nGetTranslationX(mFinalizer.mNativeDisplayList);
-        }
-        return 0.0f;
+        return nGetTranslationX(mNativeDisplayList);
     }
 
     /**
@@ -648,9 +476,7 @@
      * @see #getTranslationY()
      */
     public void setTranslationY(float translationY) {
-        if (hasNativeDisplayList()) {
-            nSetTranslationY(mFinalizer.mNativeDisplayList, translationY);
-        }
+        nSetTranslationY(mNativeDisplayList, translationY);
     }
 
     /**
@@ -659,10 +485,7 @@
      * @see #setTranslationY(float)
      */
     public float getTranslationY() {
-        if (hasNativeDisplayList()) {
-            return nGetTranslationY(mFinalizer.mNativeDisplayList);
-        }
-        return 0.0f;
+        return nGetTranslationY(mNativeDisplayList);
     }
 
     /**
@@ -672,9 +495,7 @@
      * @see #getTranslationZ()
      */
     public void setTranslationZ(float translationZ) {
-        if (hasNativeDisplayList()) {
-            nSetTranslationZ(mFinalizer.mNativeDisplayList, translationZ);
-        }
+        nSetTranslationZ(mNativeDisplayList, translationZ);
     }
 
     /**
@@ -683,10 +504,7 @@
      * @see #setTranslationZ(float)
      */
     public float getTranslationZ() {
-        if (hasNativeDisplayList()) {
-            return nGetTranslationZ(mFinalizer.mNativeDisplayList);
-        }
-        return 0.0f;
+        return nGetTranslationZ(mNativeDisplayList);
     }
 
     /**
@@ -698,9 +516,7 @@
      * @see #getRotation()
      */
     public void setRotation(float rotation) {
-        if (hasNativeDisplayList()) {
-            nSetRotation(mFinalizer.mNativeDisplayList, rotation);
-        }
+        nSetRotation(mNativeDisplayList, rotation);
     }
 
     /**
@@ -709,10 +525,7 @@
      * @see #setRotation(float)
      */
     public float getRotation() {
-        if (hasNativeDisplayList()) {
-            return nGetRotation(mFinalizer.mNativeDisplayList);
-        }
-        return 0.0f;
+        return nGetRotation(mNativeDisplayList);
     }
 
     /**
@@ -724,9 +537,7 @@
      * @see #getRotationX()
      */
     public void setRotationX(float rotationX) {
-        if (hasNativeDisplayList()) {
-            nSetRotationX(mFinalizer.mNativeDisplayList, rotationX);
-        }
+        nSetRotationX(mNativeDisplayList, rotationX);
     }
 
     /**
@@ -735,10 +546,7 @@
      * @see #setRotationX(float)
      */
     public float getRotationX() {
-        if (hasNativeDisplayList()) {
-            return nGetRotationX(mFinalizer.mNativeDisplayList);
-        }
-        return 0.0f;
+        return nGetRotationX(mNativeDisplayList);
     }
 
     /**
@@ -750,9 +558,7 @@
      * @see #getRotationY()
      */
     public void setRotationY(float rotationY) {
-        if (hasNativeDisplayList()) {
-            nSetRotationY(mFinalizer.mNativeDisplayList, rotationY);
-        }
+        nSetRotationY(mNativeDisplayList, rotationY);
     }
 
     /**
@@ -761,10 +567,7 @@
      * @see #setRotationY(float)
      */
     public float getRotationY() {
-        if (hasNativeDisplayList()) {
-            return nGetRotationY(mFinalizer.mNativeDisplayList);
-        }
-        return 0.0f;
+        return nGetRotationY(mNativeDisplayList);
     }
 
     /**
@@ -776,9 +579,7 @@
      * @see #getScaleX()
      */
     public void setScaleX(float scaleX) {
-        if (hasNativeDisplayList()) {
-            nSetScaleX(mFinalizer.mNativeDisplayList, scaleX);
-        }
+        nSetScaleX(mNativeDisplayList, scaleX);
     }
 
     /**
@@ -787,10 +588,7 @@
      * @see #setScaleX(float)
      */
     public float getScaleX() {
-        if (hasNativeDisplayList()) {
-            return nGetScaleX(mFinalizer.mNativeDisplayList);
-        }
-        return 1.0f;
+        return nGetScaleX(mNativeDisplayList);
     }
 
     /**
@@ -802,9 +600,7 @@
      * @see #getScaleY()
      */
     public void setScaleY(float scaleY) {
-        if (hasNativeDisplayList()) {
-            nSetScaleY(mFinalizer.mNativeDisplayList, scaleY);
-        }
+        nSetScaleY(mNativeDisplayList, scaleY);
     }
 
     /**
@@ -813,10 +609,7 @@
      * @see #setScaleY(float)
      */
     public float getScaleY() {
-        if (hasNativeDisplayList()) {
-            return nGetScaleY(mFinalizer.mNativeDisplayList);
-        }
-        return 1.0f;
+        return nGetScaleY(mNativeDisplayList);
     }
 
     /**
@@ -836,11 +629,9 @@
     public void setTransformationInfo(float alpha,
             float translationX, float translationY, float translationZ,
             float rotation, float rotationX, float rotationY, float scaleX, float scaleY) {
-        if (hasNativeDisplayList()) {
-            nSetTransformationInfo(mFinalizer.mNativeDisplayList, alpha,
-                    translationX, translationY, translationZ,
-                    rotation, rotationX, rotationY, scaleX, scaleY);
-        }
+        nSetTransformationInfo(mNativeDisplayList, alpha,
+                translationX, translationY, translationZ,
+                rotation, rotationX, rotationY, scaleX, scaleY);
     }
 
     /**
@@ -852,9 +643,7 @@
      * @see #getPivotX()
      */
     public void setPivotX(float pivotX) {
-        if (hasNativeDisplayList()) {
-            nSetPivotX(mFinalizer.mNativeDisplayList, pivotX);
-        }
+        nSetPivotX(mNativeDisplayList, pivotX);
     }
 
     /**
@@ -863,10 +652,7 @@
      * @see #setPivotX(float)
      */
     public float getPivotX() {
-        if (hasNativeDisplayList()) {
-            return nGetPivotX(mFinalizer.mNativeDisplayList);
-        }
-        return 0.0f;
+        return nGetPivotX(mNativeDisplayList);
     }
 
     /**
@@ -878,9 +664,7 @@
      * @see #getPivotY()
      */
     public void setPivotY(float pivotY) {
-        if (hasNativeDisplayList()) {
-            nSetPivotY(mFinalizer.mNativeDisplayList, pivotY);
-        }
+        nSetPivotY(mNativeDisplayList, pivotY);
     }
 
     /**
@@ -889,10 +673,7 @@
      * @see #setPivotY(float)
      */
     public float getPivotY() {
-        if (hasNativeDisplayList()) {
-            return nGetPivotY(mFinalizer.mNativeDisplayList);
-        }
-        return 0.0f;
+        return nGetPivotY(mNativeDisplayList);
     }
 
     /**
@@ -906,9 +687,7 @@
      * @see #getCameraDistance()
      */
     public void setCameraDistance(float distance) {
-        if (hasNativeDisplayList()) {
-            nSetCameraDistance(mFinalizer.mNativeDisplayList, distance);
-        }
+        nSetCameraDistance(mNativeDisplayList, distance);
     }
 
     /**
@@ -917,10 +696,7 @@
      * @see #setCameraDistance(float)
      */
     public float getCameraDistance() {
-        if (hasNativeDisplayList()) {
-            return nGetCameraDistance(mFinalizer.mNativeDisplayList);
-        }
-        return 0.0f;
+        return nGetCameraDistance(mNativeDisplayList);
     }
 
     /**
@@ -932,9 +708,7 @@
      * @see #getLeft()
      */
     public void setLeft(int left) {
-        if (hasNativeDisplayList()) {
-            nSetLeft(mFinalizer.mNativeDisplayList, left);
-        }
+        nSetLeft(mNativeDisplayList, left);
     }
 
     /**
@@ -943,10 +717,7 @@
      * @see #setLeft(int)
      */
     public float getLeft() {
-        if (hasNativeDisplayList()) {
-            return nGetLeft(mFinalizer.mNativeDisplayList);
-        }
-        return 0.0f;
+        return nGetLeft(mNativeDisplayList);
     }
 
     /**
@@ -958,9 +729,7 @@
      * @see #getTop()
      */
     public void setTop(int top) {
-        if (hasNativeDisplayList()) {
-            nSetTop(mFinalizer.mNativeDisplayList, top);
-        }
+        nSetTop(mNativeDisplayList, top);
     }
 
     /**
@@ -969,10 +738,7 @@
      * @see #setTop(int)
      */
     public float getTop() {
-        if (hasNativeDisplayList()) {
-            return nGetTop(mFinalizer.mNativeDisplayList);
-        }
-        return 0.0f;
+        return nGetTop(mNativeDisplayList);
     }
 
     /**
@@ -984,9 +750,7 @@
      * @see #getRight()
      */
     public void setRight(int right) {
-        if (hasNativeDisplayList()) {
-            nSetRight(mFinalizer.mNativeDisplayList, right);
-        }
+        nSetRight(mNativeDisplayList, right);
     }
 
     /**
@@ -995,10 +759,7 @@
      * @see #setRight(int)
      */
     public float getRight() {
-        if (hasNativeDisplayList()) {
-            return nGetRight(mFinalizer.mNativeDisplayList);
-        }
-        return 0.0f;
+        return nGetRight(mNativeDisplayList);
     }
 
     /**
@@ -1010,9 +771,7 @@
      * @see #getBottom()
      */
     public void setBottom(int bottom) {
-        if (hasNativeDisplayList()) {
-            nSetBottom(mFinalizer.mNativeDisplayList, bottom);
-        }
+        nSetBottom(mNativeDisplayList, bottom);
     }
 
     /**
@@ -1021,10 +780,7 @@
      * @see #setBottom(int)
      */
     public float getBottom() {
-        if (hasNativeDisplayList()) {
-            return nGetBottom(mFinalizer.mNativeDisplayList);
-        }
-        return 0.0f;
+        return nGetBottom(mNativeDisplayList);
     }
 
     /**
@@ -1041,9 +797,7 @@
      * @see View#setBottom(int)
      */
     public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
-        if (hasNativeDisplayList()) {
-            nSetLeftTopRightBottom(mFinalizer.mNativeDisplayList, left, top, right, bottom);
-        }
+        nSetLeftTopRightBottom(mNativeDisplayList, left, top, right, bottom);
     }
 
     /**
@@ -1055,9 +809,7 @@
      * @see View#offsetLeftAndRight(int)
      */
     public void offsetLeftAndRight(float offset) {
-        if (hasNativeDisplayList()) {
-            nOffsetLeftAndRight(mFinalizer.mNativeDisplayList, offset);
-        }
+        nOffsetLeftAndRight(mNativeDisplayList, offset);
     }
 
     /**
@@ -1069,9 +821,7 @@
      * @see View#offsetTopAndBottom(int)
      */
     public void offsetTopAndBottom(float offset) {
-        if (hasNativeDisplayList()) {
-            nOffsetTopAndBottom(mFinalizer.mNativeDisplayList, offset);
-        }
+        nOffsetTopAndBottom(mNativeDisplayList, offset);
     }
 
     /**
@@ -1081,22 +831,19 @@
      * @hide
      */
     public void output() {
-        if (hasNativeDisplayList()) {
-            nOutput(mFinalizer.mNativeDisplayList);
-        }
+        nOutput(mNativeDisplayList);
     }
 
     ///////////////////////////////////////////////////////////////////////////
     // Native methods
     ///////////////////////////////////////////////////////////////////////////
 
+    private static native long nCreate();
     private static native void nDestroyDisplayList(long displayList);
-    private static native int nGetDisplayListSize(long displayList);
     private static native void nSetDisplayListName(long displayList, String name);
 
     // Properties
 
-    private static native void nReset(long displayList);
     private static native void nOffsetTopAndBottom(long displayList, float offset);
     private static native void nOffsetLeftAndRight(long displayList, float offset);
     private static native void nSetLeftTopRightBottom(long displayList, int left, int top,
@@ -1135,7 +882,6 @@
     private static native void nSetAnimationMatrix(long displayList, long animationMatrix);
 
     private static native boolean nHasOverlappingRendering(long displayList);
-    private static native void nGetMatrix(long displayList, long matrix);
     private static native float nGetAlpha(long displayList);
     private static native float nGetLeft(long displayList);
     private static native float nGetTop(long displayList);
@@ -1158,20 +904,12 @@
     // Finalization
     ///////////////////////////////////////////////////////////////////////////
 
-    private static class DisplayListFinalizer {
-        final long mNativeDisplayList;
-
-        public DisplayListFinalizer(long nativeDisplayList) {
-            mNativeDisplayList = nativeDisplayList;
-        }
-
-        @Override
-        protected void finalize() throws Throwable {
-            try {
-                nDestroyDisplayList(mNativeDisplayList);
-            } finally {
-                super.finalize();
-            }
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            nDestroyDisplayList(mNativeDisplayList);
+        } finally {
+            super.finalize();
         }
     }
 }
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 2ed0cba..6c6fc9b 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -18,7 +18,6 @@
 
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
-import android.graphics.ColorFilter;
 import android.graphics.DrawFilter;
 import android.graphics.Matrix;
 import android.graphics.NinePatch;
@@ -47,7 +46,7 @@
     private static final int MODIFIER_SHADER = 2;
 
     private final boolean mOpaque;
-    private long mRenderer;
+    protected long mRenderer;
 
     // The native renderer will be destroyed when this object dies.
     // DO NOT overwrite this reference once it is set.
@@ -107,10 +106,6 @@
         }
     }
 
-    protected void resetDisplayListRenderer() {
-        nResetDisplayListRenderer(mRenderer);
-    }
-
     private static native long nCreateRenderer();
     private static native long nCreateDisplayListRenderer();
     private static native void nResetDisplayListRenderer(long renderer);
@@ -351,21 +346,17 @@
     // Atlas
     ///////////////////////////////////////////////////////////////////////////
 
-    static void initAtlas(GraphicBuffer buffer, int[] map) {
+    static void initAtlas(GraphicBuffer buffer, long[] map) {
         nInitAtlas(buffer, map, map.length);
     }
 
-    private static native void nInitAtlas(GraphicBuffer buffer, int[] map, int count);
+    private static native void nInitAtlas(GraphicBuffer buffer, long[] map, int count);
 
     ///////////////////////////////////////////////////////////////////////////
     // Display list
     ///////////////////////////////////////////////////////////////////////////
 
-    long getDisplayList(long displayList) {
-        return nGetDisplayList(mRenderer, displayList);
-    }
-
-    private static native long nGetDisplayList(long renderer, long displayList);
+    protected static native long nFinishRecording(long renderer);
 
     @Override
     public int drawDisplayList(DisplayList displayList, Rect dirty, int flags) {
diff --git a/core/java/android/view/GLES20RecordingCanvas.java b/core/java/android/view/GLES20RecordingCanvas.java
index b7b6883..2b29e5c 100644
--- a/core/java/android/view/GLES20RecordingCanvas.java
+++ b/core/java/android/view/GLES20RecordingCanvas.java
@@ -16,7 +16,6 @@
 
 package android.view;
 
-import android.graphics.Rect;
 import android.util.Pools.SynchronizedPool;
 
 /**
@@ -33,39 +32,23 @@
     private static final SynchronizedPool<GLES20RecordingCanvas> sPool =
             new SynchronizedPool<GLES20RecordingCanvas>(POOL_LIMIT);
 
-    private DisplayList mDisplayList;
-
     private GLES20RecordingCanvas() {
         super(true, true);
     }
 
-    static GLES20RecordingCanvas obtain(DisplayList displayList) {
+    static GLES20RecordingCanvas obtain() {
         GLES20RecordingCanvas canvas = sPool.acquire();
         if (canvas == null) {
             canvas = new GLES20RecordingCanvas();
         }
-        canvas.mDisplayList = displayList;
         return canvas;
     }
 
     void recycle() {
-        mDisplayList = null;
-        resetDisplayListRenderer();
         sPool.release(this);
     }
 
-    void start() {
-        mDisplayList.clearReferences();
-    }
-
-    long end(long nativeDisplayList) {
-        return getDisplayList(nativeDisplayList);
-    }
-
-    @Override
-    public int drawDisplayList(DisplayList displayList, Rect dirty, int flags) {
-        int status = super.drawDisplayList(displayList, dirty, flags);
-        mDisplayList.getChildDisplayLists().add(displayList);
-        return status;
+    long finishRecording() {
+        return nFinishRecording(mRenderer);
     }
 }
diff --git a/core/java/android/view/GLRenderer.java b/core/java/android/view/GLRenderer.java
index d61c4b1..c90e4b0 100644
--- a/core/java/android/view/GLRenderer.java
+++ b/core/java/android/view/GLRenderer.java
@@ -271,7 +271,7 @@
             if (atlas.isCompatible(android.os.Process.myPpid())) {
                 GraphicBuffer buffer = atlas.getBuffer();
                 if (buffer != null) {
-                    int[] map = atlas.getMap();
+                    long[] map = atlas.getMap();
                     if (map != null) {
                         GLES20Canvas.initAtlas(buffer, map);
                     }
@@ -478,6 +478,7 @@
     @Override
     void flushLayerUpdates() {
         if (validate()) {
+            flushLayerChanges();
             mGlCanvas.flushLayerUpdates();
         }
     }
@@ -1195,6 +1196,11 @@
         }
     }
 
+    void swapDisplayListData(long displayList, long newData) {
+        nSwapDisplayListData(displayList, newData);
+    }
+    private static native void nSwapDisplayListData(long displayList, long newData);
+
     private DisplayList buildDisplayList(View view, HardwareCanvas canvas) {
         if (mDrawDelta <= 0) {
             return view.mDisplayList;
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index 958c071..c526dd2 100644
--- a/core/java/android/view/HardwareLayer.java
+++ b/core/java/android/view/HardwareLayer.java
@@ -66,8 +66,7 @@
      * @see View#setLayerPaint(android.graphics.Paint)
      */
     public void setLayerPaint(Paint paint) {
-        nSetLayerPaint(mFinalizer.mDeferredUpdater, paint.mNativePaint,
-                paint.getColorFilter() != null ? paint.getColorFilter().native_instance : 0);
+        nSetLayerPaint(mFinalizer.mDeferredUpdater, paint.mNativePaint);
     }
 
     /**
@@ -89,7 +88,7 @@
         }
 
         if (mDisplayList != null) {
-            mDisplayList.reset();
+            mDisplayList.destroyDisplayListData(mRenderer);
             mDisplayList = null;
         }
         if (mRenderer != null) {
@@ -270,7 +269,7 @@
     private static native void nDestroyLayerUpdater(long layerUpdater);
 
     private static native boolean nPrepare(long layerUpdater, int width, int height, boolean isOpaque);
-    private static native void nSetLayerPaint(long layerUpdater, long paint, long colorFilter);
+    private static native void nSetLayerPaint(long layerUpdater, long paint);
     private static native void nSetTransform(long layerUpdater, long matrix);
     private static native void nSetSurfaceTexture(long layerUpdater,
             SurfaceTexture surface, boolean isAlreadyAttached);
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 7a943f0..bcc28e3 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -562,6 +562,8 @@
         mRequested = requested;
     }
 
+    abstract void swapDisplayListData(long displayList, long newData);
+
     /**
      * Describes a series of frames that should be drawn on screen as a graph.
      * Each frame is composed of 1 or more elements.
diff --git a/core/java/android/view/IAssetAtlas.aidl b/core/java/android/view/IAssetAtlas.aidl
index 5f1e238..edce059 100644
--- a/core/java/android/view/IAssetAtlas.aidl
+++ b/core/java/android/view/IAssetAtlas.aidl
@@ -45,10 +45,10 @@
      * if the atlas is not available yet.
      *
      * Each bitmap is represented by several entries in the array:
-     * int0: SkBitmap*, the native bitmap object
-     * int1: x position
-     * int2: y position
-     * int3: rotated, 1 if the bitmap must be rotated, 0 otherwise
+     * long0: SkBitmap*, the native bitmap object
+     * long1: x position
+     * long2: y position
+     * long3: rotated, 1 if the bitmap must be rotated, 0 otherwise
      */
-    int[] getMap();
+    long[] getMap();
 }
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 7e745d8..c183f08 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -628,11 +628,19 @@
     /** Key code constant: Brightness Up key.
      * Adjusts the screen brightness up. */
     public static final int KEYCODE_BRIGHTNESS_UP   = 221;
-    /** Key code constant: Audio Track key
+    /** Key code constant: Audio Track key.
      * Switches the audio tracks. */
     public static final int KEYCODE_MEDIA_AUDIO_TRACK = 222;
+    /** Key code constant: Sleep key.
+     * Puts the device to sleep.  Behaves somewhat like {@link #KEYCODE_POWER} but it
+     * has no effect if the device is already asleep. */
+    public static final int KEYCODE_SLEEP           = 223;
+    /** Key code constant: Wakeup key.
+     * Wakes up the device.  Behaves somewhat like {@link #KEYCODE_POWER} but it
+     * has no effect if the device is already awake. */
+    public static final int KEYCODE_WAKEUP          = 224;
 
-    private static final int LAST_KEYCODE           = KEYCODE_MEDIA_AUDIO_TRACK;
+    private static final int LAST_KEYCODE = KEYCODE_WAKEUP;
 
     // NOTE: If you add a new keycode here you must also add it to:
     //  isSystem()
@@ -877,6 +885,8 @@
         names.append(KEYCODE_BRIGHTNESS_DOWN, "KEYCODE_BRIGHTNESS_DOWN");
         names.append(KEYCODE_BRIGHTNESS_UP, "KEYCODE_BRIGHTNESS_UP");
         names.append(KEYCODE_MEDIA_AUDIO_TRACK, "KEYCODE_MEDIA_AUDIO_TRACK");
+        names.append(KEYCODE_SLEEP, "KEYCODE_SLEEP");
+        names.append(KEYCODE_WAKEUP, "KEYCODE_WAKEUP");
     };
 
     // Symbolic names of all metakeys in bit order from least significant to most significant.
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 5a8d2c8..e693b9e 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -167,6 +167,13 @@
     public static final int FX_SURFACE_DIM = 0x00020000;
 
     /**
+     * Surface creation flag: Creates a video plane Surface.
+     * This surface is backed by a hardware video plane. It is an error to lock
+     * a video plane surface, since it doesn't have a backing store.
+     */
+    public static final int FX_SURFACE_VIDEO_PLANE = 0x00040000;
+
+    /**
      * Mask used for FX values above.
      *
      */
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 65d3f6d..1f211c2 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -255,8 +255,9 @@
         updateWindow(false, false);
     }
 
+    /** @hide */
     @Override
-    protected void onDetachedFromWindow() {
+    protected void onDetachedFromWindowInternal() {
         if (mGlobalListenersAdded) {
             ViewTreeObserver observer = getViewTreeObserver();
             observer.removeOnScrollChangedListener(mScrollChangedListener);
@@ -278,7 +279,7 @@
         mSession = null;
         mLayout.token = null;
 
-        super.onDetachedFromWindow();
+        super.onDetachedFromWindowInternal();
     }
 
     @Override
@@ -421,7 +422,10 @@
         mWindowType = type;
     }
 
-    private void updateWindow(boolean force, boolean redrawNeeded) {
+    /**
+     * @hide
+     */
+    protected void updateWindow(boolean force, boolean redrawNeeded) {
         if (!mHaveFrame) {
             return;
         }
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index ef0d80d..3cfe5e9 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -228,10 +228,11 @@
         }
     }
 
+    /** @hide */
     @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
+    protected void onDetachedFromWindowInternal() {
         destroySurface();
+        super.onDetachedFromWindowInternal();
     }
 
     private void destroySurface() {
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index e8f5e45..3dcfbb3 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -148,6 +148,11 @@
     }
 
     @Override
+    void swapDisplayListData(long displayList, long newData) {
+        nSwapDisplayListData(mNativeProxy, displayList, newData);
+    }
+
+    @Override
     void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) {
         attachInfo.mIgnoreDirtyState = true;
         attachInfo.mDrawingTime = SystemClock.uptimeMillis();
@@ -252,6 +257,8 @@
     private static native boolean nInitialize(long nativeProxy, Surface window);
     private static native void nUpdateSurface(long nativeProxy, Surface window);
     private static native void nSetup(long nativeProxy, int width, int height);
+    private static native void nSwapDisplayListData(long nativeProxy, long displayList,
+            long newData);
     private static native void nDrawDisplayList(long nativeProxy, long displayList,
             int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
     private static native void nRunWithGlContext(long nativeProxy, Runnable runnable);
diff --git a/core/java/android/view/VideoPlaneView.java b/core/java/android/view/VideoPlaneView.java
new file mode 100644
index 0000000..81dcf9d
--- /dev/null
+++ b/core/java/android/view/VideoPlaneView.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+/**
+ * Provides a dedicated surface embedded inside of a view hierarchy much like a
+ * {@link SurfaceView}, but the surface is actually backed by a hardware video
+ * plane.
+ *
+ * TODO: Eventually this should be separate from SurfaceView.
+ *
+ * @hide
+ */
+public class VideoPlaneView extends SurfaceView {
+    public VideoPlaneView(Context context) {
+        super(context);
+    }
+
+    public VideoPlaneView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public VideoPlaneView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public VideoPlaneView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    protected void updateWindow(boolean force, boolean redrawNeeded) {
+        mLayout.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_VIDEO_PLANE;
+        super.updateWindow(force, redrawNeeded);
+    }
+}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a647194..9b45f97 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -101,7 +101,9 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -5136,8 +5138,7 @@
      * @param text The announcement text.
      */
     public void announceForAccessibility(CharSequence text) {
-        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null
-                && isImportantForAccessibility()) {
+        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
             AccessibilityEvent event = AccessibilityEvent.obtain(
                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
             onInitializeAccessibilityEvent(event);
@@ -5187,7 +5188,7 @@
      * Note: Called from the default {@link AccessibilityDelegate}.
      */
     void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
-        if (!isShown() || !isImportantForAccessibility()) {
+        if (!isShown()) {
             return;
         }
         onInitializeAccessibilityEvent(event);
@@ -7982,8 +7983,6 @@
      * @hide
      */
     public void dispatchStartTemporaryDetach() {
-        clearDisplayList();
-
         onStartTemporaryDetach();
     }
 
@@ -9391,7 +9390,7 @@
 
         if ((changed & VISIBILITY_MASK) != 0) {
             // If the view is invisible, cleanup its display list to free up resources
-            if (newVisibility != VISIBLE) {
+            if (newVisibility != VISIBLE && mAttachInfo != null) {
                 cleanupDraw();
             }
 
@@ -10846,11 +10845,14 @@
      * Sets the outline of the view, which defines the shape of the shadow it
      * casts, and can used for clipping.
      * <p>
+     * The outline path of a View must be {@link android.graphics.Path#isConvex() convex}.
+     * <p>
      * If the outline is not set, or {@link Path#isEmpty()}, shadows will be
      * cast from the bounds of the View, and clipToOutline will be ignored.
      *
-     * @param outline The new outline of the view. Must be non-null.
+     * @param outline The new outline of the view. Must be non-null, and convex.
      *
+     * @see #setCastsShadow(boolean)
      * @see #getOutline(Path)
      * @see #getClipToOutline()
      * @see #setClipToOutline(boolean)
@@ -10859,6 +10861,9 @@
         if (outline == null) {
             throw new IllegalArgumentException("Path must be non-null");
         }
+        if (!outline.isConvex()) {
+            throw new IllegalArgumentException("Path must be convex");
+        }
         // always copy the path since caller may reuse
         if (mOutline == null) {
             mOutline = new Path(outline);
@@ -10929,9 +10934,8 @@
      * Set to true to enable this View to cast shadows.
      * <p>
      * If enabled, and the View has a z translation greater than 0, or is
-     * rotated in 3D, the shadow will be cast onto the current
-     * {@link ViewGroup#setIsolatedZVolume(boolean) isolated Z volume},
-     * at the z = 0 plane.
+     * rotated in 3D, the shadow will be cast onto its parent at the z = 0
+     * plane.
      * <p>
      * The shape of the shadow being cast is defined by the
      * {@link #setOutline(Path) outline} of the view, or the rectangular bounds
@@ -11454,76 +11458,54 @@
                 (!(mParent instanceof ViewGroup) ||
                         !((ViewGroup) mParent).isViewTransitioning(this));
     }
+
     /**
      * Mark the area defined by dirty as needing to be drawn. If the view is
-     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some point
-     * in the future. This must be called from a UI thread. To call from a non-UI
-     * thread, call {@link #postInvalidate()}.
+     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
+     * point in the future.
+     * <p>
+     * This must be called from a UI thread. To call from a non-UI thread, call
+     * {@link #postInvalidate()}.
+     * <p>
+     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
+     * {@code dirty}.
      *
-     * WARNING: This method is destructive to dirty.
      * @param dirty the rectangle representing the bounds of the dirty region
      */
     public void invalidate(Rect dirty) {
-        if (skipInvalidate()) {
-            return;
-        }
-        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
-                (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID ||
-                (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) {
-            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
-            mPrivateFlags |= PFLAG_INVALIDATED;
-            mPrivateFlags |= PFLAG_DIRTY;
-            final ViewParent p = mParent;
-            final AttachInfo ai = mAttachInfo;
-            if (p != null && ai != null) {
-                final int scrollX = mScrollX;
-                final int scrollY = mScrollY;
-                final Rect r = ai.mTmpInvalRect;
-                r.set(dirty.left - scrollX, dirty.top - scrollY,
-                        dirty.right - scrollX, dirty.bottom - scrollY);
-                mParent.invalidateChild(this, r);
-            }
-        }
+        final int scrollX = mScrollX;
+        final int scrollY = mScrollY;
+        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
+                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
     }
 
     /**
-     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn.
-     * The coordinates of the dirty rect are relative to the view.
-     * If the view is visible, {@link #onDraw(android.graphics.Canvas)}
-     * will be called at some point in the future. This must be called from
-     * a UI thread. To call from a non-UI thread, call {@link #postInvalidate()}.
+     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
+     * coordinates of the dirty rect are relative to the view. If the view is
+     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
+     * point in the future.
+     * <p>
+     * This must be called from a UI thread. To call from a non-UI thread, call
+     * {@link #postInvalidate()}.
+     *
      * @param l the left position of the dirty region
      * @param t the top position of the dirty region
      * @param r the right position of the dirty region
      * @param b the bottom position of the dirty region
      */
     public void invalidate(int l, int t, int r, int b) {
-        if (skipInvalidate()) {
-            return;
-        }
-        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
-                (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID ||
-                (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) {
-            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
-            mPrivateFlags |= PFLAG_INVALIDATED;
-            mPrivateFlags |= PFLAG_DIRTY;
-            final ViewParent p = mParent;
-            final AttachInfo ai = mAttachInfo;
-            if (p != null && ai != null && l < r && t < b) {
-                final int scrollX = mScrollX;
-                final int scrollY = mScrollY;
-                final Rect tmpr = ai.mTmpInvalRect;
-                tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY);
-                p.invalidateChild(this, tmpr);
-            }
-        }
+        final int scrollX = mScrollX;
+        final int scrollY = mScrollY;
+        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
     }
 
     /**
      * Invalidate the whole view. If the view is visible,
      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
-     * the future. This must be called from a UI thread. To call from a non-UI thread,
-     * call {@link #postInvalidate()}.
+     * the future.
+     * <p>
+     * This must be called from a UI thread. To call from a non-UI thread, call
+     * {@link #postInvalidate()}.
      */
     public void invalidate() {
         invalidate(true);
@@ -11531,38 +11513,108 @@
 
     /**
      * This is where the invalidate() work actually happens. A full invalidate()
-     * causes the drawing cache to be invalidated, but this function can be called with
-     * invalidateCache set to false to skip that invalidation step for cases that do not
-     * need it (for example, a component that remains at the same dimensions with the same
-     * content).
+     * causes the drawing cache to be invalidated, but this function can be
+     * called with invalidateCache set to false to skip that invalidation step
+     * for cases that do not need it (for example, a component that remains at
+     * the same dimensions with the same content).
      *
-     * @param invalidateCache Whether the drawing cache for this view should be invalidated as
-     * well. This is usually true for a full invalidate, but may be set to false if the
-     * View's contents or dimensions have not changed.
+     * @param invalidateCache Whether the drawing cache for this view should be
+     *            invalidated as well. This is usually true for a full
+     *            invalidate, but may be set to false if the View's contents or
+     *            dimensions have not changed.
      */
     void invalidate(boolean invalidateCache) {
+        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
+    }
+
+    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
+            boolean fullInvalidate) {
         if (skipInvalidate()) {
             return;
         }
-        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
-                (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) ||
-                (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED || isOpaque() != mLastIsOpaque) {
-            mLastIsOpaque = isOpaque();
-            mPrivateFlags &= ~PFLAG_DRAWN;
+
+        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
+                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
+                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
+                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
+            if (fullInvalidate) {
+                mLastIsOpaque = isOpaque();
+                mPrivateFlags &= ~PFLAG_DRAWN;
+            }
+
             mPrivateFlags |= PFLAG_DIRTY;
+
             if (invalidateCache) {
                 mPrivateFlags |= PFLAG_INVALIDATED;
                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
             }
+
+            // Propagate the damage rectangle to the parent view.
             final AttachInfo ai = mAttachInfo;
             final ViewParent p = mParent;
+            if (p != null && ai != null && l < r && t < b) {
+                final Rect damage = ai.mTmpInvalRect;
+                damage.set(l, t, r, b);
+                p.invalidateChild(this, damage);
+            }
 
-            if (p != null && ai != null) {
-                final Rect r = ai.mTmpInvalRect;
-                r.set(0, 0, mRight - mLeft, mBottom - mTop);
-                // Don't call invalidate -- we don't want to internally scroll
-                // our own bounds
-                p.invalidateChild(this, r);
+            // Damage the entire projection receiver, if necessary.
+            if (mBackground != null && mBackground.isProjected()) {
+                final View receiver = getProjectionReceiver();
+                if (receiver != null) {
+                    receiver.damageInParent();
+                }
+            }
+
+            // Damage the entire IsolatedZVolume recieving this view's shadow.
+            if (getCastsShadow() && getTranslationZ() != 0) {
+                damageIsolatedZVolume();
+            }
+        }
+    }
+
+    /**
+     * @return this view's projection receiver, or {@code null} if none exists
+     */
+    private View getProjectionReceiver() {
+        ViewParent p = getParent();
+        while (p != null && p instanceof View) {
+            final View v = (View) p;
+            if (v.isProjectionReceiver()) {
+                return v;
+            }
+            p = p.getParent();
+        }
+
+        return null;
+    }
+
+    /**
+     * @return whether the view is a projection receiver
+     */
+    private boolean isProjectionReceiver() {
+        return mBackground != null;
+    }
+
+    /**
+     * Damage area of the screen covered by the current isolated Z volume
+     *
+     * This method will guarantee that any changes to shadows cast by a View
+     * are damaged on the screen for future redraw.
+     */
+    private void damageIsolatedZVolume() {
+        final AttachInfo ai = mAttachInfo;
+        if (ai != null) {
+            ViewParent p = getParent();
+            while (p != null) {
+                if (p instanceof ViewGroup) {
+                    final ViewGroup vg = (ViewGroup) p;
+                    if (vg.hasIsolatedZVolume()) {
+                        vg.damageInParent();
+                        return;
+                    }
+                }
+                p = p.getParent();
             }
         }
     }
@@ -11593,16 +11645,28 @@
             }
             invalidate(false);
         } else {
-            final AttachInfo ai = mAttachInfo;
-            final ViewParent p = mParent;
-            if (p != null && ai != null) {
-                final Rect r = ai.mTmpInvalRect;
-                r.set(0, 0, mRight - mLeft, mBottom - mTop);
-                if (mParent instanceof ViewGroup) {
-                    ((ViewGroup) mParent).invalidateChildFast(this, r);
-                } else {
-                    mParent.invalidateChild(this, r);
-                }
+            damageInParent();
+        }
+        if (invalidateParent && getCastsShadow() && getTranslationZ() != 0) {
+            damageIsolatedZVolume();
+        }
+    }
+
+    /**
+     * Tells the parent view to damage this view's bounds.
+     *
+     * @hide
+     */
+    protected void damageInParent() {
+        final AttachInfo ai = mAttachInfo;
+        final ViewParent p = mParent;
+        if (p != null && ai != null) {
+            final Rect r = ai.mTmpInvalRect;
+            r.set(0, 0, mRight - mLeft, mBottom - mTop);
+            if (mParent instanceof ViewGroup) {
+                ((ViewGroup) mParent).invalidateChildFast(this, r);
+            } else {
+                mParent.invalidateChild(this, r);
             }
         }
     }
@@ -12475,7 +12539,7 @@
     }
 
     /**
-     * <p>Compute the vertical extent of the horizontal scrollbar's thumb
+     * <p>Compute the vertical extent of the vertical scrollbar's thumb
      * within the vertical range. This value is used to compute the length
      * of the thumb within the scrollbar's track.</p>
      *
@@ -12758,14 +12822,6 @@
             InputMethodManager imm = InputMethodManager.peekInstance();
             imm.focusIn(this);
         }
-
-        if (mDisplayList != null) {
-            mDisplayList.clearDirty();
-        }
-
-        if (mBackgroundDisplayList != null) {
-            mBackgroundDisplayList.clearDirty();
-        }
     }
 
     /**
@@ -13066,6 +13122,19 @@
      * @see #onAttachedToWindow()
      */
     protected void onDetachedFromWindow() {
+    }
+
+    /**
+     * This is a framework-internal mirror of onDetachedFromWindow() that's called
+     * after onDetachedFromWindow().
+     *
+     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
+     * The super method should be called at the end of the overriden method to ensure
+     * subclasses are destroyed first
+     *
+     * @hide
+     */
+    protected void onDetachedFromWindowInternal() {
         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
 
@@ -13083,20 +13152,9 @@
     }
 
     private void cleanupDraw() {
+        resetDisplayList();
         if (mAttachInfo != null) {
-            // Ensure the display lists are reset when the view root dies.
-            if (mDisplayList != null) {
-                mDisplayList.markDirty();
-                mAttachInfo.mViewRootImpl.enqueueDisplayList(mDisplayList);
-            }
-            if (mBackgroundDisplayList != null) {
-                mBackgroundDisplayList.markDirty();
-                mAttachInfo.mViewRootImpl.enqueueDisplayList(mBackgroundDisplayList);
-            }
             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
-        } else {
-            // Should never happen.
-            resetDisplayList();
         }
     }
 
@@ -13264,6 +13322,7 @@
         }
 
         onDetachedFromWindow();
+        onDetachedFromWindowInternal();
 
         ListenerInfo li = mListenerInfo;
         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
@@ -13565,11 +13624,7 @@
         }
 
         if (layerType == mLayerType) {
-            if (layerType != LAYER_TYPE_NONE && paint != mLayerPaint) {
-                mLayerPaint = paint == null ? new Paint() : paint;
-                invalidateParentCaches();
-                invalidate(true);
-            }
+            setLayerPaint(paint);
             return;
         }
 
@@ -13626,7 +13681,7 @@
             if (layerType == LAYER_TYPE_HARDWARE) {
                 HardwareLayer layer = getHardwareLayer();
                 if (layer != null) {
-                    layer.setLayerPaint(paint);
+                    layer.setLayerPaint(mLayerPaint);
                 }
                 invalidateViewProperty(false, false);
             } else {
@@ -13977,7 +14032,7 @@
                     }
                 }
             } finally {
-                displayList.end();
+                displayList.end(getHardwareRenderer(), canvas);
                 displayList.setCaching(caching);
                 if (isLayer) {
                     displayList.setLeftTopRightBottom(0, 0, width, height);
@@ -14006,23 +14061,14 @@
         return mDisplayList;
     }
 
-    private void clearDisplayList() {
-        if (mDisplayList != null) {
-            mDisplayList.clear();
-        }
-
-        if (mBackgroundDisplayList != null) {
-            mBackgroundDisplayList.clear();
-        }
-    }
-
     private void resetDisplayList() {
-        if (mDisplayList != null) {
-            mDisplayList.reset();
+        HardwareRenderer renderer = getHardwareRenderer();
+        if (mDisplayList != null && mDisplayList.isValid()) {
+            mDisplayList.destroyDisplayListData(renderer);
         }
 
-        if (mBackgroundDisplayList != null) {
-            mBackgroundDisplayList.reset();
+        if (mBackgroundDisplayList != null && mBackgroundDisplayList.isValid()) {
+            mBackgroundDisplayList.destroyDisplayListData(renderer);
         }
     }
 
@@ -14645,7 +14691,7 @@
                             alpha = t.getAlpha();
                         }
                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
-                            displayList.setMatrix(t.getMatrix());
+                            displayList.setStaticMatrix(t.getMatrix());
                         }
                     }
                 }
@@ -15236,9 +15282,9 @@
             mBackgroundSizeChanged = false;
         }
 
-
         // Attempt to use a display list if requested.
-        if (canvas != null && canvas.isHardwareAccelerated()) {
+        if (canvas.isHardwareAccelerated() && mAttachInfo != null
+                && mAttachInfo.mHardwareRenderer != null) {
             mBackgroundDisplayList = getDrawableDisplayList(background, mBackgroundDisplayList);
 
             final DisplayList displayList = mBackgroundDisplayList;
@@ -15278,7 +15324,7 @@
      * @param displayList Existing display list, or {@code null}
      * @return A valid display list for the specified drawable
      */
-    private static DisplayList getDrawableDisplayList(Drawable drawable, DisplayList displayList) {
+    private DisplayList getDrawableDisplayList(Drawable drawable, DisplayList displayList) {
         if (displayList == null) {
             displayList = DisplayList.create(drawable.getClass().getName());
         }
@@ -15288,7 +15334,7 @@
         final int height = bounds.height();
         final HardwareCanvas canvas = displayList.start(width, height);
         drawable.draw(canvas);
-        displayList.end();
+        displayList.end(getHardwareRenderer(), canvas);
 
         // Set up drawable properties that are view-independent.
         displayList.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
@@ -15642,11 +15688,6 @@
     @Override
     public void invalidateDrawable(Drawable drawable) {
         if (verifyDrawable(drawable)) {
-            if (drawable == mBackground && mBackgroundDisplayList != null) {
-                // We'll need to redraw the display list.
-                mBackgroundDisplayList.clear();
-            }
-
             final Rect dirty = drawable.getDirtyBounds();
             final int scrollX = mScrollX;
             final int scrollY = mScrollY;
@@ -18794,6 +18835,33 @@
         }
     }
 
+    /**
+     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
+     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
+     *                           a normal View or a ViewGroup with
+     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
+     * @hide
+     */
+    public void captureTransitioningViews(List<View> transitioningViews) {
+        if (getVisibility() == View.VISIBLE) {
+            transitioningViews.add(this);
+        }
+    }
+
+    /**
+     * Adds all Views that have {@link #getSharedElementName()} non-null to sharedElements.
+     * @param sharedElements Will contain all Views in the hierarchy having a shared element name.
+     * @hide
+     */
+    public void findSharedElements(Map<String, View> sharedElements) {
+        if (getVisibility() == VISIBLE) {
+            String sharedElementName = getSharedElementName();
+            if (sharedElementName != null) {
+                sharedElements.put(sharedElementName, this);
+            }
+        }
+    }
+
     //
     // Properties
     //
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 9cd3c9d..f9b9401 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -31,6 +31,7 @@
 import android.graphics.RectF;
 import android.graphics.Region;
 import android.os.Build;
+import android.os.Bundle;
 import android.os.Parcelable;
 import android.os.SystemClock;
 import android.util.AttributeSet;
@@ -50,6 +51,8 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
 
 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
 
@@ -512,7 +515,8 @@
 
     private void initFromAttributes(
             Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
-        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ViewGroup);
+        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ViewGroup, defStyleAttr,
+                defStyleRes);
 
         final int N = a.getIndexCount();
         for (int i = 0; i < N; i++) {
@@ -2300,14 +2304,13 @@
      * individually during the transition.
      * @return True if the ViewGroup should be acted on together during an Activity transition.
      * The default value is false when the background is null and true when the background
-     * is not null.
-     * @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)
+     * is not null or if {@link #getSharedElementName()} is not null.
      */
     public boolean isTransitionGroup() {
         if ((mGroupFlags & FLAG_IS_TRANSITION_GROUP_SET) != 0) {
             return ((mGroupFlags & FLAG_IS_TRANSITION_GROUP) != 0);
         } else {
-            return getBackground() != null;
+            return getBackground() != null || getSharedElementName() != null;
         }
     }
 
@@ -2318,7 +2321,6 @@
      *                          in Activity transitions. If false, the ViewGroup won't transition,
      *                          only its children. If true, the entire ViewGroup will transition
      *                          together.
-     * @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)
      */
     public void setTransitionGroup(boolean isTransitionGroup) {
         mGroupFlags |= FLAG_IS_TRANSITION_GROUP_SET;
@@ -2636,6 +2638,7 @@
         for (int i = 0; i < count; i++) {
             children[i].dispatchDetachedFromWindow();
         }
+        clearDisappearingChildren();
         super.dispatchDetachedFromWindow();
     }
 
@@ -3163,6 +3166,8 @@
      * @see #setIsolatedZVolume(boolean)
      *
      * @return True if the ViewGroup has an isolated Z volume.
+     *
+     * @hide
      */
     public boolean hasIsolatedZVolume() {
         return ((mGroupFlags & FLAG_ISOLATED_Z_VOLUME) != 0);
@@ -3177,6 +3182,8 @@
      *         ordering space, false if its decendents should inhabit the
      *         inherited Z ordering volume.
      * @attr ref android.R.styleable#ViewGroup_isolatedZVolume
+     *
+     * @hide
      */
     public void setIsolatedZVolume(boolean isolateZVolume) {
         boolean previousValue = (mGroupFlags & FLAG_ISOLATED_Z_VOLUME) != 0;
@@ -5303,8 +5310,17 @@
      * this if you don't want animations for exiting views to stack up.
      */
     public void clearDisappearingChildren() {
-        if (mDisappearingChildren != null) {
-            mDisappearingChildren.clear();
+        final ArrayList<View> disappearingChildren = mDisappearingChildren;
+        if (disappearingChildren != null) {
+            final int count = disappearingChildren.size();
+            for (int i = 0; i < count; i++) {
+                final View view = disappearingChildren.get(i);
+                if (view.mAttachInfo != null) {
+                    view.dispatchDetachedFromWindow();
+                }
+                view.clearAnimation();
+            }
+            disappearingChildren.clear();
             invalidate();
         }
     }
@@ -5880,6 +5896,37 @@
     protected void onSetLayoutParams(View child, LayoutParams layoutParams) {
     }
 
+    /** @hide */
+    @Override
+    public void captureTransitioningViews(List<View> transitioningViews) {
+        if (getVisibility() != View.VISIBLE) {
+            return;
+        }
+        if (isTransitionGroup()) {
+            transitioningViews.add(this);
+        } else {
+            int count = getChildCount();
+            for (int i = 0; i < count; i++) {
+                View child = getChildAt(i);
+                child.captureTransitioningViews(transitioningViews);
+            }
+        }
+    }
+
+    /** @hide */
+    @Override
+    public void findSharedElements(Map<String, View> sharedElements) {
+        if (getVisibility() != VISIBLE) {
+            return;
+        }
+        super.findSharedElements(sharedElements);
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            View child = getChildAt(i);
+            child.findSharedElements(sharedElements);
+        }
+    }
+
     /**
      * LayoutParams are used by views to tell their parents how they want to be
      * laid out. See
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index a13b184..18517c5 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -56,6 +56,7 @@
 import android.util.Log;
 import android.util.Slog;
 import android.util.TypedValue;
+import android.view.Surface.OutOfResourcesException;
 import android.view.View.AttachInfo;
 import android.view.View.MeasureSpec;
 import android.view.accessibility.AccessibilityEvent;
@@ -69,7 +70,6 @@
 import android.view.animation.Interpolator;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
-import android.view.Surface.OutOfResourcesException;
 import android.widget.Scroller;
 
 import com.android.internal.R;
@@ -264,10 +264,14 @@
     int mScrollY;
     int mCurScrollY;
     Scroller mScroller;
-//    HardwareLayer mResizeBuffer;
-//    long mResizeBufferStartTime;
-//    int mResizeBufferDuration;
-//    static final Interpolator mResizeInterpolator = new AccelerateDecelerateInterpolator();
+    HardwareLayer mResizeBuffer;
+    long mResizeBufferStartTime;
+    int mResizeBufferDuration;
+    // Used to block the creation of the ResizeBuffer due to invalidations in
+    // the previous DisplayList tree that must prevent re-execution.
+    // Currently this means a functor was detached.
+    boolean mBlockResizeBuffer;
+    static final Interpolator mResizeInterpolator = new AccelerateDecelerateInterpolator();
     private ArrayList<LayoutTransition> mPendingTransitions;
 
     final ViewConfiguration mViewConfiguration;
@@ -290,8 +294,6 @@
     private long mFpsPrevTime = -1;
     private int mFpsNumFrames;
 
-    private final ArrayList<DisplayList> mDisplayLists = new ArrayList<DisplayList>();
-
     /**
      * see {@link #playSoundEffect(int)}
      */
@@ -616,7 +618,6 @@
     }
 
     void destroyHardwareResources() {
-        invalidateDisplayLists();
         if (mAttachInfo.mHardwareRenderer != null) {
             mAttachInfo.mHardwareRenderer.destroyHardwareResources(mView);
             mAttachInfo.mHardwareRenderer.destroy(false);
@@ -630,7 +631,6 @@
                 HardwareRenderer.trimMemory(ComponentCallbacks2.TRIM_MEMORY_MODERATE);
             }
         } else {
-            invalidateDisplayLists();
             destroyHardwareLayer(mView);
         }
     }
@@ -667,6 +667,7 @@
     }
 
     public void detachFunctor(int functor) {
+        mBlockResizeBuffer = true;
         if (mAttachInfo.mHardwareRenderer != null) {
             mAttachInfo.mHardwareRenderer.detachFunctor(functor);
         }
@@ -931,17 +932,12 @@
         return mAppVisible ? mView.getVisibility() : View.GONE;
     }
 
-//    void disposeResizeBuffer() {
-//        if (mResizeBuffer != null && mAttachInfo.mHardwareRenderer != null) {
-//            mAttachInfo.mHardwareRenderer.safelyRun(new Runnable() {
-//                @Override
-//                public void run() {
-//                    mResizeBuffer.destroy();
-//                    mResizeBuffer = null;
-//                }
-//            });
-//        }
-//    }
+    void disposeResizeBuffer() {
+        if (mResizeBuffer != null) {
+            mResizeBuffer.destroy();
+            mResizeBuffer = null;
+        }
+    }
 
     /**
      * Add LayoutTransition to the list of transitions to be started in the next traversal.
@@ -1452,76 +1448,64 @@
                 final boolean visibleInsetsChanged = !mPendingVisibleInsets.equals(
                         mAttachInfo.mVisibleInsets);
                 if (contentInsetsChanged) {
-//                    TODO: Do something with this...
-//                    if (mWidth > 0 && mHeight > 0 && lp != null &&
-//                            ((lp.systemUiVisibility|lp.subtreeSystemUiVisibility)
-//                                    & View.SYSTEM_UI_LAYOUT_FLAGS) == 0 &&
-//                            mSurface != null && mSurface.isValid() &&
-//                            !mAttachInfo.mTurnOffWindowResizeAnim &&
-//                            mAttachInfo.mHardwareRenderer != null &&
-//                            mAttachInfo.mHardwareRenderer.isEnabled() &&
-//                            mAttachInfo.mHardwareRenderer.validate() &&
-//                            lp != null && !PixelFormat.formatHasAlpha(lp.format)) {
-//
-//                        disposeResizeBuffer();
-//
-//                        boolean completed = false;
-//                        HardwareCanvas hwRendererCanvas = mAttachInfo.mHardwareRenderer.getCanvas();
-//                        HardwareCanvas layerCanvas = null;
-//                        try {
-//                            if (mResizeBuffer == null) {
-//                                mResizeBuffer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
-//                                        mWidth, mHeight, false);
-//                            } else if (mResizeBuffer.getWidth() != mWidth ||
-//                                    mResizeBuffer.getHeight() != mHeight) {
-//                                mResizeBuffer.resize(mWidth, mHeight);
-//                            }
-//                            // TODO: should handle create/resize failure
-//                            layerCanvas = mResizeBuffer.start(hwRendererCanvas);
-//                            final int restoreCount = layerCanvas.save();
-//
-//                            int yoff;
-//                            final boolean scrolling = mScroller != null
-//                                    && mScroller.computeScrollOffset();
-//                            if (scrolling) {
-//                                yoff = mScroller.getCurrY();
-//                                mScroller.abortAnimation();
-//                            } else {
-//                                yoff = mScrollY;
-//                            }
-//
-//                            layerCanvas.translate(0, -yoff);
-//                            if (mTranslator != null) {
-//                                mTranslator.translateCanvas(layerCanvas);
-//                            }
-//
-//                            DisplayList displayList = mView.mDisplayList;
-//                            if (displayList != null && displayList.isValid()) {
-//                                layerCanvas.drawDisplayList(displayList, null,
-//                                        DisplayList.FLAG_CLIP_CHILDREN);
-//                            } else {
-//                                mView.draw(layerCanvas);
-//                            }
-//
-//                            drawAccessibilityFocusedDrawableIfNeeded(layerCanvas);
-//
-//                            mResizeBufferStartTime = SystemClock.uptimeMillis();
-//                            mResizeBufferDuration = mView.getResources().getInteger(
-//                                    com.android.internal.R.integer.config_mediumAnimTime);
-//                            completed = true;
-//
-//                            layerCanvas.restoreToCount(restoreCount);
-//                        } catch (OutOfMemoryError e) {
-//                            Log.w(TAG, "Not enough memory for content change anim buffer", e);
-//                        } finally {
-//                            if (mResizeBuffer != null) {
-//                                mResizeBuffer.end(hwRendererCanvas);
-//                                if (!completed) {
-//                                    disposeResizeBuffer();
-//                                }
-//                            }
-//                        }
-//                    }
+                    if (mWidth > 0 && mHeight > 0 && lp != null &&
+                            ((lp.systemUiVisibility|lp.subtreeSystemUiVisibility)
+                                    & View.SYSTEM_UI_LAYOUT_FLAGS) == 0 &&
+                            mSurface != null && mSurface.isValid() &&
+                            !mAttachInfo.mTurnOffWindowResizeAnim &&
+                            mAttachInfo.mHardwareRenderer != null &&
+                            mAttachInfo.mHardwareRenderer.isEnabled() &&
+                            lp != null && !PixelFormat.formatHasAlpha(lp.format)
+                            && !mBlockResizeBuffer) {
+
+                        disposeResizeBuffer();
+
+                        if (mResizeBuffer == null) {
+                            mResizeBuffer = mAttachInfo.mHardwareRenderer.createDisplayListLayer(
+                                    mWidth, mHeight);
+                        }
+                        mResizeBuffer.prepare(mWidth, mHeight, false);
+                        DisplayList layerDisplayList = mResizeBuffer.startRecording();
+                        HardwareCanvas layerCanvas = layerDisplayList.start(mWidth, mHeight);
+                        final int restoreCount = layerCanvas.save();
+
+                        int yoff;
+                        final boolean scrolling = mScroller != null
+                                && mScroller.computeScrollOffset();
+                        if (scrolling) {
+                            yoff = mScroller.getCurrY();
+                            mScroller.abortAnimation();
+                        } else {
+                            yoff = mScrollY;
+                        }
+
+                        layerCanvas.translate(0, -yoff);
+                        if (mTranslator != null) {
+                            mTranslator.translateCanvas(layerCanvas);
+                        }
+
+                        DisplayList displayList = mView.mDisplayList;
+                        if (displayList != null && displayList.isValid()) {
+                            layerCanvas.drawDisplayList(displayList, null,
+                                    DisplayList.FLAG_CLIP_CHILDREN);
+                        } else {
+                            mView.draw(layerCanvas);
+                        }
+
+                        drawAccessibilityFocusedDrawableIfNeeded(layerCanvas);
+
+                        mResizeBufferStartTime = SystemClock.uptimeMillis();
+                        mResizeBufferDuration = mView.getResources().getInteger(
+                                com.android.internal.R.integer.config_mediumAnimTime);
+
+                        layerCanvas.restoreToCount(restoreCount);
+                        layerDisplayList.end(mAttachInfo.mHardwareRenderer, layerCanvas);
+                        layerDisplayList.setCaching(true);
+                        layerDisplayList.setLeftTopRightBottom(0, 0, mWidth, mHeight);
+                        mTempRect.set(0, 0, mWidth, mHeight);
+                        mResizeBuffer.endRecording(mTempRect);
+                        mAttachInfo.mHardwareRenderer.flushLayerUpdates();
+                    }
                     mAttachInfo.mContentInsets.set(mPendingContentInsets);
                     if (DEBUG_LAYOUT) Log.v(TAG, "Content insets changing to: "
                             + mAttachInfo.mContentInsets);
@@ -1581,7 +1565,7 @@
                     if (mScroller != null) {
                         mScroller.abortAnimation();
                     }
-//                    disposeResizeBuffer();
+                    disposeResizeBuffer();
                     // Our surface is gone
                     if (mAttachInfo.mHardwareRenderer != null &&
                             mAttachInfo.mHardwareRenderer.isEnabled()) {
@@ -2180,10 +2164,10 @@
 
     @Override
     public void onHardwarePostDraw(HardwareCanvas canvas) {
-//        if (mResizeBuffer != null) {
-//            mResizePaint.setAlpha(mResizeAlpha);
-//            canvas.drawHardwareLayer(mResizeBuffer, 0.0f, mHardwareYOffset, mResizePaint);
-//        }
+        if (mResizeBuffer != null) {
+            mResizePaint.setAlpha(mResizeAlpha);
+            canvas.drawHardwareLayer(mResizeBuffer, 0.0f, mHardwareYOffset, mResizePaint);
+        }
         // TODO: this
         if (!HardwareRenderer.sUseRenderThread) {
             drawAccessibilityFocusedDrawableIfNeeded(canvas);
@@ -2342,17 +2326,17 @@
         final boolean scalingRequired = attachInfo.mScalingRequired;
 
         int resizeAlpha = 0;
-//        if (mResizeBuffer != null) {
-//            long deltaTime = SystemClock.uptimeMillis() - mResizeBufferStartTime;
-//            if (deltaTime < mResizeBufferDuration) {
-//                float amt = deltaTime/(float) mResizeBufferDuration;
-//                amt = mResizeInterpolator.getInterpolation(amt);
-//                animating = true;
-//                resizeAlpha = 255 - (int)(amt*255);
-//            } else {
-//                disposeResizeBuffer();
-//            }
-//        }
+        if (mResizeBuffer != null) {
+            long deltaTime = SystemClock.uptimeMillis() - mResizeBufferStartTime;
+            if (deltaTime < mResizeBufferDuration) {
+                float amt = deltaTime/(float) mResizeBufferDuration;
+                amt = mResizeInterpolator.getInterpolation(amt);
+                animating = true;
+                resizeAlpha = 255 - (int)(amt*255);
+            } else {
+                disposeResizeBuffer();
+            }
+        }
 
         final Rect dirty = mDirty;
         if (mSurfaceHolder != null) {
@@ -2362,7 +2346,7 @@
                 if (mScroller != null) {
                     mScroller.abortAnimation();
                 }
-//                disposeResizeBuffer();
+                disposeResizeBuffer();
             }
             return;
         }
@@ -2381,8 +2365,6 @@
                     appScale + ", width=" + mWidth + ", height=" + mHeight);
         }
 
-        invalidateDisplayLists();
-
         attachInfo.mTreeObserver.dispatchOnDraw();
 
         if (!dirty.isEmpty() || mIsAnimating) {
@@ -2395,6 +2377,7 @@
                 mCurrentDirty.set(dirty);
                 dirty.setEmpty();
 
+                mBlockResizeBuffer = false;
                 attachInfo.mHardwareRenderer.draw(mView, attachInfo, this,
                         animating ? null : mCurrentDirty);
             } else {
@@ -2599,20 +2582,6 @@
         return null;
     }
 
-    void invalidateDisplayLists() {
-        final ArrayList<DisplayList> displayLists = mDisplayLists;
-        final int count = displayLists.size();
-
-        for (int i = 0; i < count; i++) {
-            final DisplayList displayList = displayLists.get(i);
-            if (displayList.isDirty()) {
-                displayList.reset();
-            }
-        }
-
-        displayLists.clear();
-    }
-
     /**
      * @hide
      */
@@ -2725,7 +2694,7 @@
         if (scrollY != mScrollY) {
             if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Pan scroll changed: old="
                     + mScrollY + " , new=" + scrollY);
-            if (!immediate /*&& mResizeBuffer == null*/) {
+            if (!immediate && mResizeBuffer == null) {
                 if (mScroller == null) {
                     mScroller = new Scroller(mView.getContext());
                 }
@@ -2932,7 +2901,7 @@
             }
         }
     }
-
+    
     /**
      * Return true if child is an ancestor of parent, (or equal to the parent).
      */
@@ -5240,7 +5209,7 @@
         DisplayList displayList = view.mDisplayList;
         info[0]++;
         if (displayList != null) {
-            info[1] += displayList.getSize();
+            info[1] += 0; /* TODO: Memory used by display lists */
         }
 
         if (view instanceof ViewGroup) {
@@ -5288,7 +5257,6 @@
             }
 
             if (mAdded && !mFirst) {
-                invalidateDisplayLists();
                 destroyHardwareRenderer();
 
                 if (mView != null) {
@@ -5754,10 +5722,6 @@
         mInvalidateOnAnimationRunnable.addViewRect(info);
     }
 
-    public void enqueueDisplayList(DisplayList displayList) {
-        mDisplayLists.add(displayList);
-    }
-
     public void cancelInvalidate(View view) {
         mHandler.removeMessages(MSG_INVALIDATE, view);
         // fixme: might leak the AttachInfo.InvalidateInfo objects instead of returning
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 11740ab..0cd6325 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -29,9 +29,12 @@
 import android.os.IBinder;
 import android.os.SystemProperties;
 import android.transition.Scene;
+import android.transition.Transition;
 import android.transition.TransitionManager;
 import android.view.accessibility.AccessibilityEvent;
 
+import java.util.Map;
+
 /**
  * Abstract base class for a top-level window look and behavior policy.  An
  * instance of this class should be used as the top-level view added to the
@@ -95,6 +98,10 @@
      */
     public static final int FEATURE_ACTION_MODE_OVERLAY = 10;
     /**
+     * Flag for requesting a decoration-free window that is dismissed by swiping from the left.
+     */
+    public static final int FEATURE_SWIPE_TO_DISMISS = 11;
+    /**
      * Flag for requesting that window content changes should be represented
      * with scenes and transitions.
      *
@@ -102,7 +109,7 @@
      *
      * @see #setContentView
      */
-    public static final int FEATURE_CONTENT_TRANSITIONS = 11;
+    public static final int FEATURE_CONTENT_TRANSITIONS = 12;
 
     /**
      * Max value used as a feature ID
@@ -401,6 +408,12 @@
          * @param mode The mode that was just finished.
          */
         public void onActionModeFinished(ActionMode mode);
+
+        /**
+         * Called when a window is dismissed. This informs the callback that the
+         * window is gone, and it should finish itself.
+         */
+        public void onWindowDismissed();
     }
 
     public Window(Context context) {
@@ -1386,30 +1399,43 @@
      * @hide
      */
     public interface SceneTransitionListener {
-        void enterSharedElement(Bundle transitionArgs);
         void nullPendingTransition();
         void convertFromTranslucent();
         void convertToTranslucent();
+        void sharedElementStart(Transition transition);
+        void sharedElementEnd();
     }
 
     /**
-     * Controls how the background fade is triggered. If fadeEarly is true, the Window background
-     * will fade in as soon as the shared elements are ready to switch. If fadeEarly is false,
-     * the background will fade only after the calling Activity's exit transition completes.
-     * By default, the Window will fade in when the calling Activity's exit transition completes.
+     * Controls when the Activity enter scene is triggered and the background is faded in. If
+     * triggerEarly is true, the enter scene will begin as soon as possible and the background
+     * will fade in when all shared elements are ready to begin transitioning. If triggerEarly is
+     * false, the Activity enter scene and background fade will be triggered when the calling
+     * Activity's exit transition completes.
      *
-     * @param fadeEarly Set to true to fade out the exiting Activity as soon as the shared elements
-     *                  are transferred. Set to false to fade out the exiting Activity as soon as
-     *                  the shared element is transferred.
-     * @hide
+     * @param triggerEarly Set to true to have the Activity enter scene transition in as early as
+     *                     possible or set to false to wait for the calling Activity to exit first.
      */
-    public void setEarlyBackgroundTransition(boolean fadeEarly) {
+    public void setTriggerEarlyEnterTransition(boolean triggerEarly) {
     }
 
     /**
      * Start the exit transition.
      * @hide
      */
-    public void startExitTransition(ActivityOptions activityOptions) {
+    public Bundle startExitTransition(ActivityOptions options) {
+        return null;
+    }
+
+    /**
+     * On entering Activity Scene transitions, shared element names may be mapped from a
+     * source Activity's specified name to a unique shared element name in the View hierarchy.
+     * Under most circumstances, mapping is not necessary - a single View will have the
+     * shared element name given by the calling Activity. However, if there are several similar
+     * Views (e.g. in a ListView), the correct shared element must be mapped.
+     * @param sharedElementNames A mapping from the calling Activity's assigned shared element
+     *                           name to a unique shared element name in the View hierarchy.
+     */
+    public void mapTransitionTargets(Map<String, String> sharedElementNames) {
     }
 }
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 53a4c0d0..55956bf 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -98,7 +98,7 @@
      * the given view hierarchy's {@link View#onDetachedFromWindow()
      * View.onDetachedFromWindow()} methods before returning.  This is not
      * for normal applications; using it correctly requires great care.
-     * 
+     *
      * @param view The view to be removed.
      */
     public void removeViewImmediate(View view);
@@ -112,7 +112,7 @@
          */
         @ViewDebug.ExportedProperty
         public int x;
-        
+
         /**
          * Y position for this window.  With the default gravity it is ignored.
          * When using {@link Gravity#TOP} or {@link Gravity#BOTTOM} it provides
@@ -161,7 +161,7 @@
          * be used by applications, and a special permission is required
          * to use them.
          * </ul>
-         * 
+         *
          * @see #TYPE_BASE_APPLICATION
          * @see #TYPE_APPLICATION
          * @see #TYPE_APPLICATION_STARTING
@@ -223,12 +223,12 @@
             @ViewDebug.IntToString(from = TYPE_PRIVATE_PRESENTATION, to = "TYPE_PRIVATE_PRESENTATION")
         })
         public int type;
-    
+
         /**
          * Start of window types that represent normal application windows.
          */
         public static final int FIRST_APPLICATION_WINDOW = 1;
-        
+
         /**
          * Window type: an application window that serves as the "base" window
          * of the overall application; all other application windows will
@@ -236,14 +236,14 @@
          * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_BASE_APPLICATION   = 1;
-        
+
         /**
          * Window type: a normal application window.  The {@link #token} must be
          * an Activity token identifying who the window belongs to.
          * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_APPLICATION        = 2;
-    
+
         /**
          * Window type: special application window that is displayed while the
          * application is starting.  Not for use by applications themselves;
@@ -252,12 +252,12 @@
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_APPLICATION_STARTING = 3;
-    
+
         /**
          * End of types of application windows.
          */
         public static final int LAST_APPLICATION_WINDOW = 99;
-    
+
         /**
          * Start of types of sub-windows.  The {@link #token} of these windows
          * must be set to the window they are attached to.  These types of
@@ -265,19 +265,19 @@
          * coordinate space is relative to their attached window.
          */
         public static final int FIRST_SUB_WINDOW        = 1000;
-    
+
         /**
          * Window type: a panel on top of an application window.  These windows
          * appear on top of their attached window.
          */
         public static final int TYPE_APPLICATION_PANEL  = FIRST_SUB_WINDOW;
-    
+
         /**
          * Window type: window for showing media (such as video).  These windows
          * are displayed behind their attached window.
          */
         public static final int TYPE_APPLICATION_MEDIA  = FIRST_SUB_WINDOW+1;
-    
+
         /**
          * Window type: a sub-panel on top of an application window.  These
          * windows are displayed on top their attached window and any
@@ -290,7 +290,7 @@
          * as a child of its container.
          */
         public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3;
-        
+
         /**
          * Window type: window for showing overlays on top of media windows.
          * These windows are displayed between TYPE_APPLICATION_MEDIA and the
@@ -299,18 +299,18 @@
          * @hide
          */
         public static final int TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW+4;
-    
+
         /**
          * End of types of sub-windows.
          */
         public static final int LAST_SUB_WINDOW         = 1999;
-        
+
         /**
          * Start of system-specific window types.  These are not normally
          * created by applications.
          */
         public static final int FIRST_SYSTEM_WINDOW     = 2000;
-    
+
         /**
          * Window type: the status bar.  There can be only one status bar
          * window; it is placed at the top of the screen, and all other
@@ -318,14 +318,14 @@
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_STATUS_BAR         = FIRST_SYSTEM_WINDOW;
-    
+
         /**
          * Window type: the search bar.  There can be only one search bar
          * window; it is placed at the top of the screen.
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_SEARCH_BAR         = FIRST_SYSTEM_WINDOW+1;
-    
+
         /**
          * Window type: phone.  These are non-application windows providing
          * user interaction with the phone (in particular incoming calls).
@@ -334,26 +334,26 @@
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_PHONE              = FIRST_SYSTEM_WINDOW+2;
-    
+
         /**
          * Window type: system window, such as low power alert. These windows
          * are always on top of application windows.
          * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_SYSTEM_ALERT       = FIRST_SYSTEM_WINDOW+3;
-        
+
         /**
          * Window type: keyguard window.
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4;
-        
+
         /**
          * Window type: transient notifications.
          * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_TOAST              = FIRST_SYSTEM_WINDOW+5;
-        
+
         /**
          * Window type: system overlay windows, which need to be displayed
          * on top of everything else.  These windows must not take input
@@ -361,7 +361,7 @@
          * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_SYSTEM_OVERLAY     = FIRST_SYSTEM_WINDOW+6;
-        
+
         /**
          * Window type: priority phone UI, which needs to be displayed even if
          * the keyguard is active.  These windows must not take input
@@ -369,26 +369,26 @@
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_PRIORITY_PHONE     = FIRST_SYSTEM_WINDOW+7;
-        
+
         /**
          * Window type: panel that slides out from the status bar
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_SYSTEM_DIALOG      = FIRST_SYSTEM_WINDOW+8;
-    
+
         /**
          * Window type: dialogs that the keyguard shows
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_KEYGUARD_DIALOG    = FIRST_SYSTEM_WINDOW+9;
-        
+
         /**
          * Window type: internal system error windows, appear on top of
          * everything they can.
          * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_SYSTEM_ERROR       = FIRST_SYSTEM_WINDOW+10;
-        
+
         /**
          * Window type: internal input methods windows, which appear above
          * the normal UI.  Application windows may be resized or panned to keep
@@ -559,16 +559,16 @@
         /** @deprecated this is ignored, this value is set automatically when needed. */
         @Deprecated
         public static final int MEMORY_TYPE_PUSH_BUFFERS = 3;
-        
+
         /**
          * @deprecated this is ignored
          */
         @Deprecated
         public int memoryType;
-        
+
         /** Window flag: as long as this window is visible to the user, allow
-         *  the lock screen to activate while the screen is on. 
-         *  This can be used independently, or in combination with 
+         *  the lock screen to activate while the screen is on.
+         *  This can be used independently, or in combination with
          *  {@link #FLAG_KEEP_SCREEN_ON} and/or {@link #FLAG_SHOW_WHEN_LOCKED} */
         public static final int FLAG_ALLOW_LOCK_WHILE_SCREEN_ON     = 0x00000001;
 
@@ -586,47 +586,47 @@
          * instead go to whatever focusable window is behind it.  This flag
          * will also enable {@link #FLAG_NOT_TOUCH_MODAL} whether or not that
          * is explicitly set.
-         * 
+         *
          * <p>Setting this flag also implies that the window will not need to
          * interact with
-         * a soft input method, so it will be Z-ordered and positioned 
+         * a soft input method, so it will be Z-ordered and positioned
          * independently of any active input method (typically this means it
          * gets Z-ordered on top of the input method, so it can use the full
          * screen for its content and cover the input method if needed.  You
          * can use {@link #FLAG_ALT_FOCUSABLE_IM} to modify this behavior. */
         public static final int FLAG_NOT_FOCUSABLE      = 0x00000008;
-        
+
         /** Window flag: this window can never receive touch events. */
         public static final int FLAG_NOT_TOUCHABLE      = 0x00000010;
-        
+
         /** Window flag: even when this window is focusable (its
          * {@link #FLAG_NOT_FOCUSABLE} is not set), allow any pointer events
          * outside of the window to be sent to the windows behind it.  Otherwise
          * it will consume all pointer events itself, regardless of whether they
          * are inside of the window. */
         public static final int FLAG_NOT_TOUCH_MODAL    = 0x00000020;
-        
+
         /** Window flag: when set, if the device is asleep when the touch
          * screen is pressed, you will receive this first touch event.  Usually
          * the first touch event is consumed by the system since the user can
          * not see what they are pressing on.
          */
         public static final int FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040;
-        
+
         /** Window flag: as long as this window is visible to the user, keep
          *  the device's screen turned on and bright. */
         public static final int FLAG_KEEP_SCREEN_ON     = 0x00000080;
-        
+
         /** Window flag: place the window within the entire screen, ignoring
          *  decorations around the border (such as the status bar).  The
          *  window must correctly position its contents to take the screen
          *  decoration into account.  This flag is normally set for you
          *  by Window as described in {@link Window#setFlags}. */
         public static final int FLAG_LAYOUT_IN_SCREEN   = 0x00000100;
-        
+
         /** Window flag: allow window to extend outside of the screen. */
         public static final int FLAG_LAYOUT_NO_LIMITS   = 0x00000200;
-        
+
         /**
          * Window flag: hide all screen decorations (such as the status bar) while
          * this window is displayed.  This allows the window to use the entire
@@ -648,17 +648,17 @@
          * {@link android.R.style#Theme_DeviceDefault_Light_NoActionBar_Fullscreen}.</p>
          */
         public static final int FLAG_FULLSCREEN      = 0x00000400;
-        
+
         /** Window flag: override {@link #FLAG_FULLSCREEN} and force the
          *  screen decorations (such as the status bar) to be shown. */
         public static final int FLAG_FORCE_NOT_FULLSCREEN   = 0x00000800;
-        
+
         /** Window flag: turn on dithering when compositing this window to
          *  the screen.
          * @deprecated This flag is no longer used. */
         @Deprecated
         public static final int FLAG_DITHER             = 0x00001000;
-        
+
         /** Window flag: treat the content of the window as secure, preventing
          * it from appearing in screenshots or from being viewed on non-secure
          * displays.
@@ -667,21 +667,21 @@
          * secure surfaces and secure displays.
          */
         public static final int FLAG_SECURE             = 0x00002000;
-        
+
         /** Window flag: a special mode where the layout parameters are used
          * to perform scaling of the surface when it is composited to the
          * screen. */
         public static final int FLAG_SCALED             = 0x00004000;
-        
+
         /** Window flag: intended for windows that will often be used when the user is
          * holding the screen against their face, it will aggressively filter the event
          * stream to prevent unintended presses in this situation that may not be
-         * desired for a particular window, when such an event stream is detected, the 
+         * desired for a particular window, when such an event stream is detected, the
          * application will receive a CANCEL motion event to indicate this so applications
-         * can handle this accordingly by taking no action on the event 
+         * can handle this accordingly by taking no action on the event
          * until the finger is released. */
         public static final int FLAG_IGNORE_CHEEK_PRESSES    = 0x00008000;
-        
+
         /** Window flag: a special option only for use in combination with
          * {@link #FLAG_LAYOUT_IN_SCREEN}.  When requesting layout in the
          * screen your window may appear on top of or behind screen decorations
@@ -690,7 +690,7 @@
          * content is not covered by screen decorations.  This flag is normally
          * set for you by Window as described in {@link Window#setFlags}.*/
         public static final int FLAG_LAYOUT_INSET_DECOR = 0x00010000;
-        
+
         /** Window flag: invert the state of {@link #FLAG_NOT_FOCUSABLE} with
          * respect to how this window interacts with the current method.  That
          * is, if FLAG_NOT_FOCUSABLE is set and this flag is set, then the
@@ -701,7 +701,7 @@
          * to use more space and cover the input method.
          */
         public static final int FLAG_ALT_FOCUSABLE_IM = 0x00020000;
-        
+
         /** Window flag: if you have set {@link #FLAG_NOT_TOUCH_MODAL}, you
          * can set this flag to receive a single special MotionEvent with
          * the action
@@ -711,7 +711,7 @@
          * first down as an ACTION_OUTSIDE.
          */
         public static final int FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000;
-        
+
         /** Window flag: special flag to let windows be shown when the screen
          * is locked. This will let application windows take precedence over
          * key guard or any other lock screens. Can be used with
@@ -741,13 +741,13 @@
          * {@link android.R.style#Theme_DeviceDefault_Wallpaper_NoTitleBar}.</p>
          */
         public static final int FLAG_SHOW_WALLPAPER = 0x00100000;
-        
+
         /** Window flag: when set as a window is being added or made
          * visible, once the window has been shown then the system will
          * poke the power manager's user activity (as if the user had woken
          * up the device) to turn the screen on. */
         public static final int FLAG_TURN_SCREEN_ON = 0x00200000;
-        
+
         /** Window flag: when set the window will cause the keyguard to
          * be dismissed, only if it is not a secure lock keyguard.  Because such
          * a keyguard is not needed for security, it will never re-appear if
@@ -761,7 +761,7 @@
          * also been set.
          */
         public static final int FLAG_DISMISS_KEYGUARD = 0x00400000;
-        
+
         /** Window flag: when set the window will accept for touch events
          * outside of its bounds to be sent to other windows that also
          * support split touch.  When this flag is not set, the first pointer
@@ -773,7 +773,7 @@
          * to be split across multiple windows.
          */
         public static final int FLAG_SPLIT_TOUCH = 0x00800000;
-        
+
         /**
          * <p>Indicates whether this window should be hardware accelerated.
          * Requesting hardware acceleration does not guarantee it will happen.</p>
@@ -916,7 +916,7 @@
 
         /**
          * Various behavioral options/flags.  Default is none.
-         * 
+         *
          * @see #FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
          * @see #FLAG_DIM_BEHIND
          * @see #FLAG_NOT_FOCUSABLE
@@ -1014,10 +1014,10 @@
          * as if it was.
          * Like {@link #FLAG_HARDWARE_ACCELERATED} except for trusted system windows
          * that need hardware acceleration (e.g. LockScreen), where hardware acceleration
-         * is generally disabled. This flag must be specified in addition to 
+         * is generally disabled. This flag must be specified in addition to
          * {@link #FLAG_HARDWARE_ACCELERATED} to enable hardware acceleration for system
          * windows.
-         * 
+         *
          * @hide
          */
         public static final int PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED = 0x00000001;
@@ -1028,7 +1028,7 @@
          * If certain parts of the UI that really do want to use hardware
          * acceleration, this flag can be set to force it.  This is basically
          * for the lock screen.  Anyone else using it, you are probably wrong.
-         * 
+         *
          * @hide
          */
         public static final int PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED = 0x00000002;
@@ -1086,6 +1086,11 @@
          * {@hide} */
         public static final int PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR = 0x00000200;
 
+        /** Window flag: the window is backed by a video plane, instead of a
+         * regular surface.
+         * {@hide} */
+        public static final int PRIVATE_FLAG_VIDEO_PLANE = 0x00000400;
+
         /**
          * Control flags that are private to the platform.
          * @hide
@@ -1100,9 +1105,9 @@
          * flags and returns true if the combination of the two corresponds
          * to a window that needs to be behind the input method so that the
          * user can type into it.
-         * 
+         *
          * @param flags The current window manager flags.
-         * 
+         *
          * @return Returns true if such a window should be behind/interact
          * with an input method, false if not.
          */
@@ -1114,63 +1119,63 @@
             }
             return false;
         }
-        
+
         /**
          * Mask for {@link #softInputMode} of the bits that determine the
          * desired visibility state of the soft input area for this window.
          */
         public static final int SOFT_INPUT_MASK_STATE = 0x0f;
-        
+
         /**
          * Visibility state for {@link #softInputMode}: no state has been specified.
          */
         public static final int SOFT_INPUT_STATE_UNSPECIFIED = 0;
-        
+
         /**
          * Visibility state for {@link #softInputMode}: please don't change the state of
          * the soft input area.
          */
         public static final int SOFT_INPUT_STATE_UNCHANGED = 1;
-        
+
         /**
          * Visibility state for {@link #softInputMode}: please hide any soft input
          * area when normally appropriate (when the user is navigating
          * forward to your window).
          */
         public static final int SOFT_INPUT_STATE_HIDDEN = 2;
-        
+
         /**
          * Visibility state for {@link #softInputMode}: please always hide any
          * soft input area when this window receives focus.
          */
         public static final int SOFT_INPUT_STATE_ALWAYS_HIDDEN = 3;
-        
+
         /**
          * Visibility state for {@link #softInputMode}: please show the soft
          * input area when normally appropriate (when the user is navigating
          * forward to your window).
          */
         public static final int SOFT_INPUT_STATE_VISIBLE = 4;
-        
+
         /**
          * Visibility state for {@link #softInputMode}: please always make the
          * soft input area visible when this window receives input focus.
          */
         public static final int SOFT_INPUT_STATE_ALWAYS_VISIBLE = 5;
-        
+
         /**
          * Mask for {@link #softInputMode} of the bits that determine the
          * way that the window should be adjusted to accommodate the soft
          * input window.
          */
         public static final int SOFT_INPUT_MASK_ADJUST = 0xf0;
-        
+
         /** Adjustment option for {@link #softInputMode}: nothing specified.
          * The system will try to pick one or
          * the other depending on the contents of the window.
          */
         public static final int SOFT_INPUT_ADJUST_UNSPECIFIED = 0x00;
-        
+
         /** Adjustment option for {@link #softInputMode}: set to allow the
          * window to be resized when an input
          * method is shown, so that its contents are not covered by the input
@@ -1183,7 +1188,7 @@
          * not resize, but will stay fullscreen.
          */
         public static final int SOFT_INPUT_ADJUST_RESIZE = 0x10;
-        
+
         /** Adjustment option for {@link #softInputMode}: set to have a window
          * pan when an input method is
          * shown, so it doesn't need to deal with resizing but just panned
@@ -1193,7 +1198,7 @@
          * the other depending on the contents of the window.
          */
         public static final int SOFT_INPUT_ADJUST_PAN = 0x20;
-        
+
         /** Adjustment option for {@link #softInputMode}: set to have a window
          * not adjust for a shown input method.  The window will not be resized,
          * and it will not be panned to make its focus visible.
@@ -1212,7 +1217,7 @@
         /**
          * Desired operating mode for any soft input area.  May be any combination
          * of:
-         * 
+         *
          * <ul>
          * <li> One of the visibility states
          * {@link #SOFT_INPUT_STATE_UNSPECIFIED}, {@link #SOFT_INPUT_STATE_UNCHANGED},
@@ -1229,7 +1234,7 @@
          * {@link android.R.attr#windowSoftInputMode} attribute.</p>
          */
         public int softInputMode;
-        
+
         /**
          * Placement of window within the screen as per {@link Gravity}.  Both
          * {@link Gravity#apply(int, int, int, android.graphics.Rect, int, int,
@@ -1246,7 +1251,7 @@
          * @see Gravity
          */
         public int gravity;
-    
+
         /**
          * The horizontal margin, as a percentage of the container's width,
          * between the container and the widget.  See
@@ -1255,7 +1260,7 @@
          * field is added with {@link #x} to supply the <var>xAdj</var> parameter.
          */
         public float horizontalMargin;
-    
+
         /**
          * The vertical margin, as a percentage of the container's height,
          * between the container and the widget.  See
@@ -1264,26 +1269,26 @@
          * field is added with {@link #y} to supply the <var>yAdj</var> parameter.
          */
         public float verticalMargin;
-    
+
         /**
          * The desired bitmap format.  May be one of the constants in
          * {@link android.graphics.PixelFormat}.  Default is OPAQUE.
          */
         public int format;
-    
+
         /**
          * A style resource defining the animations to use for this window.
          * This must be a system resource; it can not be an application resource
          * because the window manager does not have access to applications.
          */
         public int windowAnimations;
-    
+
         /**
          * An alpha value to apply to this entire window.
          * An alpha of 1.0 means fully opaque and 0.0 means fully transparent
          */
         public float alpha = 1.0f;
-    
+
         /**
          * When {@link #FLAG_DIM_BEHIND} is set, this is the amount of dimming
          * to apply.  Range is from 1.0 for completely opaque to 0.0 for no
@@ -1311,7 +1316,7 @@
          * to the hightest value when this window is in front.
          */
         public static final float BRIGHTNESS_OVERRIDE_FULL = 1.0f;
-    
+
         /**
          * This can be used to override the user's preferred brightness of
          * the screen.  A value of less than 0, the default, means to use the
@@ -1319,7 +1324,7 @@
          * dark to full bright.
          */
         public float screenBrightness = BRIGHTNESS_OVERRIDE_NONE;
-        
+
         /**
          * This can be used to override the standard behavior of the button and
          * keyboard backlights.  A value of less than 0, the default, means to
@@ -1353,7 +1358,7 @@
          * opaque windows have the #FLAG_FULLSCREEN bit set and are not covered
          * by other windows. All other situations default to the
          * {@link #ROTATION_ANIMATION_ROTATE} behavior.
-         * 
+         *
          * @see #ROTATION_ANIMATION_ROTATE
          * @see #ROTATION_ANIMATION_CROSSFADE
          * @see #ROTATION_ANIMATION_JUMPCUT
@@ -1365,18 +1370,18 @@
          * you.
          */
         public IBinder token = null;
-    
+
         /**
          * Name of the package owning this window.
          */
         public String packageName = null;
-        
+
         /**
          * Specific orientation value for a window.
          * May be any of the same values allowed
-         * for {@link android.content.pm.ActivityInfo#screenOrientation}. 
-         * If not set, a default value of 
-         * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} 
+         * for {@link android.content.pm.ActivityInfo#screenOrientation}.
+         * If not set, a default value of
+         * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED}
          * will be used.
          */
         public int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -1398,7 +1403,7 @@
 
         /**
          * Get callbacks about the system ui visibility changing.
-         * 
+         *
          * TODO: Maybe there should be a bitfield of optional callbacks that we need.
          *
          * @hide
@@ -1464,34 +1469,34 @@
             type = TYPE_APPLICATION;
             format = PixelFormat.OPAQUE;
         }
-        
+
         public LayoutParams(int _type) {
             super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
             type = _type;
             format = PixelFormat.OPAQUE;
         }
-    
+
         public LayoutParams(int _type, int _flags) {
             super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
             type = _type;
             flags = _flags;
             format = PixelFormat.OPAQUE;
         }
-    
+
         public LayoutParams(int _type, int _flags, int _format) {
             super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
             type = _type;
             flags = _flags;
             format = _format;
         }
-        
+
         public LayoutParams(int w, int h, int _type, int _flags, int _format) {
             super(w, h);
             type = _type;
             flags = _flags;
             format = _format;
         }
-        
+
         public LayoutParams(int w, int h, int xpos, int ypos, int _type,
                 int _flags, int _format) {
             super(w, h);
@@ -1501,18 +1506,18 @@
             flags = _flags;
             format = _format;
         }
-    
+
         public final void setTitle(CharSequence title) {
             if (null == title)
                 title = "";
-    
+
             mTitle = TextUtils.stringOrSpannedString(title);
         }
-    
+
         public final CharSequence getTitle() {
             return mTitle;
         }
-    
+
         public int describeContents() {
             return 0;
         }
@@ -1546,19 +1551,19 @@
             out.writeInt(inputFeatures);
             out.writeLong(userActivityTimeout);
         }
-        
+
         public static final Parcelable.Creator<LayoutParams> CREATOR
                     = new Parcelable.Creator<LayoutParams>() {
             public LayoutParams createFromParcel(Parcel in) {
                 return new LayoutParams(in);
             }
-    
+
             public LayoutParams[] newArray(int size) {
                 return new LayoutParams[size];
             }
         };
-    
-    
+
+
         public LayoutParams(Parcel in) {
             width = in.readInt();
             height = in.readInt();
@@ -1588,7 +1593,7 @@
             inputFeatures = in.readInt();
             userActivityTimeout = in.readLong();
         }
-    
+
         @SuppressWarnings({"PointlessBitwiseExpression"})
         public static final int LAYOUT_CHANGED = 1<<0;
         public static final int TYPE_CHANGED = 1<<1;
@@ -1622,10 +1627,10 @@
 
         // internal buffer to backup/restore parameters under compatibility mode.
         private int[] mCompatibilityParamsBackup = null;
-        
+
         public final int copyFrom(LayoutParams o) {
             int changes = 0;
-    
+
             if (width != o.width) {
                 width = o.width;
                 changes |= LAYOUT_CHANGED;
@@ -1724,7 +1729,7 @@
                 rotationAnimation = o.rotationAnimation;
                 changes |= ROTATION_ANIMATION_CHANGED;
             }
-    
+
             if (screenOrientation != o.screenOrientation) {
                 screenOrientation = o.screenOrientation;
                 changes |= SCREEN_ORIENTATION_CHANGED;
@@ -1754,7 +1759,7 @@
 
             return changes;
         }
-    
+
         @Override
         public String debug(String output) {
             output += "Contents of " + this + ":";
@@ -1765,7 +1770,7 @@
             Log.d("Debug", "WindowManager.LayoutParams={title=" + mTitle + "}");
             return "";
         }
-    
+
         @Override
         public String toString() {
             StringBuilder sb = new StringBuilder(256);
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 4fdbc1e..560d0c9 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -282,6 +282,22 @@
      */
     public static final int ACTION_DISMISS = 0x00100000;
 
+    /**
+     * Action that sets the text of the node. Performing the action without argument, using <code>
+     * null</code> or empty {@link CharSequence} will clear the text. This action will also put the
+     * cursor at the end of text.
+     * <p>
+     * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE}<br>
+     * <strong>Example:</strong>
+     * <code><pre><p>
+     *   Bundle arguments = new Bundle();
+     *   arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
+     *       "android");
+     *   info.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
+     * </code></pre></p>
+     */
+    public static final int ACTION_SET_TEXT = 0x00200000;
+
     // Action arguments
 
     /**
@@ -351,6 +367,18 @@
     public static final String ACTION_ARGUMENT_SELECTION_END_INT =
             "ACTION_ARGUMENT_SELECTION_END_INT";
 
+    /**
+     * Argument for specifying the text content to set
+     * <p>
+     * <strong>Type:</strong> CharSequence<br>
+     * <strong>Actions:</strong> {@link #ACTION_SET_TEXT}
+     * </p>
+     *
+     * @see #ACTION_SET_TEXT
+     */
+    public static final String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE =
+            "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE";
+
     // Focus types
 
     /**
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 5df5811..f8160c8 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -1,12 +1,12 @@
 /*
  * Copyright (C) 2007-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
@@ -37,6 +37,7 @@
 import android.util.Slog;
 import android.util.Xml;
 import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
+import android.view.inputmethod.InputMethodSubtypeArray;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -64,7 +65,7 @@
      * The Service that implements this input method component.
      */
     final ResolveInfo mService;
-    
+
     /**
      * The unique string Id to identify the input method.  This is generated
      * from the input method component.
@@ -86,9 +87,9 @@
     final int mIsDefaultResId;
 
     /**
-     * The array of the subtypes.
+     * An array-like container of the subtypes.
      */
-    private final ArrayList<InputMethodSubtype> mSubtypes = new ArrayList<InputMethodSubtype>();
+    private final InputMethodSubtypeArray mSubtypes;
 
     private final boolean mIsAuxIme;
 
@@ -138,28 +139,29 @@
         int isDefaultResId = 0;
 
         XmlResourceParser parser = null;
+        final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
         try {
             parser = si.loadXmlMetaData(pm, InputMethod.SERVICE_META_DATA);
             if (parser == null) {
                 throw new XmlPullParserException("No "
                         + InputMethod.SERVICE_META_DATA + " meta-data");
             }
-        
+
             Resources res = pm.getResourcesForApplication(si.applicationInfo);
-            
+
             AttributeSet attrs = Xml.asAttributeSet(parser);
-            
+
             int type;
             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
                     && type != XmlPullParser.START_TAG) {
             }
-            
+
             String nodeName = parser.getName();
             if (!"input-method".equals(nodeName)) {
                 throw new XmlPullParserException(
                         "Meta-data does not start with input-method tag");
             }
-            
+
             TypedArray sa = res.obtainAttributes(attrs,
                     com.android.internal.R.styleable.InputMethod);
             settingsActivityComponent = sa.getString(
@@ -206,7 +208,7 @@
                     if (!subtype.isAuxiliary()) {
                         isAuxIme = false;
                     }
-                    mSubtypes.add(subtype);
+                    subtypes.add(subtype);
                 }
             }
         } catch (NameNotFoundException e) {
@@ -216,7 +218,7 @@
             if (parser != null) parser.close();
         }
 
-        if (mSubtypes.size() == 0) {
+        if (subtypes.size() == 0) {
             isAuxIme = false;
         }
 
@@ -225,14 +227,15 @@
             final int N = additionalSubtypes.size();
             for (int i = 0; i < N; ++i) {
                 final InputMethodSubtype subtype = additionalSubtypes.get(i);
-                if (!mSubtypes.contains(subtype)) {
-                    mSubtypes.add(subtype);
+                if (!subtypes.contains(subtype)) {
+                    subtypes.add(subtype);
                 } else {
                     Slog.w(TAG, "Duplicated subtype definition found: "
                             + subtype.getLocale() + ", " + subtype.getMode());
                 }
             }
         }
+        mSubtypes = new InputMethodSubtypeArray(subtypes);
         mSettingsActivityName = settingsActivityComponent;
         mIsDefaultResId = isDefaultResId;
         mIsAuxIme = isAuxIme;
@@ -246,7 +249,7 @@
         mIsAuxIme = source.readInt() == 1;
         mSupportsSwitchingToNextInputMethod = source.readInt() == 1;
         mService = ResolveInfo.CREATOR.createFromParcel(source);
-        source.readTypedList(mSubtypes, InputMethodSubtype.CREATOR);
+        mSubtypes = new InputMethodSubtypeArray(source);
         mForceDefault = false;
     }
 
@@ -272,9 +275,7 @@
         mSettingsActivityName = settingsActivity;
         mIsDefaultResId = isDefaultResId;
         mIsAuxIme = isAuxIme;
-        if (subtypes != null) {
-            mSubtypes.addAll(subtypes);
-        }
+        mSubtypes = new InputMethodSubtypeArray(subtypes);
         mForceDefault = forceDefault;
         mSupportsSwitchingToNextInputMethod = true;
     }
@@ -338,7 +339,7 @@
 
     /**
      * Load the user-displayed label for this input method.
-     * 
+     *
      * @param pm Supply a PackageManager used to load the input method's
      * resources.
      */
@@ -348,7 +349,7 @@
 
     /**
      * Load the user-displayed icon for this input method.
-     * 
+     *
      * @param pm Supply a PackageManager used to load the input method's
      * resources.
      */
@@ -362,9 +363,9 @@
      * an {@link android.content.Intent} whose action is MAIN and with an
      * explicit {@link android.content.ComponentName}
      * composed of {@link #getPackageName} and the class name returned here.
-     * 
+     *
      * <p>A null will be returned if there is no settings activity associated
-     * with the input method.
+     * with the input method.</p>
      */
     public String getSettingsActivity() {
         return mSettingsActivityName;
@@ -374,7 +375,7 @@
      * Return the count of the subtypes of Input Method.
      */
     public int getSubtypeCount() {
-        return mSubtypes.size();
+        return mSubtypes.getCount();
     }
 
     /**
@@ -419,7 +420,7 @@
         pw.println(prefix + "Service:");
         mService.dump(pw, prefix + "  ");
     }
-    
+
     @Override
     public String toString() {
         return "InputMethodInfo{" + mId
@@ -430,7 +431,7 @@
     /**
      * Used to test whether the given parameter object is an
      * {@link InputMethodInfo} and its Id is the same to this one.
-     * 
+     *
      * @return true if the given parameter object is an
      *         {@link InputMethodInfo} and its Id is the same to this one.
      */
@@ -467,7 +468,7 @@
 
     /**
      * Used to package this object into a {@link Parcel}.
-     * 
+     *
      * @param dest The {@link Parcel} to be written.
      * @param flags The flags used for parceling.
      */
@@ -479,7 +480,7 @@
         dest.writeInt(mIsAuxIme ? 1 : 0);
         dest.writeInt(mSupportsSwitchingToNextInputMethod ? 1 : 0);
         mService.writeToParcel(dest, flags);
-        dest.writeTypedList(mSubtypes);
+        mSubtypes.writeToParcel(dest);
     }
 
     /**
diff --git a/core/java/android/view/inputmethod/InputMethodSubtypeArray.java b/core/java/android/view/inputmethod/InputMethodSubtypeArray.java
new file mode 100644
index 0000000..5bef71f
--- /dev/null
+++ b/core/java/android/view/inputmethod/InputMethodSubtypeArray.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2007-2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.view.inputmethod;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AndroidRuntimeException;
+import android.util.Slog;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+/**
+ * An array-like container that stores multiple instances of {@link InputMethodSubtype}.
+ *
+ * <p>This container is designed to reduce the risk of {@link TransactionTooLargeException}
+ * when one or more instancess of {@link InputMethodInfo} are transferred through IPC.
+ * Basically this class does following three tasks.</p>
+ * <ul>
+ * <li>Applying compression for the marshalled data</li>
+ * <li>Lazily unmarshalling objects</li>
+ * <li>Caching the marshalled data when appropriate</li>
+ * </ul>
+ *
+ * @hide
+ */
+public class InputMethodSubtypeArray {
+    private final static String TAG = "InputMethodSubtypeArray";
+
+    /**
+     * Create a new instance of {@link InputMethodSubtypeArray} from an existing list of
+     * {@link InputMethodSubtype}.
+     *
+     * @param subtypes A list of {@link InputMethodSubtype} from which
+     * {@link InputMethodSubtypeArray} will be created.
+     */
+    public InputMethodSubtypeArray(final List<InputMethodSubtype> subtypes) {
+        if (subtypes == null) {
+            mCount = 0;
+            return;
+        }
+        mCount = subtypes.size();
+        mInstance = subtypes.toArray(new InputMethodSubtype[mCount]);
+    }
+
+    /**
+     * Unmarshall an instance of {@link InputMethodSubtypeArray} from a given {@link Parcel}
+     * object.
+     *
+     * @param source A {@link Parcel} object from which {@link InputMethodSubtypeArray} will be
+     * unmarshalled.
+     */
+    public InputMethodSubtypeArray(final Parcel source) {
+        mCount = source.readInt();
+        if (mCount > 0) {
+            mDecompressedSize = source.readInt();
+            mCompressedData = source.createByteArray();
+        }
+    }
+
+    /**
+     * Marshall the instance into a given {@link Parcel} object.
+     *
+     * <p>This methods may take a bit additional time to compress data lazily when called
+     * first time.</p>
+     *
+     * @param source A {@link Parcel} object to which {@link InputMethodSubtypeArray} will be
+     * marshalled.
+     */
+    public void writeToParcel(final Parcel dest) {
+        if (mCount == 0) {
+            dest.writeInt(mCount);
+            return;
+        }
+
+        byte[] compressedData = mCompressedData;
+        int decompressedSize = mDecompressedSize;
+        if (compressedData == null && decompressedSize == 0) {
+            synchronized (mLockObject) {
+                compressedData = mCompressedData;
+                decompressedSize = mDecompressedSize;
+                if (compressedData == null && decompressedSize == 0) {
+                    final byte[] decompressedData = marshall(mInstance);
+                    compressedData = compress(decompressedData);
+                    if (compressedData == null) {
+                        decompressedSize = -1;
+                        Slog.i(TAG, "Failed to compress data.");
+                    } else {
+                        decompressedSize = decompressedData.length;
+                    }
+                    mDecompressedSize = decompressedSize;
+                    mCompressedData = compressedData;
+                }
+            }
+        }
+
+        if (compressedData != null && decompressedSize > 0) {
+            dest.writeInt(mCount);
+            dest.writeInt(decompressedSize);
+            dest.writeByteArray(compressedData);
+        } else {
+            Slog.i(TAG, "Unexpected state. Behaving as an empty array.");
+            dest.writeInt(0);
+        }
+    }
+
+    /**
+     * Return {@link InputMethodSubtype} specified with the given index.
+     *
+     * <p>This methods may take a bit additional time to decompress data lazily when called
+     * first time.</p>
+     *
+     * @param index The index of {@link InputMethodSubtype}.
+     */
+    public InputMethodSubtype get(final int index) {
+        if (index < 0 || mCount <= index) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        InputMethodSubtype[] instance = mInstance;
+        if (instance == null) {
+            synchronized (mLockObject) {
+                instance = mInstance;
+                if (instance == null) {
+                    final byte[] decompressedData =
+                          decompress(mCompressedData, mDecompressedSize);
+                    // Clear the compressed data until {@link #getMarshalled()} is called.
+                    mCompressedData = null;
+                    mDecompressedSize = 0;
+                    if (decompressedData != null) {
+                        instance = unmarshall(decompressedData);
+                    } else {
+                        Slog.e(TAG, "Failed to decompress data. Returns null as fallback.");
+                        instance = new InputMethodSubtype[mCount];
+                    }
+                    mInstance = instance;
+                }
+            }
+        }
+        return instance[index];
+    }
+
+    /**
+     * Return the number of {@link InputMethodSubtype} objects.
+     */
+    public int getCount() {
+        return mCount;
+    }
+
+    private final Object mLockObject = new Object();
+    private final int mCount;
+
+    private volatile InputMethodSubtype[] mInstance;
+    private volatile byte[] mCompressedData;
+    private volatile int mDecompressedSize;
+
+    private static byte[] marshall(final InputMethodSubtype[] array) {
+        Parcel parcel = null;
+        try {
+            parcel = Parcel.obtain();
+            parcel.writeTypedArray(array, 0);
+            return parcel.marshall();
+        } finally {
+            if (parcel != null) {
+                parcel.recycle();
+                parcel = null;
+            }
+        }
+    }
+
+    private static InputMethodSubtype[] unmarshall(final byte[] data) {
+        Parcel parcel = null;
+        try {
+            parcel = Parcel.obtain();
+            parcel.unmarshall(data, 0, data.length);
+            parcel.setDataPosition(0);
+            return parcel.createTypedArray(InputMethodSubtype.CREATOR);
+        } finally {
+            if (parcel != null) {
+                parcel.recycle();
+                parcel = null;
+            }
+        }
+    }
+
+    private static byte[] compress(final byte[] data) {
+        ByteArrayOutputStream resultStream = null;
+        GZIPOutputStream zipper = null;
+        try {
+            resultStream = new ByteArrayOutputStream();
+            zipper = new GZIPOutputStream(resultStream);
+            zipper.write(data);
+        } catch(IOException e) {
+            return null;
+        } finally {
+            try {
+                if (zipper != null) {
+                    zipper.close();
+                }
+            } catch (IOException e) {
+                zipper = null;
+                Slog.e(TAG, "Failed to close the stream.", e);
+                // swallowed, not propagated back to the caller
+            }
+            try {
+                if (resultStream != null) {
+                    resultStream.close();
+                }
+            } catch (IOException e) {
+                resultStream = null;
+                Slog.e(TAG, "Failed to close the stream.", e);
+                // swallowed, not propagated back to the caller
+            }
+        }
+        return resultStream != null ? resultStream.toByteArray() : null;
+    }
+
+    private static byte[] decompress(final byte[] data, final int expectedSize) {
+        ByteArrayInputStream inputStream = null;
+        GZIPInputStream unzipper = null;
+        try {
+            inputStream = new ByteArrayInputStream(data);
+            unzipper = new GZIPInputStream(inputStream);
+            final byte [] result = new byte[expectedSize];
+            int totalReadBytes = 0;
+            while (totalReadBytes < result.length) {
+                final int restBytes = result.length - totalReadBytes;
+                final int readBytes = unzipper.read(result, totalReadBytes, restBytes);
+                if (readBytes < 0) {
+                    break;
+                }
+                totalReadBytes += readBytes;
+            }
+            if (expectedSize != totalReadBytes) {
+                return null;
+            }
+            return result;
+        } catch(IOException e) {
+            return null;
+        } finally {
+            try {
+                if (unzipper != null) {
+                    unzipper.close();
+                }
+            } catch (IOException e) {
+                Slog.e(TAG, "Failed to close the stream.", e);
+                // swallowed, not propagated back to the caller
+            }
+            try {
+                if (inputStream != null) {
+                  inputStream.close();
+                }
+            } catch (IOException e) {
+                Slog.e(TAG, "Failed to close the stream.", e);
+                // swallowed, not propagated back to the caller
+            }
+        }
+    }
+}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 826bcec..81d36a4 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2139,10 +2139,11 @@
         mProvider.getViewDelegate().onAttachedToWindow();
     }
 
+    /** @hide */
     @Override
-    protected void onDetachedFromWindow() {
+    protected void onDetachedFromWindowInternal() {
         mProvider.getViewDelegate().onDetachedFromWindow();
-        super.onDetachedFromWindow();
+        super.onDetachedFromWindowInternal();
     }
 
     @Override
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 7ea0613..96a2ab5 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -56,7 +56,6 @@
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.view.ViewParent;
-import android.view.ViewRootImpl;
 import android.view.ViewTreeObserver;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
@@ -704,6 +703,11 @@
     private SavedState mPendingSync;
 
     /**
+     * Whether the view is in the process of detaching from its window.
+     */
+    private boolean mIsDetaching;
+
+    /**
      * Interface definition for a callback to be invoked when the list or grid
      * has been scrolled.
      */
@@ -2131,15 +2135,15 @@
             mRecycler.markChildrenDirty();
         }
 
-        // TODO: Move somewhere sane. This doesn't belong in onLayout().
-        if (mFastScroll != null) {
-            mFastScroll.onItemCountChanged(childCount, mItemCount);
-        }
-
         layoutChildren();
         mInLayout = false;
 
         mOverscrollMax = (b - t) / OVERSCROLL_LIMIT_DIVISOR;
+
+        // TODO: Move somewhere sane. This doesn't belong in onLayout().
+        if (mFastScroll != null) {
+            mFastScroll.onItemCountChanged(getChildCount(), mItemCount);
+        }
     }
 
     /**
@@ -2169,20 +2173,11 @@
     }
 
     /**
-     * @return the direct child that contains accessibility focus, or null if no
+     * @param focusedView view that holds accessibility focus
+     * @return direct child that contains accessibility focus, or null if no
      *         child contains accessibility focus
      */
-    View getAccessibilityFocusedChild() {
-        final ViewRootImpl viewRootImpl = getViewRootImpl();
-        if (viewRootImpl == null) {
-            return null;
-        }
-
-        View focusedView = viewRootImpl.getAccessibilityFocusedHost();
-        if (focusedView == null) {
-            return null;
-        }
-
+    View getAccessibilityFocusedChild(View focusedView) {
         ViewParent viewParent = focusedView.getParent();
         while ((viewParent instanceof View) && (viewParent != this)) {
             focusedView = (View) viewParent;
@@ -2317,6 +2312,7 @@
 
                 // If we failed to re-bind the data, scrap the obtained view.
                 if (updatedView != transientView) {
+                    setItemViewLayoutParams(updatedView, position);
                     mRecycler.addScrapView(updatedView, position);
                 }
             }
@@ -2335,12 +2331,6 @@
             } else {
                 isScrap[0] = true;
 
-                // Clear any system-managed transient state so that we can
-                // recycle this view and bind it to different data.
-                if (child.isAccessibilityFocused()) {
-                    child.clearAccessibilityFocus();
-                }
-
                 child.dispatchFinishTemporaryDetach();
             }
         }
@@ -2353,19 +2343,7 @@
             child.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
         }
 
-        if (mAdapterHasStableIds) {
-            final ViewGroup.LayoutParams vlp = child.getLayoutParams();
-            LayoutParams lp;
-            if (vlp == null) {
-                lp = (LayoutParams) generateDefaultLayoutParams();
-            } else if (!checkLayoutParams(vlp)) {
-                lp = (LayoutParams) generateLayoutParams(vlp);
-            } else {
-                lp = (LayoutParams) vlp;
-            }
-            lp.itemId = mAdapter.getItemId(position);
-            child.setLayoutParams(lp);
-        }
+        setItemViewLayoutParams(child, position);
 
         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
             if (mAccessibilityDelegate == null) {
@@ -2381,6 +2359,24 @@
         return child;
     }
 
+    private void setItemViewLayoutParams(View child, int position) {
+        final ViewGroup.LayoutParams vlp = child.getLayoutParams();
+        LayoutParams lp;
+        if (vlp == null) {
+            lp = (LayoutParams) generateDefaultLayoutParams();
+        } else if (!checkLayoutParams(vlp)) {
+            lp = (LayoutParams) generateLayoutParams(vlp);
+        } else {
+            lp = (LayoutParams) vlp;
+        }
+
+        if (mAdapterHasStableIds) {
+            lp.itemId = mAdapter.getItemId(position);
+        }
+        lp.viewType = mAdapter.getItemViewType(position);
+        child.setLayoutParams(lp);
+    }
+
     class ListItemAccessibilityDelegate extends AccessibilityDelegate {
         @Override
         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
@@ -2803,6 +2799,8 @@
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
 
+        mIsDetaching = true;
+
         // Dismiss the popup in case onSaveInstanceState() was not invoked
         dismissPopup();
 
@@ -2851,6 +2849,8 @@
             removeCallbacks(mTouchModeReset);
             mTouchModeReset.run();
         }
+
+        mIsDetaching = false;
     }
 
     @Override
@@ -3477,7 +3477,7 @@
             mPositionScroller.stop();
         }
 
-        if (!isAttachedToWindow()) {
+        if (mIsDetaching || !isAttachedToWindow()) {
             // Something isn't right.
             // Since we rely on being attached to get data set change notifications,
             // don't risk doing anything where we might try to resync and find things
@@ -3716,7 +3716,7 @@
                                     mTouchMode = TOUCH_MODE_REST;
                                     child.setPressed(false);
                                     setPressed(false);
-                                    if (!mDataChanged && isAttachedToWindow()) {
+                                    if (!mDataChanged && !mIsDetaching && isAttachedToWindow()) {
                                         performClick.run();
                                     }
                                 }
@@ -3991,7 +3991,7 @@
             mPositionScroller.stop();
         }
 
-        if (!isAttachedToWindow()) {
+        if (mIsDetaching || !isAttachedToWindow()) {
             // Something isn't right.
             // Since we rely on being attached to get data set change notifications,
             // don't risk doing anything where we might try to resync and find things
@@ -4478,6 +4478,7 @@
      * scroll such that the indicated position is displayed, but it will
      * stop early if scrolling further would scroll boundPosition out of
      * view.
+     *
      * @param position Scroll to this adapter position.
      * @param boundPosition Do not scroll if it would move this adapter
      *          position out of view.
@@ -6196,18 +6197,12 @@
         void clear() {
             if (mViewTypeCount == 1) {
                 final ArrayList<View> scrap = mCurrentScrap;
-                final int scrapCount = scrap.size();
-                for (int i = 0; i < scrapCount; i++) {
-                    removeDetachedView(scrap.remove(scrapCount - 1 - i), false);
-                }
+                clearScrap(scrap);
             } else {
                 final int typeCount = mViewTypeCount;
                 for (int i = 0; i < typeCount; i++) {
                     final ArrayList<View> scrap = mScrapViews[i];
-                    final int scrapCount = scrap.size();
-                    for (int j = 0; j < scrapCount; j++) {
-                        removeDetachedView(scrap.remove(scrapCount - 1 - j), false);
-                    }
+                    clearScrap(scrap);
                 }
             }
 
@@ -6308,7 +6303,7 @@
             if (mViewTypeCount == 1) {
                 return retrieveFromScrap(mCurrentScrap, position);
             } else {
-                int whichScrap = mAdapter.getItemViewType(position);
+                final int whichScrap = mAdapter.getItemViewType(position);
                 if (whichScrap >= 0 && whichScrap < mScrapViews.length) {
                     return retrieveFromScrap(mScrapViews[whichScrap], position);
                 }
@@ -6380,13 +6375,6 @@
                     mScrapViews[viewType].add(scrap);
                 }
 
-                // Clear any system-managed transient state.
-                if (scrap.isAccessibilityFocused()) {
-                    scrap.clearAccessibilityFocus();
-                }
-
-                scrap.setAccessibilityDelegate(null);
-
                 if (mRecyclerListener != null) {
                     mRecyclerListener.onMovedToScrapHeap(scrap);
                 }
@@ -6460,7 +6448,6 @@
                         lp.scrappedFromPosition = mFirstActivePosition + i;
                         scrapViews.add(victim);
 
-                        victim.setAccessibilityDelegate(null);
                         if (hasListener) {
                             mRecyclerListener.onMovedToScrapHeap(victim);
                         }
@@ -6564,23 +6551,52 @@
                 }
             }
         }
-    }
 
-    static View retrieveFromScrap(ArrayList<View> scrapViews, int position) {
-        int size = scrapViews.size();
-        if (size > 0) {
-            // See if we still have a view for this position.
-            for (int i=0; i<size; i++) {
-                View view = scrapViews.get(i);
-                if (((AbsListView.LayoutParams)view.getLayoutParams())
-                        .scrappedFromPosition == position) {
-                    scrapViews.remove(i);
-                    return view;
+        private View retrieveFromScrap(ArrayList<View> scrapViews, int position) {
+            final int size = scrapViews.size();
+            if (size > 0) {
+                // See if we still have a view for this position or ID.
+                for (int i = 0; i < size; i++) {
+                    final View view = scrapViews.get(i);
+                    final AbsListView.LayoutParams params =
+                            (AbsListView.LayoutParams) view.getLayoutParams();
+
+                    if (mAdapterHasStableIds) {
+                        final long id = mAdapter.getItemId(position);
+                        if (id == params.itemId) {
+                            return scrapViews.remove(i);
+                        }
+                    } else if (params.scrappedFromPosition == position) {
+                        final View scrap = scrapViews.remove(i);
+                        clearAccessibilityFromScrap(scrap);
+                        return scrap;
+                    }
                 }
+                final View scrap = scrapViews.remove(size - 1);
+                clearAccessibilityFromScrap(scrap);
+                return scrap;
+            } else {
+                return null;
             }
-            return scrapViews.remove(size - 1);
-        } else {
-            return null;
+        }
+
+        private void clearScrap(final ArrayList<View> scrap) {
+            final int scrapCount = scrap.size();
+            for (int j = 0; j < scrapCount; j++) {
+                removeDetachedView(scrap.remove(scrapCount - 1 - j), false);
+            }
+        }
+
+        private void clearAccessibilityFromScrap(View view) {
+            if (view.isAccessibilityFocused()) {
+                view.clearAccessibilityFocus();
+            }
+            view.setAccessibilityDelegate(null);
+        }
+
+        private void removeDetachedView(View child, boolean animate) {
+            child.setAccessibilityDelegate(null);
+            AbsListView.this.removeDetachedView(child, animate);
         }
     }
 
@@ -7112,7 +7128,10 @@
      * understanding of layout.
      */
     abstract class AbsSubPositionScroller extends AbsPositionScroller {
-        private static final int DEFAULT_SCROLL_DURATION = 200;
+        private static final int DURATION_AUTO = -1;
+
+        private static final int DURATION_AUTO_MIN = 100;
+        private static final int DURATION_AUTO_MAX = 500;
 
         private final SubScroller mSubScroller = new SubScroller();
 
@@ -7141,9 +7160,17 @@
                 return;
             }
 
+            if (mAdapter == null) {
+                // Can't scroll anywhere without an adapter.
+                return;
+            }
+
+            final int itemCount = getCount();
+            final int clampedPosition = MathUtils.constrain(targetPosition, 0, itemCount - 1);
+            final int clampedBoundPosition = MathUtils.constrain(boundPosition, 0, itemCount - 1);
             final int firstPosition = getFirstVisiblePosition();
             final int lastPosition = firstPosition + getChildCount();
-            final int targetRow = getRowForPosition(targetPosition);
+            final int targetRow = getRowForPosition(clampedPosition);
             final int firstRow = getRowForPosition(firstPosition);
             final int lastRow = getRowForPosition(lastPosition);
             if (useOffset || targetRow <= firstRow) {
@@ -7152,15 +7179,15 @@
             } else if (targetRow >= lastRow - 1) {
                 // Offset so the target row is bottom-aligned.
                 final int listHeight = getHeight() - getPaddingTop() - getPaddingBottom();
-                mOffset = listHeight - getHeightForPosition(targetPosition);
+                mOffset = getHeightForPosition(clampedPosition) - listHeight;
             } else {
                 // Don't scroll, target is entirely on-screen.
                 return;
             }
 
             float endSubRow = targetRow;
-            if (boundPosition != INVALID_POSITION) {
-                final int boundRow = getRowForPosition(boundPosition);
+            if (clampedBoundPosition != INVALID_POSITION) {
+                final int boundRow = getRowForPosition(clampedBoundPosition);
                 if (boundRow >= firstRow && boundRow < lastRow && boundRow != targetRow) {
                     endSubRow = computeBoundSubRow(targetRow, boundRow);
                 }
@@ -7174,48 +7201,75 @@
             final int firstChildHeight = firstChild.getHeight();
             final float startOffsetRatio;
             if (firstChildHeight == 0) {
-                startOffsetRatio = 1;
+                startOffsetRatio = 0;
             } else {
                 startOffsetRatio = -firstChild.getTop() / (float) firstChildHeight;
             }
 
-            final float startSubRow = firstRow + startOffsetRatio;
+            final float startSubRow = MathUtils.constrain(
+                    firstRow + startOffsetRatio, 0, getCount());
             if (startSubRow == endSubRow && mOffset == 0) {
                 // Don't scroll, target is already in position.
                 return;
             }
 
-            mSubScroller.startScroll(startSubRow, endSubRow, duration);
+            final int durationMillis;
+            if (duration == DURATION_AUTO) {
+                final float subRowDelta = Math.abs(startSubRow - endSubRow);
+                durationMillis = (int) MathUtils.lerp(
+                        DURATION_AUTO_MIN, DURATION_AUTO_MAX, subRowDelta / getCount());
+            } else {
+                durationMillis = duration;
+            }
+
+            mSubScroller.startScroll(startSubRow, endSubRow, durationMillis);
 
             postOnAnimation(mAnimationFrame);
         }
 
-        private float computeBoundSubRow(int targetRow, int boundRow) {
-            // If the final offset is greater than 0, we're aiming above the
-            // suggested target row. Compute the actual target row and offset
-            // within that row by subtracting the height of each preceeding row.
-            int remainingOffset = mOffset;
+        /**
+         * Given a target row and offset, computes the sub-row position that
+         * aligns with the top of the list. If the offset is negative, the
+         * resulting sub-row will be smaller than the target row.
+         */
+        private float resolveOffset(int targetRow, int offset) {
+            // Compute the target sub-row position by finding the actual row
+            // indicated by the target and offset.
+            int remainingOffset = offset;
             int targetHeight = getHeightForRow(targetRow);
-            while (targetRow > 0 && remainingOffset > targetHeight) {
-                targetRow--;
-                remainingOffset -= targetHeight;
-                targetHeight = getHeightForRow(targetRow);
+            if (offset < 0) {
+                // Subtract row heights until we find the right row.
+                while (targetRow > 0 && remainingOffset < 0) {
+                    remainingOffset += targetHeight;
+                    targetRow--;
+                    targetHeight = getHeightForRow(targetRow);
+                }
+            } else if (offset > 0) {
+                // Add row heights until we find the right row.
+                while (targetRow < getCount() - 1 && remainingOffset > targetHeight) {
+                    remainingOffset -= targetHeight;
+                    targetRow++;
+                    targetHeight = getHeightForRow(targetRow);
+                }
             }
 
-            // Compute the offset within the actual target row.
             final float targetOffsetRatio;
-            if (targetHeight == 0) {
-                targetOffsetRatio = 1;
+            if (remainingOffset < 0 || targetHeight == 0) {
+                targetOffsetRatio = 0;
             } else {
                 targetOffsetRatio = remainingOffset / (float) targetHeight;
             }
 
-            // The final offset has been accounted for, reset it.
-            final float targetSubRow = targetRow - targetOffsetRatio;
+            return targetRow + targetOffsetRatio;
+        }
+
+        private float computeBoundSubRow(int targetRow, int boundRow) {
+            final float targetSubRow = resolveOffset(targetRow, mOffset);
             mOffset = 0;
 
+            // The target row is below the bound row, so the end position would
+            // push the bound position above the list. Abort!
             if (targetSubRow >= boundRow) {
-                // End position would push the bound position above the list.
                 return boundRow;
             }
 
@@ -7223,39 +7277,24 @@
             // bound position's view further below the list.
             final int listHeight = getHeight() - getPaddingTop() - getPaddingBottom();
             final int boundHeight = getHeightForRow(boundRow);
-            int endRow = boundRow;
-            int totalHeight = boundHeight;
-            int endHeight;
-            do {
-                endRow--;
-                endHeight = getHeightForRow(endRow);
-                totalHeight += endHeight;
-            } while (totalHeight < listHeight && endRow > 0);
+            final float boundSubRow = resolveOffset(boundRow, -listHeight + boundHeight);
 
-            final float endOffsetRatio;
-            if (endHeight == 0) {
-                endOffsetRatio = 1;
-            } else {
-                endOffsetRatio = (totalHeight - listHeight) / (float) endHeight;
-            }
-
-            final float boundSubRow = endRow + endOffsetRatio;
             return Math.max(boundSubRow, targetSubRow);
         }
 
         @Override
         public void start(int position) {
-            scrollToPosition(position, false, 0, INVALID_POSITION, DEFAULT_SCROLL_DURATION);
+            scrollToPosition(position, false, 0, INVALID_POSITION, DURATION_AUTO);
         }
 
         @Override
         public void start(int position, int boundPosition) {
-            scrollToPosition(position, false, 0, boundPosition, DEFAULT_SCROLL_DURATION);
+            scrollToPosition(position, false, 0, boundPosition, DURATION_AUTO);
         }
 
         @Override
         public void startWithOffset(int position, int offset) {
-            scrollToPosition(position, true, offset, INVALID_POSITION, DEFAULT_SCROLL_DURATION);
+            scrollToPosition(position, true, offset, INVALID_POSITION, DURATION_AUTO);
         }
 
         @Override
@@ -7307,7 +7346,7 @@
             final int rowHeight = getHeightForRow(row);
             final int offset = (int) (rowHeight * (subRow - row));
             final int addOffset = (int) (mOffset * mSubScroller.getInterpolatedValue());
-            setSelectionFromTop(position, -offset + addOffset);
+            setSelectionFromTop(position, -offset - addOffset);
 
             if (shouldPost) {
                 postOnAnimation(mAnimationFrame);
@@ -7326,7 +7365,7 @@
      * Scroller capable of returning floating point positions.
      */
     static class SubScroller {
-        private final Interpolator mInterpolator;
+        private static final Interpolator INTERPOLATOR = new AccelerateDecelerateInterpolator();
 
         private float mStartPosition;
         private float mEndPosition;
@@ -7336,18 +7375,6 @@
         private float mPosition;
         private float mInterpolatedValue;
 
-        public SubScroller() {
-            this(null);
-        }
-
-        public SubScroller(Interpolator interpolator) {
-            if (interpolator == null) {
-                mInterpolator = new AccelerateDecelerateInterpolator();
-            } else {
-                mInterpolator = interpolator;
-            }
-        }
-
         public void startScroll(float startPosition, float endPosition, int duration) {
             mStartPosition = startPosition;
             mEndPosition = endPosition;
@@ -7367,7 +7394,7 @@
                 value = MathUtils.constrain(elapsed / (float) mDuration, 0, 1);
             }
 
-            mInterpolatedValue = mInterpolator.getInterpolation(value);
+            mInterpolatedValue = INTERPOLATOR.getInterpolation(value);
             mPosition = (mEndPosition - mStartPosition) * mInterpolatedValue + mStartPosition;
 
             return elapsed < mDuration;
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 962ffba..1da22ca 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -667,7 +667,7 @@
 
     /**
      * When the current adapter is empty, the AdapterView can display a special view
-     * call the empty view. The empty view is used to provide feedback to the user
+     * called the empty view. The empty view is used to provide feedback to the user
      * that no data is available in this AdapterView.
      *
      * @return The view to show if the adapter is empty.
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index 3a7cc87..a8ff562 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.content.Context;
+import android.os.Bundle;
 import android.text.Editable;
 import android.text.Selection;
 import android.text.Spannable;
@@ -132,4 +133,22 @@
         super.onInitializeAccessibilityNodeInfo(info);
         info.setClassName(EditText.class.getName());
     }
+
+    @Override
+    public boolean performAccessibilityAction(int action, Bundle arguments) {
+        switch (action) {
+            case AccessibilityNodeInfo.ACTION_SET_TEXT: {
+                CharSequence text = (arguments != null) ? arguments.getCharSequence(
+                        AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE) : null;
+                setText(text);
+                if (text != null && text.length() > 0) {
+                    setSelection(text.length());
+                }
+                return true;
+            }
+            default: {
+                return super.performAccessibilityAction(action, arguments);
+            }
+        }
+    }
 }
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index ea62bbe..98b43b3 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -23,6 +23,7 @@
 import android.os.Parcelable;
 import android.text.InputFilter;
 import android.text.SpannableString;
+
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.widget.EditableInputConnection;
 
@@ -77,6 +78,7 @@
 import android.view.DragEvent;
 import android.view.Gravity;
 import android.view.HardwareCanvas;
+import android.view.HardwareRenderer;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -135,7 +137,16 @@
     InputContentType mInputContentType;
     InputMethodState mInputMethodState;
 
-    DisplayList[] mTextDisplayLists;
+    private static class TextDisplayList {
+        DisplayList displayList;
+        boolean isDirty;
+        public TextDisplayList(String name) {
+            isDirty = true;
+            displayList = DisplayList.create(name);
+        }
+        boolean needsRecord() { return isDirty || !displayList.isValid(); }
+    }
+    TextDisplayList[] mTextDisplayLists;
 
     boolean mFrozenWithFocus;
     boolean mSelectionMoved;
@@ -260,7 +271,7 @@
             mTextView.removeCallbacks(mShowSuggestionRunnable);
         }
 
-        invalidateTextDisplayList();
+        destroyDisplayListsData();
 
         if (mSpellChecker != null) {
             mSpellChecker.closeSession();
@@ -275,6 +286,19 @@
         mTemporaryDetach = false;
     }
 
+    private void destroyDisplayListsData() {
+        HardwareRenderer renderer = mTextView.getHardwareRenderer();
+        if (mTextDisplayLists != null) {
+            for (int i = 0; i < mTextDisplayLists.length; i++) {
+                DisplayList displayList = mTextDisplayLists[i] != null
+                        ? mTextDisplayLists[i].displayList : null;
+                if (displayList != null && displayList.isValid()) {
+                    displayList.destroyDisplayListData(renderer);
+                }
+            }
+        }
+    }
+
     private void showError() {
         if (mTextView.getWindowToken() == null) {
             mShowErrorAfterAttach = true;
@@ -1314,10 +1338,11 @@
 
         layout.drawBackground(canvas, highlight, highlightPaint, cursorOffsetVertical,
                 firstLine, lastLine);
+        final HardwareRenderer renderer = mTextView.getHardwareRenderer();
 
         if (layout instanceof DynamicLayout) {
             if (mTextDisplayLists == null) {
-                mTextDisplayLists = new DisplayList[ArrayUtils.idealObjectArraySize(0)];
+                mTextDisplayLists = new TextDisplayList[ArrayUtils.idealObjectArraySize(0)];
             }
 
             DynamicLayout dynamicLayout = (DynamicLayout) layout;
@@ -1341,15 +1366,13 @@
                     searchStartIndex = blockIndex + 1;
                 }
 
-                DisplayList blockDisplayList = mTextDisplayLists[blockIndex];
-                if (blockDisplayList == null) {
-                    blockDisplayList = mTextDisplayLists[blockIndex] =
-                            DisplayList.create("Text " + blockIndex);
-                } else {
-                    if (blockIsInvalid) blockDisplayList.clear();
+                if (mTextDisplayLists[blockIndex] == null) {
+                    mTextDisplayLists[blockIndex] =
+                            new TextDisplayList("Text " + blockIndex);
                 }
 
-                final boolean blockDisplayListIsInvalid = !blockDisplayList.isValid();
+                final boolean blockDisplayListIsInvalid = mTextDisplayLists[blockIndex].needsRecord();
+                DisplayList blockDisplayList = mTextDisplayLists[blockIndex].displayList;
                 if (i >= indexFirstChangedBlock || blockDisplayListIsInvalid) {
                     final int blockBeginLine = endOfPreviousBlock + 1;
                     final int top = layout.getLineTop(blockBeginLine);
@@ -1379,7 +1402,7 @@
                             // No need to untranslate, previous context is popped after
                             // drawDisplayList
                         } finally {
-                            blockDisplayList.end();
+                            blockDisplayList.end(renderer, hardwareCanvas);
                             // Same as drawDisplayList below, handled by our TextView's parent
                             blockDisplayList.setClipToBounds(false);
                         }
@@ -1420,7 +1443,7 @@
 
         // No available index found, the pool has to grow
         int newSize = ArrayUtils.idealIntArraySize(length + 1);
-        DisplayList[] displayLists = new DisplayList[newSize];
+        TextDisplayList[] displayLists = new TextDisplayList[newSize];
         System.arraycopy(mTextDisplayLists, 0, displayLists, 0, length);
         mTextDisplayLists = displayLists;
         return length;
@@ -1459,7 +1482,7 @@
             while (i < numberOfBlocks) {
                 final int blockIndex = blockIndices[i];
                 if (blockIndex != DynamicLayout.INVALID_BLOCK_INDEX) {
-                    mTextDisplayLists[blockIndex].clear();
+                    mTextDisplayLists[blockIndex].isDirty = true;
                 }
                 if (blockEndLines[i] >= lastLine) break;
                 i++;
@@ -1470,7 +1493,7 @@
     void invalidateTextDisplayList() {
         if (mTextDisplayLists != null) {
             for (int i = 0; i < mTextDisplayLists.length; i++) {
-                if (mTextDisplayLists[i] != null) mTextDisplayLists[i].clear();
+                if (mTextDisplayLists[i] != null) mTextDisplayLists[i].isDirty = true;
             }
         }
     }
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 6743002..04b18c1 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -30,13 +30,13 @@
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
+import android.view.ViewRootImpl;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.accessibility.AccessibilityNodeInfo.CollectionInfo;
 import android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo;
 import android.view.animation.GridLayoutAnimationController;
-import android.widget.AbsListView.AbsPositionScroller;
-import android.widget.ListView.ListViewPositionScroller;
 import android.widget.RemoteViews.RemoteView;
 
 import java.lang.annotation.Retention;
@@ -1222,22 +1222,32 @@
 
             setSelectedPositionInt(mNextSelectedPosition);
 
-            // Remember which child, if any, had accessibility focus.
-            final int accessibilityFocusPosition;
-            final View accessFocusedChild = getAccessibilityFocusedChild();
-            if (accessFocusedChild != null) {
-                accessibilityFocusPosition = getPositionForView(accessFocusedChild);
-                accessFocusedChild.setHasTransientState(true);
-            } else {
-                accessibilityFocusPosition = INVALID_POSITION;
-            }
+            AccessibilityNodeInfo accessibilityFocusLayoutRestoreNode = null;
+            View accessibilityFocusLayoutRestoreView = null;
+            int accessibilityFocusPosition = INVALID_POSITION;
 
-            // Ensure the child containing focus, if any, has transient state.
-            // If the list data hasn't changed, or if the adapter has stable
-            // IDs, this will maintain focus.
-            final View focusedChild = getFocusedChild();
-            if (focusedChild != null) {
-                focusedChild.setHasTransientState(true);
+            // Remember which child, if any, had accessibility focus. This must
+            // occur before recycling any views, since that will clear
+            // accessibility focus.
+            final ViewRootImpl viewRootImpl = getViewRootImpl();
+            if (viewRootImpl != null) {
+                final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
+                if (focusHost != null) {
+                    final View focusChild = getAccessibilityFocusedChild(focusHost);
+                    if (focusChild != null) {
+                        if (!dataChanged || focusChild.hasTransientState()
+                                || mAdapterHasStableIds) {
+                            // The views won't be changing, so try to maintain
+                            // focus on the current host and virtual view.
+                            accessibilityFocusLayoutRestoreView = focusHost;
+                            accessibilityFocusLayoutRestoreNode = viewRootImpl
+                                    .getAccessibilityFocusedVirtualView();
+                        }
+
+                        // Try to maintain focus at the same position.
+                        accessibilityFocusPosition = getPositionForView(focusChild);
+                    }
+                }
             }
 
             // Pull all children into the RecycleBin.
@@ -1324,27 +1334,35 @@
                 mSelectorRect.setEmpty();
             }
 
-            if (accessFocusedChild != null) {
-                accessFocusedChild.setHasTransientState(false);
-
-                // If we failed to maintain accessibility focus on the previous
-                // view, attempt to restore it to the previous position.
-                if (!accessFocusedChild.isAccessibilityFocused()
-                    && accessibilityFocusPosition != INVALID_POSITION) {
-                    // Bound the position within the visible children.
-                    final int position = MathUtils.constrain(
-                            accessibilityFocusPosition - mFirstPosition, 0, getChildCount() - 1);
-                    final View restoreView = getChildAt(position);
-                    if (restoreView != null) {
-                        restoreView.requestAccessibilityFocus();
+            // Attempt to restore accessibility focus, if necessary.
+            if (viewRootImpl != null) {
+                final View newAccessibilityFocusedView = viewRootImpl.getAccessibilityFocusedHost();
+                if (newAccessibilityFocusedView == null) {
+                    if (accessibilityFocusLayoutRestoreView != null
+                            && accessibilityFocusLayoutRestoreView.isAttachedToWindow()) {
+                        final AccessibilityNodeProvider provider =
+                                accessibilityFocusLayoutRestoreView.getAccessibilityNodeProvider();
+                        if (accessibilityFocusLayoutRestoreNode != null && provider != null) {
+                            final int virtualViewId = AccessibilityNodeInfo.getVirtualDescendantId(
+                                    accessibilityFocusLayoutRestoreNode.getSourceNodeId());
+                            provider.performAction(virtualViewId,
+                                    AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
+                        } else {
+                            accessibilityFocusLayoutRestoreView.requestAccessibilityFocus();
+                        }
+                    } else if (accessibilityFocusPosition != INVALID_POSITION) {
+                        // Bound the position within the visible children.
+                        final int position = MathUtils.constrain(
+                                accessibilityFocusPosition - mFirstPosition, 0,
+                                getChildCount() - 1);
+                        final View restoreView = getChildAt(position);
+                        if (restoreView != null) {
+                            restoreView.requestAccessibilityFocus();
+                        }
                     }
                 }
             }
 
-            if (focusedChild != null) {
-                focusedChild.setHasTransientState(false);
-            }
-
             mLayoutMode = LAYOUT_NORMAL;
             mDataChanged = false;
             if (mPositionScrollAfterLayout != null) {
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 65f1ab7..82e624d 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -667,6 +667,7 @@
         final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
 
         boolean matchWidth = false;
+        boolean skippedMeasure = false;
 
         final int baselineChildIndex = mBaselineAlignedChildIndex;        
         final boolean useLargestChild = mUseLargestChild;
@@ -701,6 +702,7 @@
                 // there is any leftover space.
                 final int totalLength = mTotalLength;
                 mTotalLength = Math.max(totalLength, totalLength + lp.topMargin + lp.bottomMargin);
+                skippedMeasure = true;
             } else {
                 int oldHeight = Integer.MIN_VALUE;
 
@@ -827,9 +829,10 @@
         heightSize = heightSizeAndState & MEASURED_SIZE_MASK;
         
         // Either expand children with weight to take up available space or
-        // shrink them if they extend beyond our current bounds
+        // shrink them if they extend beyond our current bounds. If we skipped
+        // measurement on any children, we need to measure them now.
         int delta = heightSize - mTotalLength;
-        if (delta != 0 && totalWeight > 0.0f) {
+        if (skippedMeasure || delta != 0 && totalWeight > 0.0f) {
             float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
 
             mTotalLength = 0;
@@ -995,6 +998,7 @@
         final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
 
         boolean matchHeight = false;
+        boolean skippedMeasure = false;
 
         if (mMaxAscent == null || mMaxDescent == null) {
             mMaxAscent = new int[VERTICAL_GRAVITY_COUNT];
@@ -1057,6 +1061,8 @@
                 if (baselineAligned) {
                     final int freeSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
                     child.measure(freeSpec, freeSpec);
+                } else {
+                    skippedMeasure = true;
                 }
             } else {
                 int oldWidth = Integer.MIN_VALUE;
@@ -1205,9 +1211,10 @@
         widthSize = widthSizeAndState & MEASURED_SIZE_MASK;
         
         // Either expand children with weight to take up available space or
-        // shrink them if they extend beyond our current bounds
+        // shrink them if they extend beyond our current bounds. If we skipped
+        // measurement on any children, we need to measure them now.
         int delta = widthSize - mTotalLength;
-        if (delta != 0 && totalWeight > 0.0f) {
+        if (skippedMeasure || delta != 0 && totalWeight > 0.0f) {
             float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
 
             maxAscent[0] = maxAscent[1] = maxAscent[2] = maxAscent[3] = -1;
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index cef2138..5de67c8 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -39,10 +39,12 @@
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.view.ViewParent;
+import android.view.ViewRootImpl;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeInfo.CollectionInfo;
 import android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo;
+import android.view.accessibility.AccessibilityNodeProvider;
 import android.widget.RemoteViews.RemoteView;
 
 import java.util.ArrayList;
@@ -1567,22 +1569,58 @@
 
             setSelectedPositionInt(mNextSelectedPosition);
 
-            // Remember which child, if any, had accessibility focus.
-            final int accessibilityFocusPosition;
-            final View accessFocusedChild = getAccessibilityFocusedChild();
-            if (accessFocusedChild != null) {
-                accessibilityFocusPosition = getPositionForView(accessFocusedChild);
-                accessFocusedChild.setHasTransientState(true);
-            } else {
-                accessibilityFocusPosition = INVALID_POSITION;
+            AccessibilityNodeInfo accessibilityFocusLayoutRestoreNode = null;
+            View accessibilityFocusLayoutRestoreView = null;
+            int accessibilityFocusPosition = INVALID_POSITION;
+
+            // Remember which child, if any, had accessibility focus. This must
+            // occur before recycling any views, since that will clear
+            // accessibility focus.
+            final ViewRootImpl viewRootImpl = getViewRootImpl();
+            if (viewRootImpl != null) {
+                final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
+                if (focusHost != null) {
+                    final View focusChild = getAccessibilityFocusedChild(focusHost);
+                    if (focusChild != null) {
+                        if (!dataChanged || isDirectChildHeaderOrFooter(focusChild)
+                                || focusChild.hasTransientState() || mAdapterHasStableIds) {
+                            // The views won't be changing, so try to maintain
+                            // focus on the current host and virtual view.
+                            accessibilityFocusLayoutRestoreView = focusHost;
+                            accessibilityFocusLayoutRestoreNode = viewRootImpl
+                                    .getAccessibilityFocusedVirtualView();
+                        }
+
+                        // If all else fails, maintain focus at the same
+                        // position.
+                        accessibilityFocusPosition = getPositionForView(focusChild);
+                    }
+                }
             }
 
-            // Ensure the child containing focus, if any, has transient state.
-            // If the list data hasn't changed, or if the adapter has stable
-            // IDs, this will maintain focus.
+            View focusLayoutRestoreDirectChild = null;
+            View focusLayoutRestoreView = null;
+
+            // Take focus back to us temporarily to avoid the eventual call to
+            // clear focus when removing the focused child below from messing
+            // things up when ViewAncestor assigns focus back to someone else.
             final View focusedChild = getFocusedChild();
             if (focusedChild != null) {
-                focusedChild.setHasTransientState(true);
+                // TODO: in some cases focusedChild.getParent() == null
+
+                // We can remember the focused view to restore after re-layout
+                // if the data hasn't changed, or if the focused position is a
+                // header or footer.
+                if (!dataChanged || isDirectChildHeaderOrFooter(focusedChild)) {
+                    focusLayoutRestoreDirectChild = focusedChild;
+                    // Remember the specific view that had focus.
+                    focusLayoutRestoreView = findFocus();
+                    if (focusLayoutRestoreView != null) {
+                        // Tell it we are going to mess with it.
+                        focusLayoutRestoreView.onStartTemporaryDetach();
+                    }
+                }
+                requestFocus();
             }
 
             // Pull all children into the RecycleBin.
@@ -1656,20 +1694,24 @@
             recycleBin.scrapActiveViews();
 
             if (sel != null) {
-                final boolean shouldPlaceFocus = mItemsCanFocus && hasFocus();
-                final boolean maintainedFocus = focusedChild != null && focusedChild.hasFocus();
-                if (shouldPlaceFocus && !maintainedFocus && !sel.hasFocus()) {
-                    if (sel.requestFocus()) {
-                        // Successfully placed focus, clear selection.
-                        sel.setSelected(false);
-                        mSelectorRect.setEmpty();
-                    } else {
-                        // Failed to place focus, clear current (invalid) focus.
+                // The current selected item should get focus if items are
+                // focusable.
+                if (mItemsCanFocus && hasFocus() && !sel.hasFocus()) {
+                    final boolean focusWasTaken = (sel == focusLayoutRestoreDirectChild &&
+                            focusLayoutRestoreView != null &&
+                            focusLayoutRestoreView.requestFocus()) || sel.requestFocus();
+                    if (!focusWasTaken) {
+                        // Selected item didn't take focus, but we still want to
+                        // make sure something else outside of the selected view
+                        // has focus.
                         final View focused = getFocusedChild();
                         if (focused != null) {
                             focused.clearFocus();
                         }
                         positionSelector(INVALID_POSITION, sel);
+                    } else {
+                        sel.setSelected(false);
+                        mSelectorRect.setEmpty();
                     }
                 } else {
                     positionSelector(INVALID_POSITION, sel);
@@ -1687,27 +1729,48 @@
                     mSelectedTop = 0;
                     mSelectorRect.setEmpty();
                 }
+
+                // Even if there is not selected position, we may need to
+                // restore focus (i.e. something focusable in touch mode).
+                if (hasFocus() && focusLayoutRestoreView != null) {
+                    focusLayoutRestoreView.requestFocus();
+                }
             }
 
-            if (accessFocusedChild != null) {
-                accessFocusedChild.setHasTransientState(false);
-
-                // If we failed to maintain accessibility focus on the previous
-                // view, attempt to restore it to the previous position.
-                if (!accessFocusedChild.isAccessibilityFocused()
-                    && accessibilityFocusPosition != INVALID_POSITION) {
-                    // Bound the position within the visible children.
-                    final int position = MathUtils.constrain(
-                            accessibilityFocusPosition - mFirstPosition, 0, getChildCount() - 1);
-                    final View restoreView = getChildAt(position);
-                    if (restoreView != null) {
-                        restoreView.requestAccessibilityFocus();
+            // Attempt to restore accessibility focus, if necessary.
+            if (viewRootImpl != null) {
+                final View newAccessibilityFocusedView = viewRootImpl.getAccessibilityFocusedHost();
+                if (newAccessibilityFocusedView == null) {
+                    if (accessibilityFocusLayoutRestoreView != null
+                            && accessibilityFocusLayoutRestoreView.isAttachedToWindow()) {
+                        final AccessibilityNodeProvider provider =
+                                accessibilityFocusLayoutRestoreView.getAccessibilityNodeProvider();
+                        if (accessibilityFocusLayoutRestoreNode != null && provider != null) {
+                            final int virtualViewId = AccessibilityNodeInfo.getVirtualDescendantId(
+                                    accessibilityFocusLayoutRestoreNode.getSourceNodeId());
+                            provider.performAction(virtualViewId,
+                                    AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
+                        } else {
+                            accessibilityFocusLayoutRestoreView.requestAccessibilityFocus();
+                        }
+                    } else if (accessibilityFocusPosition != INVALID_POSITION) {
+                        // Bound the position within the visible children.
+                        final int position = MathUtils.constrain(
+                                accessibilityFocusPosition - mFirstPosition, 0,
+                                getChildCount() - 1);
+                        final View restoreView = getChildAt(position);
+                        if (restoreView != null) {
+                            restoreView.requestAccessibilityFocus();
+                        }
                     }
                 }
             }
 
-            if (focusedChild != null) {
-                focusedChild.setHasTransientState(false);
+            // Tell focus view we are done mucking with it, if it is still in
+            // our view hierarchy.
+            if (focusLayoutRestoreView != null
+                    && focusLayoutRestoreView.getWindowToken() != null) {
+                focusLayoutRestoreView.onFinishTemporaryDetach();
             }
             
             mLayoutMode = LAYOUT_NORMAL;
@@ -1734,6 +1797,30 @@
     }
 
     /**
+     * @param child a direct child of this list.
+     * @return Whether child is a header or footer view.
+     */
+    private boolean isDirectChildHeaderOrFooter(View child) {
+        final ArrayList<FixedViewInfo> headers = mHeaderViewInfos;
+        final int numHeaders = headers.size();
+        for (int i = 0; i < numHeaders; i++) {
+            if (child == headers.get(i).view) {
+                return true;
+            }
+        }
+
+        final ArrayList<FixedViewInfo> footers = mFooterViewInfos;
+        final int numFooters = footers.size();
+        for (int i = 0; i < numFooters; i++) {
+            if (child == footers.get(i).view) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
      * Obtain the view and add it to our list of children. The view can be made
      * fresh, converted from an unused view, or used as is if it was in the
      * recycle bin.
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 44c4987..00b2c13 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -430,12 +430,12 @@
      * Flag whether to ignore move events - we ignore such when we show in IME
      * to prevent the content from scrolling.
      */
-    private boolean mIngonreMoveEvents;
+    private boolean mIgnoreMoveEvents;
 
     /**
-     * Flag whether to show soft input on tap.
+     * Flag whether to perform a click on tap.
      */
-    private boolean mShowSoftInputOnTap;
+    private boolean mPerformClickOnTap;
 
     /**
      * The top of the top selection divider.
@@ -834,8 +834,8 @@
                 mInputText.setVisibility(View.INVISIBLE);
                 mLastDownOrMoveEventY = mLastDownEventY = event.getY();
                 mLastDownEventTime = event.getEventTime();
-                mIngonreMoveEvents = false;
-                mShowSoftInputOnTap = false;
+                mIgnoreMoveEvents = false;
+                mPerformClickOnTap = false;
                 // Handle pressed state before any state change.
                 if (mLastDownEventY < mTopSelectionDividerTop) {
                     if (mScrollState == OnScrollListener.SCROLL_STATE_IDLE) {
@@ -866,7 +866,7 @@
                     postChangeCurrentByOneFromLongPress(
                             true, ViewConfiguration.getLongPressTimeout());
                 } else {
-                    mShowSoftInputOnTap = true;
+                    mPerformClickOnTap = true;
                     postBeginSoftInputOnLongPressCommand();
                 }
                 return true;
@@ -887,7 +887,7 @@
         int action = event.getActionMasked();
         switch (action) {
             case MotionEvent.ACTION_MOVE: {
-                if (mIngonreMoveEvents) {
+                if (mIgnoreMoveEvents) {
                     break;
                 }
                 float currentMoveY = event.getY();
@@ -919,9 +919,9 @@
                     int deltaMoveY = (int) Math.abs(eventY - mLastDownEventY);
                     long deltaTime = event.getEventTime() - mLastDownEventTime;
                     if (deltaMoveY <= mTouchSlop && deltaTime < ViewConfiguration.getTapTimeout()) {
-                        if (mShowSoftInputOnTap) {
-                            mShowSoftInputOnTap = false;
-                            showSoftInput();
+                        if (mPerformClickOnTap) {
+                            mPerformClickOnTap = false;
+                            performClick();
                         } else {
                             int selectorIndexOffset = (eventY / mSelectorElementHeight)
                                     - SELECTOR_MIDDLE_ITEM_INDEX;
@@ -1214,6 +1214,27 @@
         setValueInternal(value, false);
     }
 
+    @Override
+    public boolean performClick() {
+        if (!mHasSelectorWheel) {
+            return super.performClick();
+        } else if (!super.performClick()) {
+            showSoftInput();
+        }
+        return true;
+    }
+
+    @Override
+    public boolean performLongClick() {
+        if (!mHasSelectorWheel) {
+            return super.performLongClick();
+        } else if (!super.performLongClick()) {
+            showSoftInput();
+            mIgnoreMoveEvents = true;
+        }
+        return true;
+    }
+
     /**
      * Shows the soft input for its input text.
      */
@@ -2192,8 +2213,7 @@
 
         @Override
         public void run() {
-            showSoftInput();
-            mIngonreMoveEvents = true;
+            performLongClick();
         }
     }
 
@@ -2321,7 +2341,14 @@
                         }
                         case AccessibilityNodeInfo.ACTION_CLICK: {
                             if (NumberPicker.this.isEnabled()) {
-                                showSoftInput();
+                                performClick();
+                                return true;
+                            }
+                            return false;
+                        }
+                        case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
+                            if (NumberPicker.this.isEnabled()) {
+                                performLongClick();
                                 return true;
                             }
                             return false;
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index af9e2f0..f7e81b8 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -346,19 +346,24 @@
             return out;
             
         } else if (drawable instanceof BitmapDrawable) {
-            final Bitmap tileBitmap = ((BitmapDrawable) drawable).getBitmap();
+            final BitmapDrawable bitmap = (BitmapDrawable) drawable;
+            final Bitmap tileBitmap = bitmap.getBitmap();
             if (mSampleTile == null) {
                 mSampleTile = tileBitmap;
             }
-            
-            final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());
 
+            final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());
             final BitmapShader bitmapShader = new BitmapShader(tileBitmap,
                     Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
             shapeDrawable.getPaint().setShader(bitmapShader);
 
-            return (clip) ? new ClipDrawable(shapeDrawable, Gravity.LEFT,
-                    ClipDrawable.HORIZONTAL) : shapeDrawable;
+            // Ensure the color filter and tint are propagated.
+            shapeDrawable.setTint(bitmap.getTint());
+            shapeDrawable.setTintMode(bitmap.getTintMode());
+            shapeDrawable.setColorFilter(bitmap.getColorFilter());
+
+            return clip ? new ClipDrawable(
+                    shapeDrawable, Gravity.LEFT, ClipDrawable.HORIZONTAL) : shapeDrawable;
         }
         
         return drawable;
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 2a5fb15..3d23e4d 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -511,15 +511,18 @@
         if (mOnLayout == null) {
             mOnLayout = makeLayout(mTextOn);
         }
+
         if (mOffLayout == null) {
             mOffLayout = makeLayout(mTextOff);
         }
 
         mTrackDrawable.getPadding(mTempRect);
+
         final int maxTextWidth = Math.max(mOnLayout.getWidth(), mOffLayout.getWidth());
         final int switchWidth = Math.max(mSwitchMinWidth,
                 maxTextWidth * 2 + mThumbTextPadding * 4 + mTempRect.left + mTempRect.right);
-        final int switchHeight = mTrackDrawable.getIntrinsicHeight();
+        final int switchHeight = Math.max(mTrackDrawable.getIntrinsicHeight(),
+                mThumbDrawable.getIntrinsicHeight());
 
         mThumbWidth = maxTextWidth + mThumbTextPadding * 2;
 
@@ -772,48 +775,51 @@
     protected void onDraw(Canvas canvas) {
         super.onDraw(canvas);
 
+        final Rect tempRect = mTempRect;
+        final Drawable trackDrawable = mTrackDrawable;
+        final Drawable thumbDrawable = mThumbDrawable;
+
         // Draw the switch
-        int switchLeft = mSwitchLeft;
-        int switchTop = mSwitchTop;
-        int switchRight = mSwitchRight;
-        int switchBottom = mSwitchBottom;
+        final int switchLeft = mSwitchLeft;
+        final int switchTop = mSwitchTop;
+        final int switchRight = mSwitchRight;
+        final int switchBottom = mSwitchBottom;
+        trackDrawable.setBounds(switchLeft, switchTop, switchRight, switchBottom);
+        trackDrawable.draw(canvas);
 
-        mTrackDrawable.setBounds(switchLeft, switchTop, switchRight, switchBottom);
-        mTrackDrawable.draw(canvas);
+        final int saveCount = canvas.save();
 
-        canvas.save();
-
-        mTrackDrawable.getPadding(mTempRect);
-        int switchInnerLeft = switchLeft + mTempRect.left;
-        int switchInnerTop = switchTop + mTempRect.top;
-        int switchInnerRight = switchRight - mTempRect.right;
-        int switchInnerBottom = switchBottom - mTempRect.bottom;
+        trackDrawable.getPadding(tempRect);
+        final int switchInnerLeft = switchLeft + tempRect.left;
+        final int switchInnerTop = switchTop + tempRect.top;
+        final int switchInnerRight = switchRight - tempRect.right;
+        final int switchInnerBottom = switchBottom - tempRect.bottom;
         canvas.clipRect(switchInnerLeft, switchTop, switchInnerRight, switchBottom);
 
         // Relies on mTempRect, MUST be called first!
         final int thumbPos = getThumbOffset();
 
-        mThumbDrawable.getPadding(mTempRect);
-        int thumbLeft = switchInnerLeft - mTempRect.left + thumbPos;
-        int thumbRight = switchInnerLeft + thumbPos + mThumbWidth + mTempRect.right;
-        mThumbDrawable.setBounds(thumbLeft, switchTop, thumbRight, switchBottom);
-        mThumbDrawable.draw(canvas);
+        thumbDrawable.getPadding(tempRect);
+        int thumbLeft = switchInnerLeft - tempRect.left + thumbPos;
+        int thumbRight = switchInnerLeft + thumbPos + mThumbWidth + tempRect.right;
+        thumbDrawable.setBounds(thumbLeft, switchTop, thumbRight, switchBottom);
+        thumbDrawable.draw(canvas);
 
-        // mTextColors should not be null, but just in case
+        final int drawableState[] = getDrawableState();
         if (mTextColors != null) {
-            mTextPaint.setColor(mTextColors.getColorForState(getDrawableState(),
-                    mTextColors.getDefaultColor()));
+            mTextPaint.setColor(mTextColors.getColorForState(drawableState, 0));
         }
-        mTextPaint.drawableState = getDrawableState();
+        mTextPaint.drawableState = drawableState;
 
-        Layout switchText = getTargetCheckedState() ? mOnLayout : mOffLayout;
+        final Layout switchText = getTargetCheckedState() ? mOnLayout : mOffLayout;
         if (switchText != null) {
-            canvas.translate((thumbLeft + thumbRight) / 2 - switchText.getWidth() / 2,
-                    (switchInnerTop + switchInnerBottom) / 2 - switchText.getHeight() / 2);
+            final int left = (thumbLeft + thumbRight) / 2 - switchText.getWidth() / 2;
+            final int top = (switchInnerTop + switchInnerBottom) / 2 - switchText.getHeight() / 2;
+            canvas.translate(left, top);
             switchText.draw(canvas);
         }
 
-        canvas.restore();
+        canvas.restoreToCount(saveCount);
     }
 
     @Override
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index e5cb16f..687036c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4729,10 +4729,9 @@
         if (mEditor != null) mEditor.onAttachedToWindow();
     }
 
+    /** @hide */
     @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
-
+    protected void onDetachedFromWindowInternal() {
         if (mPreDrawRegistered) {
             getViewTreeObserver().removeOnPreDrawListener(this);
             mPreDrawRegistered = false;
@@ -4741,6 +4740,8 @@
         resetResolvedDrawables();
 
         if (mEditor != null) mEditor.onDetachedFromWindow();
+
+        super.onDetachedFromWindowInternal();
     }
 
     @Override
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 0a80495..cc51a8b 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -57,6 +57,7 @@
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.Map;
 
 /**
  * ActionBarImpl is the ActionBar implementation used
@@ -355,6 +356,10 @@
         setSubtitle(mContext.getString(resId));
     }
 
+    public void captureSharedElements(Map<String, View> sharedElements) {
+        mContainerView.findSharedElements(sharedElements);
+    }
+
     public void setSelectedNavigationItem(int position) {
         switch (mActionView.getNavigationMode()) {
         case NAVIGATION_MODE_TABS:
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 1155cbb..3f90f76 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -35,11 +35,12 @@
 
     void noteEvent(int code, String name, int uid);
 
-    void noteStartWakelock(int uid, int pid, String name, int type, boolean unimportantForLogging);
+    void noteStartWakelock(int uid, int pid, String name, String historyName,
+            int type, boolean unimportantForLogging);
     void noteStopWakelock(int uid, int pid, String name, int type);
 
-    void noteStartWakelockFromSource(in WorkSource ws, int pid, String name, int type,
-            boolean unimportantForLogging);
+    void noteStartWakelockFromSource(in WorkSource ws, int pid, String name, String historyName,
+            int type, boolean unimportantForLogging);
     void noteStopWakelockFromSource(in WorkSource ws, int pid, String name, int type);
 
     void noteVibratorOn(int uid, long durationMillis);
@@ -51,7 +52,7 @@
     void noteScreenOff();
     void noteInputEvent();
     void noteUserActivity(int uid, int event);
-    void noteDataConnectionActive(String label, boolean active);
+    void noteDataConnectionActive(int type, boolean active);
     void notePhoneOn();
     void notePhoneOff();
     void notePhoneSignalStrength(in SignalStrength signalStrength);
diff --git a/core/java/com/android/internal/app/LocalePicker.java b/core/java/com/android/internal/app/LocalePicker.java
index 043964f..ec2d654 100644
--- a/core/java/com/android/internal/app/LocalePicker.java
+++ b/core/java/com/android/internal/app/LocalePicker.java
@@ -117,7 +117,7 @@
         /** - TODO: Enable when zz_ZY Pseudolocale is complete
          *  if (!localeList.contains("zz_ZY")) {
          *      localeList.add("zz_ZY");
-         *	}
+         *  }
          */
         }
         String[] locales = new String[localeList.size()];
diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java
index a3323e9..a604d84 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/core/java/com/android/internal/backup/LocalTransport.java
@@ -35,6 +35,11 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 
+import libcore.io.ErrnoException;
+import libcore.io.Libcore;
+import libcore.io.StructStat;
+import static libcore.io.OsConstants.*;
+
 /**
  * Backup transport for stashing stuff into a known location on disk, and
  * later restoring from there.  For testing only.
@@ -96,7 +101,16 @@
     }
 
     public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor data) {
-        if (DEBUG) Log.v(TAG, "performBackup() pkg=" + packageInfo.packageName);
+        if (DEBUG) {
+            try {
+            StructStat ss = Libcore.os.fstat(data.getFileDescriptor());
+            Log.v(TAG, "performBackup() pkg=" + packageInfo.packageName
+                    + " size=" + ss.st_size);
+            } catch (ErrnoException e) {
+                Log.w(TAG, "Unable to stat input file in performBackup() on "
+                        + packageInfo.packageName);
+            }
+        }
 
         File packageDir = new File(mDataDir, packageInfo.packageName);
         packageDir.mkdirs();
@@ -130,7 +144,16 @@
                         buf = new byte[bufSize];
                     }
                     changeSet.readEntityData(buf, 0, dataSize);
-                    if (DEBUG) Log.v(TAG, "  data size " + dataSize);
+                    if (DEBUG) {
+                        try {
+                            long cur = Libcore.os.lseek(data.getFileDescriptor(), 0, SEEK_CUR);
+                            Log.v(TAG, "  read entity data; new pos=" + cur);
+                        }
+                        catch (ErrnoException e) {
+                            Log.w(TAG, "Unable to stat input file in performBackup() on "
+                                    + packageInfo.packageName);
+                        }
+                    }
 
                     try {
                         entity.write(buf, 0, dataSize);
@@ -210,7 +233,9 @@
         if (mRestorePackages == null) throw new IllegalStateException("startRestore not called");
         while (++mRestorePackage < mRestorePackages.length) {
             String name = mRestorePackages[mRestorePackage].packageName;
-            if (new File(mDataDir, name).isDirectory()) {
+            // skip packages where we have a data dir but no actual contents
+            String[] contents = (new File(mDataDir, name)).list();
+            if (contents != null && contents.length > 0) {
                 if (DEBUG) Log.v(TAG, "  nextRestorePackage() = " + name);
                 return name;
             }
diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java
index 8282d23..e2a2b1e 100644
--- a/core/java/com/android/internal/net/NetworkStatsFactory.java
+++ b/core/java/com/android/internal/net/NetworkStatsFactory.java
@@ -17,6 +17,7 @@
 package com.android.internal.net;
 
 import static android.net.NetworkStats.SET_ALL;
+import static android.net.NetworkStats.TAG_ALL;
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
 import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
@@ -26,6 +27,7 @@
 import android.os.SystemClock;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.ProcFileReader;
 
 import java.io.File;
@@ -165,22 +167,32 @@
     }
 
     public NetworkStats readNetworkStatsDetail() throws IOException {
-        return readNetworkStatsDetail(UID_ALL);
+        return readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null);
     }
 
-    public NetworkStats readNetworkStatsDetail(int limitUid) throws IOException {
+    public NetworkStats readNetworkStatsDetail(int limitUid, String[] limitIfaces, int limitTag,
+            NetworkStats lastStats)
+            throws IOException {
         if (USE_NATIVE_PARSING) {
-            final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 0);
-            if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), limitUid) != 0) {
+            final NetworkStats stats;
+            if (lastStats != null) {
+                stats = lastStats;
+                stats.setElapsedRealtime(SystemClock.elapsedRealtime());
+            } else {
+                stats = new NetworkStats(SystemClock.elapsedRealtime(), -1);
+            }
+            if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), limitUid,
+                    limitIfaces, limitTag) != 0) {
                 throw new IOException("Failed to parse network stats");
             }
             if (SANITY_CHECK_NATIVE) {
-                final NetworkStats javaStats = javaReadNetworkStatsDetail(mStatsXtUid, limitUid);
+                final NetworkStats javaStats = javaReadNetworkStatsDetail(mStatsXtUid, limitUid,
+                        limitIfaces, limitTag);
                 assertEquals(javaStats, stats);
             }
             return stats;
         } else {
-            return javaReadNetworkStatsDetail(mStatsXtUid, limitUid);
+            return javaReadNetworkStatsDetail(mStatsXtUid, limitUid, limitIfaces, limitTag);
         }
     }
 
@@ -189,7 +201,8 @@
      * expected to monotonically increase since device boot.
      */
     @VisibleForTesting
-    public static NetworkStats javaReadNetworkStatsDetail(File detailPath, int limitUid)
+    public static NetworkStats javaReadNetworkStatsDetail(File detailPath, int limitUid,
+            String[] limitIfaces, int limitTag)
             throws IOException {
         final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
 
@@ -222,7 +235,9 @@
                 entry.txBytes = reader.nextLong();
                 entry.txPackets = reader.nextLong();
 
-                if (limitUid == UID_ALL || limitUid == entry.uid) {
+                if ((limitIfaces == null || ArrayUtils.contains(limitIfaces, entry.iface))
+                        && (limitUid == UID_ALL || limitUid == entry.uid)
+                        && (limitTag == TAG_ALL || limitTag == entry.tag)) {
                     stats.addValues(entry);
                 }
 
@@ -264,5 +279,5 @@
      */
     @VisibleForTesting
     public static native int nativeReadNetworkStatsDetail(
-            NetworkStats stats, String path, int limitUid);
+            NetworkStats stats, String path, int limitUid, String[] limitIfaces, int limitTag);
 }
diff --git a/core/java/com/android/internal/os/BatterySipper.java b/core/java/com/android/internal/os/BatterySipper.java
index 4eff5ac..6ca24d7 100644
--- a/core/java/com/android/internal/os/BatterySipper.java
+++ b/core/java/com/android/internal/os/BatterySipper.java
@@ -34,6 +34,9 @@
     public long wakeLockTime;
     public long mobileRxPackets;
     public long mobileTxPackets;
+    public long mobileActive;
+    public int mobileActiveCount;
+    public double mobilemspp;         // milliseconds per packet
     public long wifiRxPackets;
     public long wifiTxPackets;
     public long mobileRxBytes;
@@ -69,6 +72,11 @@
         return values;
     }
 
+    public void computeMobilemspp() {
+        long packets = mobileRxPackets+mobileTxPackets;
+        mobilemspp = packets > 0 ? (mobileActive / (double)packets) : 0;
+    }
+
     @Override
     public int compareTo(BatterySipper other) {
         // Return the flipped value because we want the items in descending order
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index 8a15c99..1dd1f5e 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -43,6 +43,7 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 
@@ -73,9 +74,13 @@
             = new SparseArray<List<BatterySipper>>();
     private final SparseArray<Double> mUserPower = new SparseArray<Double>();
 
+    private final List<BatterySipper> mMobilemsppList = new ArrayList<BatterySipper>();
+
     private int mStatsType = BatteryStats.STATS_SINCE_CHARGED;
     private int mAsUser = 0;
 
+    long mRawRealtime;
+    long mRawUptime;
     long mBatteryRealtime;
     long mBatteryUptime;
     long mTypeBatteryRealtime;
@@ -90,6 +95,9 @@
     private double mMinDrainedPower;
     private double mMaxDrainedPower;
 
+    // How much the apps together have kept the mobile radio active.
+    private long mAppMobileActive;
+
     // How much the apps together have left WIFI running.
     private long mAppWifiRunning;
 
@@ -132,7 +140,7 @@
     }
 
     public static String makemAh(double power) {
-        if (power < .0001) return String.format("%.8f", power);
+        if (power < .00001) return String.format("%.8f", power);
         else if (power < .0001) return String.format("%.7f", power);
         else if (power < .001) return String.format("%.6f", power);
         else if (power < .01) return String.format("%.5f", power);
@@ -151,7 +159,7 @@
                 SystemClock.uptimeMillis() * 1000);
     }
 
-    public void refreshStats(int statsType, int asUser, long rawRealtimeNano, long rawUptimeNano) {
+    public void refreshStats(int statsType, int asUser, long rawRealtimeUs, long rawUptimeUs) {
         // Initialize mStats if necessary.
         getStats();
 
@@ -160,6 +168,7 @@
         mTotalPower = 0;
         mWifiPower = 0;
         mBluetoothPower = 0;
+        mAppMobileActive = 0;
         mAppWifiRunning = 0;
 
         mUsageList.clear();
@@ -167,6 +176,7 @@
         mBluetoothSippers.clear();
         mUserSippers.clear();
         mUserPower.clear();
+        mMobilemsppList.clear();
 
         if (mStats == null) {
             return;
@@ -174,14 +184,16 @@
 
         mStatsType = statsType;
         mAsUser = asUser;
-        mBatteryUptime = mStats.getBatteryUptime(rawUptimeNano);
-        mBatteryRealtime = mStats.getBatteryRealtime(rawRealtimeNano);
-        mTypeBatteryUptime = mStats.computeBatteryUptime(rawUptimeNano, mStatsType);
-        mTypeBatteryRealtime = mStats.computeBatteryRealtime(rawRealtimeNano, mStatsType);
+        mRawUptime = rawUptimeUs;
+        mRawRealtime = rawRealtimeUs;
+        mBatteryUptime = mStats.getBatteryUptime(rawUptimeUs);
+        mBatteryRealtime = mStats.getBatteryRealtime(rawRealtimeUs);
+        mTypeBatteryUptime = mStats.computeBatteryUptime(rawUptimeUs, mStatsType);
+        mTypeBatteryRealtime = mStats.computeBatteryRealtime(rawRealtimeUs, mStatsType);
 
         if (DEBUG) {
-            Log.d(TAG, "Raw time: realtime=" + (rawRealtimeNano/1000) + " uptime="
-                    + (rawUptimeNano/1000));
+            Log.d(TAG, "Raw time: realtime=" + (rawRealtimeUs/1000) + " uptime="
+                    + (rawUptimeUs/1000));
             Log.d(TAG, "Battery time: realtime=" + (mBatteryRealtime/1000) + " uptime="
                     + (mBatteryUptime/1000));
             Log.d(TAG, "Battery type time: realtime=" + (mTypeBatteryRealtime/1000) + " uptime="
@@ -193,6 +205,37 @@
                 * mPowerProfile.getBatteryCapacity()) / 100;
 
         processAppUsage();
+
+        // Before aggregating apps in to users, collect all apps to sort by their ms per packet.
+        for (int i=0; i<mUsageList.size(); i++) {
+            BatterySipper bs = mUsageList.get(i);
+            bs.computeMobilemspp();
+            if (bs.mobilemspp != 0) {
+                mMobilemsppList.add(bs);
+            }
+        }
+        for (int i=0; i<mUserSippers.size(); i++) {
+            List<BatterySipper> user = mUserSippers.valueAt(i);
+            for (int j=0; j<user.size(); j++) {
+                BatterySipper bs = user.get(j);
+                bs.computeMobilemspp();
+                if (bs.mobilemspp != 0) {
+                    mMobilemsppList.add(bs);
+                }
+            }
+        }
+        Collections.sort(mMobilemsppList, new Comparator<BatterySipper>() {
+            @Override
+            public int compare(BatterySipper lhs, BatterySipper rhs) {
+                if (lhs.mobilemspp < rhs.mobilemspp) {
+                    return 1;
+                } else if (lhs.mobilemspp > rhs.mobilemspp) {
+                    return -1;
+                }
+                return 0;
+            }
+        });
+
         processMiscUsage();
 
         if (DEBUG) {
@@ -225,8 +268,9 @@
             powerCpuNormal[p] = mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_ACTIVE, p);
         }
         final double mobilePowerPerPacket = getMobilePowerPerPacket();
+        final double mobilePowerPerMs = getMobilePowerPerMs();
         final double wifiPowerPerPacket = getWifiPowerPerPacket();
-        long appWakelockTime = 0;
+        long appWakelockTimeUs = 0;
         BatterySipper osApp = null;
         mStatsPeriod = mTypeBatteryRealtime;
         SparseArray<? extends Uid> uidStats = mStats.getUidStats();
@@ -302,11 +346,11 @@
                 // are canceled when the user turns the screen off.
                 BatteryStats.Timer timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL);
                 if (timer != null) {
-                    wakelockTime += timer.getTotalTimeLocked(mBatteryRealtime, which);
+                    wakelockTime += timer.getTotalTimeLocked(mRawRealtime, which);
                 }
             }
+            appWakelockTimeUs += wakelockTime;
             wakelockTime /= 1000; // convert to millis
-            appWakelockTime += wakelockTime;
 
             // Add cost of holding a wake lock
             p = (wakelockTime
@@ -320,9 +364,20 @@
             final long mobileTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, mStatsType);
             final long mobileRxB = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, mStatsType);
             final long mobileTxB = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, mStatsType);
-            p = (mobileRx + mobileTx) * mobilePowerPerPacket;
+            final long mobileActive = u.getMobileRadioActiveTime(mStatsType);
+            if (mobileActive > 0) {
+                // We are tracking when the radio is up, so can use the active time to
+                // determine power use.
+                mAppMobileActive += mobileActive;
+                p = (mobilePowerPerMs * mobileActive) / 1000;
+            } else {
+                // We are not tracking when the radio is up, so must approximate power use
+                // based on the number of packets.
+                p = (mobileRx + mobileTx) * mobilePowerPerPacket;
+            }
             if (DEBUG && p != 0) Log.d(TAG, "UID " + u.getUid() + ": mobile packets "
-                    + (mobileRx+mobileTx) + " power=" + makemAh(p));
+                    + (mobileRx+mobileTx) + " active time " + mobileActive
+                    + " power=" + makemAh(p));
             power += p;
 
             // Add cost of wifi traffic
@@ -336,7 +391,7 @@
             power += p;
 
             // Add cost of keeping WIFI running.
-            long wifiRunningTimeMs = u.getWifiRunningTime(mBatteryRealtime, which) / 1000;
+            long wifiRunningTimeMs = u.getWifiRunningTime(mRawRealtime, which) / 1000;
             mAppWifiRunning += wifiRunningTimeMs;
             p = (wifiRunningTimeMs
                     * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)) / (60*60*1000);
@@ -345,14 +400,14 @@
             power += p;
 
             // Add cost of WIFI scans
-            long wifiScanTimeMs = u.getWifiScanTime(mBatteryRealtime, which) / 1000;
+            long wifiScanTimeMs = u.getWifiScanTime(mRawRealtime, which) / 1000;
             p = (wifiScanTimeMs
                     * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_SCAN)) / (60*60*1000);
             if (DEBUG) Log.d(TAG, "UID " + u.getUid() + ": wifi scan " + wifiScanTimeMs
                     + " power=" + makemAh(p));
             power += p;
             for (int bin = 0; bin < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bin++) {
-                long batchScanTimeMs = u.getWifiBatchedScanTime(bin, mBatteryRealtime, which) / 1000;
+                long batchScanTimeMs = u.getWifiBatchedScanTime(bin, mRawRealtime, which) / 1000;
                 p = ((batchScanTimeMs
                         * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_BATCHED_SCAN, bin))
                     ) / (60*60*1000);
@@ -368,7 +423,7 @@
                 Uid.Sensor sensor = sensorEntry.getValue();
                 int sensorHandle = sensor.getHandle();
                 BatteryStats.Timer timer = sensor.getSensorTime();
-                long sensorTime = timer.getTotalTimeLocked(mBatteryRealtime, which) / 1000;
+                long sensorTime = timer.getTotalTimeLocked(mRawRealtime, which) / 1000;
                 double multiplier = 0;
                 switch (sensorHandle) {
                     case Uid.Sensor.GPS:
@@ -406,6 +461,8 @@
                 app.wakeLockTime = wakelockTime;
                 app.mobileRxPackets = mobileRx;
                 app.mobileTxPackets = mobileTx;
+                app.mobileActive = mobileActive / 1000;
+                app.mobileActiveCount = u.getMobileRadioActiveCount(mStatsType);
                 app.wifiRxPackets = wifiRx;
                 app.wifiTxPackets = wifiTx;
                 app.mobileRxBytes = mobileRxB;
@@ -452,8 +509,8 @@
         // this remainder to the OS, if possible.
         if (osApp != null) {
             long wakeTimeMillis = mBatteryUptime / 1000;
-            wakeTimeMillis -= appWakelockTime
-                    + (mStats.getScreenOnTime(mBatteryRealtime, which) / 1000);
+            wakeTimeMillis -= (appWakelockTimeUs / 1000)
+                    + (mStats.getScreenOnTime(mRawRealtime, which) / 1000);
             if (wakeTimeMillis > 0) {
                 double power = (wakeTimeMillis
                         * mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_AWAKE))
@@ -470,24 +527,24 @@
     }
 
     private void addPhoneUsage() {
-        long phoneOnTimeMs = mStats.getPhoneOnTime(mBatteryRealtime, mStatsType) / 1000;
+        long phoneOnTimeMs = mStats.getPhoneOnTime(mRawRealtime, mStatsType) / 1000;
         double phoneOnPower = mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE)
                 * phoneOnTimeMs / (60*60*1000);
         if (phoneOnPower != 0) {
-            addEntry(BatterySipper.DrainType.PHONE, phoneOnTimeMs, phoneOnPower);
+            BatterySipper bs = addEntry(BatterySipper.DrainType.PHONE, phoneOnTimeMs, phoneOnPower);
         }
     }
 
     private void addScreenUsage() {
         double power = 0;
-        long screenOnTimeMs = mStats.getScreenOnTime(mBatteryRealtime, mStatsType) / 1000;
+        long screenOnTimeMs = mStats.getScreenOnTime(mRawRealtime, mStatsType) / 1000;
         power += screenOnTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_SCREEN_ON);
         final double screenFullPower =
                 mPowerProfile.getAveragePower(PowerProfile.POWER_SCREEN_FULL);
         for (int i = 0; i < BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS; i++) {
             double screenBinPower = screenFullPower * (i + 0.5f)
                     / BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS;
-            long brightnessTime = mStats.getScreenBrightnessTime(i, mBatteryRealtime, mStatsType)
+            long brightnessTime = mStats.getScreenBrightnessTime(i, mRawRealtime, mStatsType)
                     / 1000;
             double p = screenBinPower*brightnessTime;
             if (DEBUG && p != 0) {
@@ -508,7 +565,7 @@
         long signalTimeMs = 0;
         long noCoverageTimeMs = 0;
         for (int i = 0; i < BINS; i++) {
-            long strengthTimeMs = mStats.getPhoneSignalStrengthTime(i, mBatteryRealtime, mStatsType)
+            long strengthTimeMs = mStats.getPhoneSignalStrengthTime(i, mRawRealtime, mStatsType)
                     / 1000;
             double p = (strengthTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ON, i))
                         / (60*60*1000);
@@ -522,7 +579,7 @@
                 noCoverageTimeMs = strengthTimeMs;
             }
         }
-        long scanningTimeMs = mStats.getPhoneSignalScanningTime(mBatteryRealtime, mStatsType)
+        long scanningTimeMs = mStats.getPhoneSignalScanningTime(mRawRealtime, mStatsType)
                 / 1000;
         double p = (scanningTimeMs * mPowerProfile.getAveragePower(
                         PowerProfile.POWER_RADIO_SCANNING))
@@ -531,12 +588,19 @@
             Log.d(TAG, "Cell radio scanning: time=" + scanningTimeMs + " power=" + makemAh(p));
         }
         power += p;
+        long radioActiveTimeUs = mStats.getMobileRadioActiveTime(mRawRealtime, mStatsType);
+        long remainingActiveTime = (radioActiveTimeUs - mAppMobileActive) / 1000;
+        if (remainingActiveTime > 0) {
+            power += getMobilePowerPerMs() * remainingActiveTime;
+        }
         if (power != 0) {
             BatterySipper bs =
                     addEntry(BatterySipper.DrainType.CELL, signalTimeMs, power);
             if (signalTimeMs != 0) {
                 bs.noCoveragePercent = noCoverageTimeMs * 100.0 / signalTimeMs;
             }
+            bs.mobileActive = remainingActiveTime;
+            bs.mobileActiveCount = mStats.getMobileRadioActiveUnknownCount(mStatsType);
         }
     }
 
@@ -551,6 +615,8 @@
             bs.wakeLockTime += wbs.wakeLockTime;
             bs.mobileRxPackets += wbs.mobileRxPackets;
             bs.mobileTxPackets += wbs.mobileTxPackets;
+            bs.mobileActive += wbs.mobileActive;
+            bs.mobileActiveCount += wbs.mobileActiveCount;
             bs.wifiRxPackets += wbs.wifiRxPackets;
             bs.wifiTxPackets += wbs.wifiTxPackets;
             bs.mobileRxBytes += wbs.mobileRxBytes;
@@ -558,11 +624,12 @@
             bs.wifiRxBytes += wbs.wifiRxBytes;
             bs.wifiTxBytes += wbs.wifiTxBytes;
         }
+        bs.computeMobilemspp();
     }
 
     private void addWiFiUsage() {
-        long onTimeMs = mStats.getWifiOnTime(mBatteryRealtime, mStatsType) / 1000;
-        long runningTimeMs = mStats.getGlobalWifiRunningTime(mBatteryRealtime, mStatsType) / 1000;
+        long onTimeMs = mStats.getWifiOnTime(mRawRealtime, mStatsType) / 1000;
+        long runningTimeMs = mStats.getGlobalWifiRunningTime(mRawRealtime, mStatsType) / 1000;
         if (DEBUG) Log.d(TAG, "WIFI runningTime=" + runningTimeMs
                 + " app runningTime=" + mAppWifiRunning);
         runningTimeMs -= mAppWifiRunning;
@@ -583,7 +650,7 @@
 
     private void addIdleUsage() {
         long idleTimeMs = (mTypeBatteryRealtime
-                - mStats.getScreenOnTime(mBatteryRealtime, mStatsType)) / 1000;
+                - mStats.getScreenOnTime(mRawRealtime, mStatsType)) / 1000;
         double idlePower = (idleTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_IDLE))
                 / (60*60*1000);
         if (DEBUG && idlePower != 0) {
@@ -595,7 +662,7 @@
     }
 
     private void addBluetoothUsage() {
-        long btOnTimeMs = mStats.getBluetoothOnTime(mBatteryRealtime, mStatsType) / 1000;
+        long btOnTimeMs = mStats.getBluetoothOnTime(mRawRealtime, mStatsType) / 1000;
         double btPower = btOnTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_ON)
                 / (60*60*1000);
         if (DEBUG && btPower != 0) {
@@ -641,15 +708,22 @@
         final long mobileData = mobileRx + mobileTx;
 
         final long radioDataUptimeMs
-                = mStats.getMobileRadioActiveTime(mBatteryRealtime, mStatsType) / 1000;
-        final double mobilePps = radioDataUptimeMs != 0
-                ? mobileData / (double)radioDataUptimeMs
+                = mStats.getMobileRadioActiveTime(mRawRealtime, mStatsType) / 1000;
+        final double mobilePps = (mobileData != 0 && radioDataUptimeMs != 0)
+                ? (mobileData / (double)radioDataUptimeMs)
                 : (((double)MOBILE_BPS) / 8 / 2048);
 
         return (MOBILE_POWER / mobilePps) / (60*60);
     }
 
     /**
+     * Return estimated power (in mAs) of keeping the radio up
+     */
+    private double getMobilePowerPerMs() {
+        return mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE) / (60*60*1000);
+    }
+
+    /**
      * Return estimated power (in mAs) of sending a byte with the Wi-Fi radio.
      */
     private double getWifiPowerPerPacket() {
@@ -691,6 +765,10 @@
         return mUsageList;
     }
 
+    public List<BatterySipper> getMobilemsppList() {
+        return mMobilemsppList;
+    }
+
     public long getStatsPeriod() { return mStatsPeriod; }
 
     public int getStatsType() { return mStatsType; };
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 274e267..db21906 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.os;
 
+import static android.net.NetworkStats.UID_ALL;
 import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
 
 import android.bluetooth.BluetoothDevice;
@@ -52,9 +53,9 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.net.NetworkStatsFactory;
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.JournaledFile;
-import com.google.android.collect.Sets;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -63,7 +64,6 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -87,7 +87,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 85 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 98 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -174,7 +174,15 @@
 
     // These are the objects that will want to do something when the device
     // is unplugged from power.
-    final ArrayList<Unpluggable> mUnpluggables = new ArrayList<Unpluggable>();
+    final TimeBase mOnBatteryTimeBase = new TimeBase();
+
+    // These are the objects that will want to do something when the device
+    // is unplugged from power *and* the screen is off.
+    final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase();
+
+    // Set to true when we want to distribute CPU across wakelocks for the next
+    // CPU update, even if we aren't currently running wake locks.
+    boolean mDistributeWakelockCpu;
 
     boolean mShuttingDown;
 
@@ -217,11 +225,6 @@
 
     long mStartClockTime;
 
-    long mBatteryUptime;
-    long mBatteryLastUptime;
-    long mBatteryRealtime;
-    long mBatteryLastRealtime;
-
     long mUptime;
     long mUptimeStart;
     long mLastUptime;
@@ -283,6 +286,9 @@
 
     boolean mMobileRadioActive;
     StopwatchTimer mMobileRadioActiveTimer;
+    StopwatchTimer mMobileRadioActivePerAppTimer;
+    LongSamplingCounter mMobileRadioActiveUnknownTime;
+    LongSamplingCounter mMobileRadioActiveUnknownCount;
 
     /** Bluetooth headset object */
     BluetoothHeadset mBtHeadset;
@@ -293,13 +299,6 @@
      */
     boolean mOnBattery;
     boolean mOnBatteryInternal;
-    long mTrackBatteryPastUptime;
-    long mTrackBatteryUptimeStart;
-    long mTrackBatteryPastRealtime;
-    long mTrackBatteryRealtimeStart;
-
-    long mUnpluggedBatteryUptime;
-    long mUnpluggedBatteryRealtime;
 
     /*
      * These keep track of battery levels (1-100) at the last plug event and the last unplug event.
@@ -370,12 +369,17 @@
             new HashMap<String, KernelWakelockStats>();
 
     private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
-    private NetworkStats mLastSnapshot;
+    private NetworkStats mCurMobileSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 50);
+    private NetworkStats mLastMobileSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 50);
+    private NetworkStats mCurWifiSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 50);
+    private NetworkStats mLastWifiSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 50);
+    private NetworkStats mTmpNetworkStats;
+    private final NetworkStats.Entry mTmpNetworkStatsEntry = new NetworkStats.Entry();
 
     @GuardedBy("this")
-    private HashSet<String> mMobileIfaces = Sets.newHashSet();
+    private String[] mMobileIfaces = new String[0];
     @GuardedBy("this")
-    private HashSet<String> mWifiIfaces = Sets.newHashSet();
+    private String[] mWifiIfaces = new String[0];
 
     // For debugging
     public BatteryStatsImpl() {
@@ -383,35 +387,235 @@
         mHandler = null;
     }
 
-    public static interface Unpluggable {
-        void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime);
-        void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime);
+    public static interface TimeBaseObs {
+        void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime);
+        void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime);
+    }
+
+    static class TimeBase {
+        private final ArrayList<TimeBaseObs> mObservers = new ArrayList<TimeBaseObs>();
+
+        private long mUptime;
+        private long mLastUptime;
+        private long mRealtime;
+        private long mLastRealtime;
+
+        private boolean mRunning;
+
+        private long mPastUptime;
+        private long mUptimeStart;
+        private long mPastRealtime;
+        private long mRealtimeStart;
+        private long mUnpluggedUptime;
+        private long mUnpluggedRealtime;
+
+        public void dump(PrintWriter pw, String prefix) {
+            StringBuilder sb = new StringBuilder(128);
+            pw.print(prefix); pw.print("mRunning="); pw.println(mRunning);
+            sb.setLength(0);
+            sb.append(prefix);
+                    sb.append("mUptime=");
+                    formatTimeMs(sb, mUptime / 1000); sb.append("mLastUptime=");
+                    formatTimeMs(sb, mLastUptime / 1000);
+            pw.println(sb.toString());
+            sb.setLength(0);
+            sb.append(prefix);
+                    sb.append("mRealtime=");
+                    formatTimeMs(sb, mRealtime / 1000); sb.append("mLastRealtime=");
+                    formatTimeMs(sb, mLastRealtime / 1000);
+            pw.println(sb.toString());
+            sb.setLength(0);
+            sb.append(prefix);
+                    sb.append("mPastUptime=");
+                    formatTimeMs(sb, mPastUptime / 1000); sb.append("mUptimeStart=");
+                    formatTimeMs(sb, mUptimeStart / 1000);
+                    sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptime / 1000);
+            pw.println(sb.toString());
+            sb.setLength(0);
+            sb.append(prefix);
+                    sb.append("mPastRealtime=");
+                    formatTimeMs(sb, mPastRealtime / 1000); sb.append("mRealtimeStart=");
+                    formatTimeMs(sb, mRealtimeStart / 1000);
+                    sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtime / 1000);
+            pw.println(sb.toString());
+        }
+
+        public void add(TimeBaseObs observer) {
+            mObservers.add(observer);
+        }
+
+        public void remove(TimeBaseObs observer) {
+            if (!mObservers.remove(observer)) {
+                Slog.wtf(TAG, "Removed unknown observer: " + observer);
+            }
+        }
+
+        public void init(long uptime, long realtime) {
+            mRealtime = 0;
+            mUptime = 0;
+            mPastUptime = 0;
+            mPastRealtime = 0;
+            mUptimeStart = uptime;
+            mRealtimeStart = realtime;
+            mUnpluggedUptime = getUptime(mUptimeStart);
+            mUnpluggedRealtime = getRealtime(mRealtimeStart);
+        }
+
+        public void reset(long uptime, long realtime) {
+            if (!mRunning) {
+                mPastUptime = 0;
+                mPastRealtime = 0;
+            } else {
+                mUptimeStart = uptime;
+                mRealtimeStart = realtime;
+                mUnpluggedUptime = getUptime(uptime);
+                mUnpluggedRealtime = getRealtime(realtime);
+            }
+        }
+
+        public long computeUptime(long curTime, int which) {
+            switch (which) {
+                case STATS_SINCE_CHARGED:
+                    return mUptime + getUptime(curTime);
+                case STATS_LAST:
+                    return mLastUptime;
+                case STATS_CURRENT:
+                    return getUptime(curTime);
+                case STATS_SINCE_UNPLUGGED:
+                    return getUptime(curTime) - mUnpluggedUptime;
+            }
+            return 0;
+        }
+
+        public long computeRealtime(long curTime, int which) {
+            switch (which) {
+                case STATS_SINCE_CHARGED:
+                    return mRealtime + getRealtime(curTime);
+                case STATS_LAST:
+                    return mLastRealtime;
+                case STATS_CURRENT:
+                    return getRealtime(curTime);
+                case STATS_SINCE_UNPLUGGED:
+                    return getRealtime(curTime) - mUnpluggedRealtime;
+            }
+            return 0;
+        }
+
+        public long getUptime(long curTime) {
+            long time = mPastUptime;
+            if (mRunning) {
+                time += curTime - mUptimeStart;
+            }
+            return time;
+        }
+
+        public long getRealtime(long curTime) {
+            long time = mPastRealtime;
+            if (mRunning) {
+                time += curTime - mRealtimeStart;
+            }
+            return time;
+        }
+
+        public long getUptimeStart() {
+            return mUptimeStart;
+        }
+
+        public long getRealtimeStart() {
+            return mRealtimeStart;
+        }
+
+        public boolean isRunning() {
+            return mRunning;
+        }
+
+        public boolean setRunning(boolean running, long uptime, long realtime) {
+            if (mRunning != running) {
+                mRunning = running;
+                if (running) {
+                    mUptimeStart = uptime;
+                    mRealtimeStart = realtime;
+                    long batteryUptime = mUnpluggedUptime = getUptime(uptime);
+                    long batteryRealtime = mUnpluggedRealtime = getRealtime(realtime);
+
+                    for (int i = mObservers.size() - 1; i >= 0; i--) {
+                        mObservers.get(i).onTimeStarted(realtime, batteryUptime, batteryRealtime);
+                    }
+                } else {
+                    mPastUptime += uptime - mUptimeStart;
+                    mPastRealtime += realtime - mRealtimeStart;
+
+                    long batteryUptime = getUptime(uptime);
+                    long batteryRealtime = getRealtime(realtime);
+
+                    for (int i = mObservers.size() - 1; i >= 0; i--) {
+                        mObservers.get(i).onTimeStopped(realtime, batteryUptime, batteryRealtime);
+                    }
+                }
+                return true;
+            }
+            return false;
+        }
+
+        public void readSummaryFromParcel(Parcel in) {
+            mUptime = in.readLong();
+            mRealtime = in.readLong();
+        }
+
+        public void writeSummaryToParcel(Parcel out, long uptime, long realtime) {
+            out.writeLong(computeUptime(uptime, STATS_SINCE_CHARGED));
+            out.writeLong(computeRealtime(realtime, STATS_SINCE_CHARGED));
+        }
+
+        public void readFromParcel(Parcel in) {
+            mRunning = false;
+            mUptime = in.readLong();
+            mLastUptime = 0;
+            mPastUptime = in.readLong();
+            mUptimeStart = in.readLong();
+            mPastRealtime = in.readLong();
+            mRealtimeStart = in.readLong();
+            mUnpluggedUptime = in.readLong();
+            mUnpluggedRealtime = in.readLong();
+        }
+
+        public void writeToParcel(Parcel out, long uptime, long realtime) {
+            final long runningUptime = getUptime(uptime);
+            final long runningRealtime = getRealtime(realtime);
+            out.writeLong(mUptime);
+            out.writeLong(runningUptime);
+            out.writeLong(mUptimeStart);
+            out.writeLong(runningRealtime);
+            out.writeLong(mRealtimeStart);
+            out.writeLong(mUnpluggedUptime);
+            out.writeLong(mUnpluggedRealtime);
+        }
     }
 
     /**
      * State for keeping track of counting information.
      */
-    public static class Counter extends BatteryStats.Counter implements Unpluggable {
+    public static class Counter extends BatteryStats.Counter implements TimeBaseObs {
         final AtomicInteger mCount = new AtomicInteger();
-        final ArrayList<Unpluggable> mUnpluggables;
+        final TimeBase mTimeBase;
         int mLoadedCount;
         int mLastCount;
         int mUnpluggedCount;
         int mPluggedCount;
 
-        Counter(ArrayList<Unpluggable> unpluggables, Parcel in) {
-            mUnpluggables = unpluggables;
+        Counter(TimeBase timeBase, Parcel in) {
+            mTimeBase = timeBase;
             mPluggedCount = in.readInt();
             mCount.set(mPluggedCount);
             mLoadedCount = in.readInt();
             mLastCount = 0;
             mUnpluggedCount = in.readInt();
-            unpluggables.add(this);
+            timeBase.add(this);
         }
 
-        Counter(ArrayList<Unpluggable> unpluggables) {
-            mUnpluggables = unpluggables;
-            unpluggables.add(this);
+        Counter(TimeBase timeBase) {
+            mTimeBase = timeBase;
+            timeBase.add(this);
         }
 
         public void writeToParcel(Parcel out) {
@@ -420,12 +624,12 @@
             out.writeInt(mUnpluggedCount);
         }
 
-        public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+        public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
             mUnpluggedCount = mPluggedCount;
             mCount.set(mPluggedCount);
         }
 
-        public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+        public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
             mPluggedCount = mCount.get();
         }
 
@@ -485,7 +689,7 @@
         }
 
         void detach() {
-            mUnpluggables.remove(this);
+            mTimeBase.remove(this);
         }
 
         void writeSummaryFromParcelLocked(Parcel out) {
@@ -502,12 +706,12 @@
     }
 
     public static class SamplingCounter extends Counter {
-        SamplingCounter(ArrayList<Unpluggable> unpluggables, Parcel in) {
-            super(unpluggables, in);
+        SamplingCounter(TimeBase timeBase, Parcel in) {
+            super(timeBase, in);
         }
 
-        SamplingCounter(ArrayList<Unpluggable> unpluggables) {
-            super(unpluggables);
+        SamplingCounter(TimeBase timeBase) {
+            super(timeBase);
         }
 
         public void addCountAtomic(long count) {
@@ -515,27 +719,27 @@
         }
     }
 
-    public static class LongSamplingCounter implements Unpluggable {
-        final ArrayList<Unpluggable> mUnpluggables;
+    public static class LongSamplingCounter implements TimeBaseObs {
+        final TimeBase mTimeBase;
         long mCount;
         long mLoadedCount;
         long mLastCount;
         long mUnpluggedCount;
         long mPluggedCount;
 
-        LongSamplingCounter(ArrayList<Unpluggable> unpluggables, Parcel in) {
-            mUnpluggables = unpluggables;
+        LongSamplingCounter(TimeBase timeBase, Parcel in) {
+            mTimeBase = timeBase;
             mPluggedCount = in.readLong();
             mCount = mPluggedCount;
             mLoadedCount = in.readLong();
             mLastCount = 0;
             mUnpluggedCount = in.readLong();
-            unpluggables.add(this);
+            timeBase.add(this);
         }
 
-        LongSamplingCounter(ArrayList<Unpluggable> unpluggables) {
-            mUnpluggables = unpluggables;
-            unpluggables.add(this);
+        LongSamplingCounter(TimeBase timeBase) {
+            mTimeBase = timeBase;
+            timeBase.add(this);
         }
 
         public void writeToParcel(Parcel out) {
@@ -545,13 +749,13 @@
         }
 
         @Override
-        public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+        public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
             mUnpluggedCount = mPluggedCount;
             mCount = mPluggedCount;
         }
 
         @Override
-        public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+        public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
             mPluggedCount = mCount;
         }
 
@@ -587,7 +791,7 @@
         }
 
         void detach() {
-            mUnpluggables.remove(this);
+            mTimeBase.remove(this);
         }
 
         void writeSummaryFromParcelLocked(Parcel out) {
@@ -605,9 +809,9 @@
     /**
      * State for keeping track of timing information.
      */
-    public static abstract class Timer extends BatteryStats.Timer implements Unpluggable {
+    public static abstract class Timer extends BatteryStats.Timer implements TimeBaseObs {
         final int mType;
-        final ArrayList<Unpluggable> mUnpluggables;
+        final TimeBase mTimeBase;
 
         int mCount;
         int mLoadedCount;
@@ -646,12 +850,12 @@
         /**
          * Constructs from a parcel.
          * @param type
-         * @param unpluggables
+         * @param timeBase
          * @param in
          */
-        Timer(int type, ArrayList<Unpluggable> unpluggables, Parcel in) {
+        Timer(int type, TimeBase timeBase, Parcel in) {
             mType = type;
-            mUnpluggables = unpluggables;
+            mTimeBase = timeBase;
 
             mCount = in.readInt();
             mLoadedCount = in.readInt();
@@ -661,13 +865,13 @@
             mLoadedTime = in.readLong();
             mLastTime = 0;
             mUnpluggedTime = in.readLong();
-            unpluggables.add(this);
+            timeBase.add(this);
         }
 
-        Timer(int type, ArrayList<Unpluggable> unpluggables) {
+        Timer(int type, TimeBase timeBase) {
             mType = type;
-            mUnpluggables = unpluggables;
-            unpluggables.add(this);
+            mTimeBase = timeBase;
+            timeBase.add(this);
         }
 
         protected abstract long computeRunTimeLocked(long curBatteryRealtime);
@@ -678,7 +882,7 @@
          * Clear state of this timer.  Returns true if the timer is inactive
          * so can be completely dropped.
          */
-        boolean reset(BatteryStatsImpl stats, boolean detachIfReset) {
+        boolean reset(boolean detachIfReset) {
             mTotalTime = mLoadedTime = mLastTime = 0;
             mCount = mLoadedCount = mLastCount = 0;
             if (detachIfReset) {
@@ -688,25 +892,25 @@
         }
 
         void detach() {
-            mUnpluggables.remove(this);
+            mTimeBase.remove(this);
         }
 
-        public void writeToParcel(Parcel out, long batteryRealtime) {
+        public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
             out.writeInt(mCount);
             out.writeInt(mLoadedCount);
             out.writeInt(mUnpluggedCount);
-            out.writeLong(computeRunTimeLocked(batteryRealtime));
+            out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)));
             out.writeLong(mLoadedTime);
             out.writeLong(mUnpluggedTime);
         }
 
-        public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+        public void onTimeStarted(long elapsedRealtime, long timeBaseUptime, long baseRealtime) {
             if (DEBUG && mType < 0) {
-                Log.v(TAG, "unplug #" + mType + ": realtime=" + batteryRealtime
+                Log.v(TAG, "unplug #" + mType + ": realtime=" + baseRealtime
                         + " old mUnpluggedTime=" + mUnpluggedTime
                         + " old mUnpluggedCount=" + mUnpluggedCount);
             }
-            mUnpluggedTime = computeRunTimeLocked(batteryRealtime);
+            mUnpluggedTime = computeRunTimeLocked(baseRealtime);
             mUnpluggedCount = mCount;
             if (DEBUG && mType < 0) {
                 Log.v(TAG, "unplug #" + mType
@@ -715,12 +919,12 @@
             }
         }
 
-        public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+        public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
             if (DEBUG && mType < 0) {
-                Log.v(TAG, "plug #" + mType + ": realtime=" + batteryRealtime
+                Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtime
                         + " old mTotalTime=" + mTotalTime);
             }
-            mTotalTime = computeRunTimeLocked(batteryRealtime);
+            mTotalTime = computeRunTimeLocked(baseRealtime);
             mCount = computeCurrentCountLocked();
             if (DEBUG && mType < 0) {
                 Log.v(TAG, "plug #" + mType
@@ -734,24 +938,23 @@
          * @param out the Parcel to be written to.
          * @param timer a Timer, or null.
          */
-        public static void writeTimerToParcel(Parcel out, Timer timer,
-                long batteryRealtime) {
+        public static void writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs) {
             if (timer == null) {
                 out.writeInt(0); // indicates null
                 return;
             }
             out.writeInt(1); // indicates non-null
 
-            timer.writeToParcel(out, batteryRealtime);
+            timer.writeToParcel(out, elapsedRealtimeUs);
         }
 
         @Override
-        public long getTotalTimeLocked(long batteryRealtime, int which) {
+        public long getTotalTimeLocked(long elapsedRealtimeUs, int which) {
             long val;
             if (which == STATS_LAST) {
                 val = mLastTime;
             } else {
-                val = computeRunTimeLocked(batteryRealtime);
+                val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
                 if (which == STATS_SINCE_UNPLUGGED) {
                     val -= mUnpluggedTime;
                 } else if (which != STATS_SINCE_CHARGED) {
@@ -790,16 +993,15 @@
         }
 
 
-        void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
-            long runTime = computeRunTimeLocked(batteryRealtime);
-            // Divide by 1000 for backwards compatibility
-            out.writeLong((runTime + 500) / 1000);
+        void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) {
+            long runTime = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs));
+            out.writeLong(runTime);
             out.writeInt(mCount);
         }
 
         void readSummaryFromParcelLocked(Parcel in) {
             // Multiply by 1000 for backwards compatibility
-            mTotalTime = mLoadedTime = in.readLong() * 1000;
+            mTotalTime = mLoadedTime = in.readLong();
             mLastTime = 0;
             mUnpluggedTime = mTotalTime;
             mCount = mLoadedCount = in.readInt();
@@ -836,7 +1038,7 @@
         /**
          * Whether we are currently in a discharge cycle.
          */
-        boolean mInDischarge;
+        boolean mTimeBaseRunning;
 
         /**
          * Whether we are currently recording reported values.
@@ -848,21 +1050,20 @@
          */
         int mUpdateVersion;
 
-        SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, Parcel in) {
-            super(0, unpluggables, in);
+        SamplingTimer(TimeBase timeBase, Parcel in) {
+            super(0, timeBase, in);
             mCurrentReportedCount = in.readInt();
             mUnpluggedReportedCount = in.readInt();
             mCurrentReportedTotalTime = in.readLong();
             mUnpluggedReportedTotalTime = in.readLong();
             mTrackingReportedValues = in.readInt() == 1;
-            mInDischarge = inDischarge;
+            mTimeBaseRunning = timeBase.isRunning();
         }
 
-        SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge,
-                boolean trackReportedValues) {
-            super(0, unpluggables);
+        SamplingTimer(TimeBase timeBase, boolean trackReportedValues) {
+            super(0, timeBase);
             mTrackingReportedValues = trackReportedValues;
-            mInDischarge = inDischarge;
+            mTimeBaseRunning = timeBase.isRunning();
         }
 
         public void setStale() {
@@ -880,7 +1081,7 @@
         }
 
         public void updateCurrentReportedCount(int count) {
-            if (mInDischarge && mUnpluggedReportedCount == 0) {
+            if (mTimeBaseRunning && mUnpluggedReportedCount == 0) {
                 // Updating the reported value for the first time.
                 mUnpluggedReportedCount = count;
                 // If we are receiving an update update mTrackingReportedValues;
@@ -890,7 +1091,7 @@
         }
 
         public void updateCurrentReportedTotalTime(long totalTime) {
-            if (mInDischarge && mUnpluggedReportedTotalTime == 0) {
+            if (mTimeBaseRunning && mUnpluggedReportedTotalTime == 0) {
                 // Updating the reported value for the first time.
                 mUnpluggedReportedTotalTime = totalTime;
                 // If we are receiving an update update mTrackingReportedValues;
@@ -899,18 +1100,18 @@
             mCurrentReportedTotalTime = totalTime;
         }
 
-        public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
-            super.unplug(elapsedRealtime, batteryUptime, batteryRealtime);
+        public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
+            super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
             if (mTrackingReportedValues) {
                 mUnpluggedReportedTotalTime = mCurrentReportedTotalTime;
                 mUnpluggedReportedCount = mCurrentReportedCount;
             }
-            mInDischarge = true;
+            mTimeBaseRunning = true;
         }
 
-        public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
-            super.plug(elapsedRealtime, batteryUptime, batteryRealtime);
-            mInDischarge = false;
+        public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
+            super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
+            mTimeBaseRunning = false;
         }
 
         public void logState(Printer pw, String prefix) {
@@ -922,17 +1123,17 @@
         }
 
         protected long computeRunTimeLocked(long curBatteryRealtime) {
-            return mTotalTime + (mInDischarge && mTrackingReportedValues
+            return mTotalTime + (mTimeBaseRunning && mTrackingReportedValues
                     ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0);
         }
 
         protected int computeCurrentCountLocked() {
-            return mCount + (mInDischarge && mTrackingReportedValues
+            return mCount + (mTimeBaseRunning && mTrackingReportedValues
                     ? mCurrentReportedCount - mUnpluggedReportedCount : 0);
         }
 
-        public void writeToParcel(Parcel out, long batteryRealtime) {
-            super.writeToParcel(out, batteryRealtime);
+        public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
+            super.writeToParcel(out, elapsedRealtimeUs);
             out.writeInt(mCurrentReportedCount);
             out.writeInt(mUnpluggedReportedCount);
             out.writeLong(mCurrentReportedTotalTime);
@@ -940,8 +1141,8 @@
             out.writeInt(mTrackingReportedValues ? 1 : 0);
         }
 
-        boolean reset(BatteryStatsImpl stats, boolean detachIfReset) {
-            super.reset(stats, detachIfReset);
+        boolean reset(boolean detachIfReset) {
+            super.reset(detachIfReset);
             setStale();
             return true;
         }
@@ -983,45 +1184,43 @@
          */
         boolean mInDischarge;
 
-        BatchTimer(Uid uid, int type, ArrayList<Unpluggable> unpluggables,
-                boolean inDischarge, Parcel in) {
-            super(type, unpluggables, in);
+        BatchTimer(Uid uid, int type, TimeBase timeBase, Parcel in) {
+            super(type, timeBase, in);
             mUid = uid;
             mLastAddedTime = in.readLong();
             mLastAddedDuration = in.readLong();
-            mInDischarge = inDischarge;
+            mInDischarge = timeBase.isRunning();
         }
 
-        BatchTimer(Uid uid, int type, ArrayList<Unpluggable> unpluggables,
-                boolean inDischarge) {
-            super(type, unpluggables);
+        BatchTimer(Uid uid, int type, TimeBase timeBase) {
+            super(type, timeBase);
             mUid = uid;
-            mInDischarge = inDischarge;
+            mInDischarge = timeBase.isRunning();
         }
 
         @Override
-        public void writeToParcel(Parcel out, long batteryRealtime) {
-            super.writeToParcel(out, batteryRealtime);
+        public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
+            super.writeToParcel(out, elapsedRealtimeUs);
             out.writeLong(mLastAddedTime);
             out.writeLong(mLastAddedDuration);
         }
 
         @Override
-        public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+        public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
             recomputeLastDuration(SystemClock.elapsedRealtime() * 1000, false);
             mInDischarge = false;
-            super.plug(elapsedRealtime, batteryUptime, batteryRealtime);
+            super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
         }
 
         @Override
-        public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+        public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
             recomputeLastDuration(elapsedRealtime, false);
             mInDischarge = true;
             // If we are still within the last added duration, then re-added whatever remains.
             if (mLastAddedTime == elapsedRealtime) {
                 mTotalTime += mLastAddedDuration;
             }
-            super.unplug(elapsedRealtime, batteryUptime, batteryRealtime);
+            super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
         }
 
         @Override
@@ -1087,11 +1286,11 @@
         }
 
         @Override
-        boolean reset(BatteryStatsImpl stats, boolean detachIfReset) {
+        boolean reset(boolean detachIfReset) {
             final long now = SystemClock.elapsedRealtime() * 1000;
             recomputeLastDuration(now, true);
             boolean stillActive = mLastAddedTime == now;
-            super.reset(stats, !stillActive && detachIfReset);
+            super.reset(!stillActive && detachIfReset);
             return !stillActive;
         }
     }
@@ -1127,16 +1326,16 @@
         boolean mInList;
 
         StopwatchTimer(Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
-                ArrayList<Unpluggable> unpluggables, Parcel in) {
-            super(type, unpluggables, in);
+                TimeBase timeBase, Parcel in) {
+            super(type, timeBase, in);
             mUid = uid;
             mTimerPool = timerPool;
             mUpdateTime = in.readLong();
         }
 
         StopwatchTimer(Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
-                ArrayList<Unpluggable> unpluggables) {
-            super(type, unpluggables);
+                TimeBase timeBase) {
+            super(type, timeBase);
             mUid = uid;
             mTimerPool = timerPool;
         }
@@ -1145,18 +1344,18 @@
             mTimeout = timeout;
         }
 
-        public void writeToParcel(Parcel out, long batteryRealtime) {
-            super.writeToParcel(out, batteryRealtime);
+        public void writeToParcel(Parcel out, long elapsedRealtimeUs) {
+            super.writeToParcel(out, elapsedRealtimeUs);
             out.writeLong(mUpdateTime);
         }
 
-        public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+        public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
             if (mNesting > 0) {
                 if (DEBUG && mType < 0) {
                     Log.v(TAG, "old mUpdateTime=" + mUpdateTime);
                 }
-                super.plug(elapsedRealtime, batteryUptime, batteryRealtime);
-                mUpdateTime = batteryRealtime;
+                super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime);
+                mUpdateTime = baseRealtime;
                 if (DEBUG && mType < 0) {
                     Log.v(TAG, "new mUpdateTime=" + mUpdateTime);
                 }
@@ -1169,13 +1368,14 @@
                     + " mAcquireTime=" + mAcquireTime);
         }
 
-        void startRunningLocked(BatteryStatsImpl stats, long elapsedRealtime) {
+        void startRunningLocked(long elapsedRealtimeMs) {
             if (mNesting++ == 0) {
-                mUpdateTime = stats.getBatteryRealtimeLocked(elapsedRealtime * 1000);
+                final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
+                mUpdateTime = batteryRealtime;
                 if (mTimerPool != null) {
                     // Accumulate time to all currently active timers before adding
                     // this new one to the pool.
-                    refreshTimersLocked(stats, mTimerPool);
+                    refreshTimersLocked(batteryRealtime, mTimerPool, null);
                     // Add this timer to the active pool
                     mTimerPool.add(this);
                 }
@@ -1194,21 +1394,35 @@
             return mNesting > 0;
         }
 
-        void stopRunningLocked(BatteryStatsImpl stats, long elapsedRealtime) {
+        long checkpointRunningLocked(long elapsedRealtimeMs) {
+            if (mNesting > 0) {
+                // We are running...
+                final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
+                if (mTimerPool != null) {
+                    return refreshTimersLocked(batteryRealtime, mTimerPool, this);
+                }
+                final long heldTime = batteryRealtime - mUpdateTime;
+                mUpdateTime = batteryRealtime;
+                mTotalTime += heldTime;
+                return heldTime;
+            }
+            return 0;
+        }
+
+        void stopRunningLocked(long elapsedRealtimeMs) {
             // Ignore attempt to stop a timer that isn't running
             if (mNesting == 0) {
                 return;
             }
             if (--mNesting == 0) {
+                final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000);
                 if (mTimerPool != null) {
                     // Accumulate time to all active counters, scaled by the total
                     // active in the pool, before taking this one out of the pool.
-                    refreshTimersLocked(stats, mTimerPool);
+                    refreshTimersLocked(batteryRealtime, mTimerPool, null);
                     // Remove this timer from the active pool
                     mTimerPool.remove(this);
                 } else {
-                    final long batteryRealtime = stats.getBatteryRealtimeLocked(
-                            elapsedRealtime * 1000);
                     mNesting = 1;
                     mTotalTime = computeRunTimeLocked(batteryRealtime);
                     mNesting = 0;
@@ -1230,19 +1444,23 @@
 
         // Update the total time for all other running Timers with the same type as this Timer
         // due to a change in timer count
-        private static void refreshTimersLocked(final BatteryStatsImpl stats,
-                final ArrayList<StopwatchTimer> pool) {
-            final long realtime = SystemClock.elapsedRealtime() * 1000;
-            final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime);
+        private static long refreshTimersLocked(long batteryRealtime,
+                final ArrayList<StopwatchTimer> pool, StopwatchTimer self) {
+            long selfTime = 0;
             final int N = pool.size();
             for (int i=N-1; i>= 0; i--) {
                 final StopwatchTimer t = pool.get(i);
                 long heldTime = batteryRealtime - t.mUpdateTime;
                 if (heldTime > 0) {
-                    t.mTotalTime += heldTime / N;
+                    final long myTime = heldTime / N;
+                    if (t == self) {
+                        selfTime = myTime;
+                    }
+                    t.mTotalTime += myTime;
                 }
                 t.mUpdateTime = batteryRealtime;
             }
+            return selfTime;
         }
 
         @Override
@@ -1261,12 +1479,11 @@
             return mCount;
         }
 
-        boolean reset(BatteryStatsImpl stats, boolean detachIfReset) {
+        boolean reset(boolean detachIfReset) {
             boolean canDetach = mNesting <= 0;
-            super.reset(stats, canDetach && detachIfReset);
+            super.reset(canDetach && detachIfReset);
             if (mNesting > 0) {
-                mUpdateTime = stats.getBatteryRealtimeLocked(
-                        SystemClock.elapsedRealtime() * 1000);
+                mUpdateTime = mTimeBase.getRealtime(SystemClock.elapsedRealtime() * 1000);
             }
             mAcquireTime = mTotalTime;
             return canDetach;
@@ -1429,8 +1646,7 @@
     public SamplingTimer getKernelWakelockTimerLocked(String name) {
         SamplingTimer kwlt = mKernelWakelockStats.get(name);
         if (kwlt == null) {
-            kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal,
-                    true /* track reported values */);
+            kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase, true /* track reported values */);
             mKernelWakelockStats.put(name, kwlt);
         }
         return kwlt;
@@ -1496,7 +1712,7 @@
     static final int DELTA_STATE_FLAG           = 0x00100000;
     // Flag in delta int: a new full state2 int follows.
     static final int DELTA_STATE2_FLAG          = 0x00200000;
-    // Flag in delta int: contains a wakelock tag.
+    // Flag in delta int: contains a wakelock or wakeReason tag.
     static final int DELTA_WAKELOCK_FLAG        = 0x00400000;
     // Flag in delta int: contains an event description.
     static final int DELTA_EVENT_FLAG           = 0x00800000;
@@ -1543,7 +1759,7 @@
         if (stateIntChanged) {
             firstToken |= DELTA_STATE_FLAG;
         }
-        if (cur.wakelockTag != null) {
+        if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
             firstToken |= DELTA_WAKELOCK_FLAG;
         }
         if (cur.eventCode != HistoryItem.EVENT_NONE) {
@@ -1579,11 +1795,24 @@
                     + " batteryPlugType=" + cur.batteryPlugType
                     + " states=0x" + Integer.toHexString(cur.states));
         }
-        if (cur.wakelockTag != null) {
-            int index = writeHistoryTag(cur.wakelockTag);
-            dest.writeInt(index);
-            if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
-                + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
+        if (cur.wakelockTag != null || cur.wakeReasonTag != null) {
+            int wakeLockIndex;
+            int wakeReasonIndex;
+            if (cur.wakelockTag != null) {
+                wakeLockIndex = writeHistoryTag(cur.wakelockTag);
+                if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
+                    + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
+            } else {
+                wakeLockIndex = 0xffff;
+            }
+            if (cur.wakeReasonTag != null) {
+                wakeReasonIndex = writeHistoryTag(cur.wakeReasonTag);
+                if (DEBUG) Slog.i(TAG, "WRITE DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
+                    + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
+            } else {
+                wakeReasonIndex = 0xffff;
+            }
+            dest.writeInt((wakeReasonIndex<<16) | wakeLockIndex);
         }
         if (cur.eventCode != HistoryItem.EVENT_NONE) {
             int index = writeHistoryTag(cur.eventTag);
@@ -1689,14 +1918,29 @@
         }
 
         if ((firstToken&DELTA_WAKELOCK_FLAG) != 0) {
-            cur.wakelockTag = cur.localWakelockTag;
-            int index = src.readInt();
-            readHistoryTag(index, cur.wakelockTag);
+            int indexes = src.readInt();
+            int wakeLockIndex = indexes&0xffff;
+            int wakeReasonIndex = (indexes>>16)&0xffff;
+            if (wakeLockIndex != 0xffff) {
+                cur.wakelockTag = cur.localWakelockTag;
+                readHistoryTag(wakeLockIndex, cur.wakelockTag);
+                if (DEBUG) Slog.i(TAG, "READ DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
+                    + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
+            } else {
+                cur.wakelockTag = null;
+            }
+            if (wakeReasonIndex != 0xffff) {
+                cur.wakeReasonTag = cur.localWakeReasonTag;
+                readHistoryTag(wakeReasonIndex, cur.wakeReasonTag);
+                if (DEBUG) Slog.i(TAG, "READ DELTA: wakeReasonTag=#" + cur.wakeReasonTag.poolIdx
+                    + " " + cur.wakeReasonTag.uid + ":" + cur.wakeReasonTag.string);
+            } else {
+                cur.wakeReasonTag = null;
+            }
             cur.numReadInts += 1;
-            if (DEBUG) Slog.i(TAG, "READ DELTA: wakelockTag=#" + cur.wakelockTag.poolIdx
-                + " " + cur.wakelockTag.uid + ":" + cur.wakelockTag.string);
         } else {
             cur.wakelockTag = null;
+            cur.wakeReasonTag = null;
         }
 
         if ((firstToken&DELTA_EVENT_FLAG) != 0) {
@@ -1728,6 +1972,7 @@
         if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE
                 && timeDiff < 1000 && (diffStates&lastDiffStates) == 0
                 && (mHistoryLastWritten.wakelockTag == null || mHistoryCur.wakelockTag == null)
+                && (mHistoryLastWritten.wakeReasonTag == null || mHistoryCur.wakeReasonTag == null)
                 && (mHistoryLastWritten.eventCode == HistoryItem.EVENT_NONE
                         || mHistoryCur.eventCode == HistoryItem.EVENT_NONE)
                 && mHistoryLastWritten.batteryLevel == mHistoryCur.batteryLevel
@@ -1752,6 +1997,13 @@
                 mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
                 mHistoryCur.wakelockTag.setTo(mHistoryLastWritten.wakelockTag);
             }
+            // If the last written history had a wake reason tag, we need to retain it.
+            // Note that the condition above made sure that we aren't in a case where
+            // both it and the current history item have a wakelock tag.
+            if (mHistoryLastWritten.wakeReasonTag != null) {
+                mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
+                mHistoryCur.wakeReasonTag.setTo(mHistoryLastWritten.wakeReasonTag);
+            }
             // If the last written history had an event, we need to retain it.
             // Note that the condition above made sure that we aren't in a case where
             // both it and the current history item have an event.
@@ -1800,6 +2052,7 @@
         writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten);
         mLastHistoryTime = curTime;
         mHistoryCur.wakelockTag = null;
+        mHistoryCur.wakeReasonTag = null;
         mHistoryCur.eventCode = HistoryItem.EVENT_NONE;
         mHistoryCur.eventTag = null;
         if (DEBUG_HISTORY) Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
@@ -1926,24 +2179,31 @@
         mHistoryOverflow = false;
     }
 
-    public void doUnplugLocked(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
-        for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
-            mUnpluggables.get(i).unplug(elapsedRealtime, batteryUptime, batteryRealtime);
+    public void updateTimeBasesLocked(boolean unplugged, boolean screenOff, long uptime,
+            long realtime) {
+        if (mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime)) {
+            if (unplugged) {
+                // Track bt headset ping count
+                mBluetoothPingStart = getCurrentBluetoothPingCount();
+                mBluetoothPingCount = 0;
+            } else {
+                // Track bt headset ping count
+                mBluetoothPingCount = getBluetoothPingCount();
+                mBluetoothPingStart = -1;
+            }
         }
 
-        // Track bt headset ping count
-        mBluetoothPingStart = getCurrentBluetoothPingCount();
-        mBluetoothPingCount = 0;
-    }
-
-    public void doPlugLocked(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
-        for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
-            mUnpluggables.get(i).plug(elapsedRealtime, batteryUptime, batteryRealtime);
+        boolean unpluggedScreenOff = unplugged && screenOff;
+        if (unpluggedScreenOff != mOnBatteryScreenOffTimeBase.isRunning()) {
+            updateKernelWakelocksLocked();
+            requestWakelockCpuUpdate();
+            if (!unpluggedScreenOff) {
+                // We are switching to no longer tracking wake locks, but we want
+                // the next CPU update we receive to take them in to account.
+                mDistributeWakelockCpu = true;
+            }
+            mOnBatteryScreenOffTimeBase.setRunning(unpluggedScreenOff, uptime, realtime);
         }
-
-        // Track bt headset ping count
-        mBluetoothPingCount = getBluetoothPingCount();
-        mBluetoothPingStart = -1;
     }
 
     public void addIsolatedUidLocked(int isolatedUid, int appUid) {
@@ -2006,7 +2266,14 @@
         addHistoryEventLocked(SystemClock.elapsedRealtime(), code, name, uid);
     }
 
-    public void noteStartWakeLocked(int uid, int pid, String name, int type,
+    private void requestWakelockCpuUpdate() {
+        if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
+            Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
+            mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS);
+        }
+    }
+
+    public void noteStartWakeLocked(int uid, int pid, String name, String historyName, int type,
             boolean unimportantForLogging) {
         uid = mapUid(uid);
         final long elapsedRealtime = SystemClock.elapsedRealtime();
@@ -2018,7 +2285,7 @@
                 if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
                         + Integer.toHexString(mHistoryCur.states));
                 mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
-                mHistoryCur.wakelockTag.string = name;
+                mHistoryCur.wakelockTag.string = historyName != null ? historyName : name;
                 mHistoryCur.wakelockTag.uid = uid;
                 mWakeLockImportant = !unimportantForLogging;
                 addHistoryRecordLocked(elapsedRealtime);
@@ -2027,7 +2294,7 @@
                     // We'll try to update the last tag.
                     mHistoryLastWritten.wakelockTag = null;
                     mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
-                    mHistoryCur.wakelockTag.string = name;
+                    mHistoryCur.wakelockTag.string = historyName != null ? historyName : name;
                     mHistoryCur.wakelockTag.uid = uid;
                     addHistoryRecordLocked(elapsedRealtime);
                 }
@@ -2036,10 +2303,7 @@
             mWakeLockNesting++;
         }
         if (uid >= 0) {
-            if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
-                Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
-                mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS);
-            }
+            requestWakelockCpuUpdate();
             getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime);
         }
     }
@@ -2057,19 +2321,16 @@
             }
         }
         if (uid >= 0) {
-            if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
-                Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
-                mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS);
-            }
+            requestWakelockCpuUpdate();
             getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime);
         }
     }
 
-    public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, int type,
-            boolean unimportantForLogging) {
+    public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
+            String historyName, int type, boolean unimportantForLogging) {
         int N = ws.size();
         for (int i=0; i<N; i++) {
-            noteStartWakeLocked(ws.get(i), pid, name, type, unimportantForLogging);
+            noteStartWakeLocked(ws.get(i), pid, name, historyName, type, unimportantForLogging);
         }
     }
 
@@ -2080,19 +2341,32 @@
         }
     }
 
+    public void noteWakeupReasonLocked(int irq, String reason) {
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason irq #" + irq + "\"" + reason +"\": "
+                + Integer.toHexString(mHistoryCur.states));
+        mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
+        mHistoryCur.wakeReasonTag.string = reason;
+        mHistoryCur.wakeReasonTag.uid = irq;
+        addHistoryRecordLocked(elapsedRealtime);
+    }
+
     public int startAddingCpuLocked() {
         mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
 
-        if (mScreenOn) {
-            return 0;
-        }
-
         final int N = mPartialTimers.size();
         if (N == 0) {
             mLastPartialTimers.clear();
+            mDistributeWakelockCpu = false;
             return 0;
         }
 
+        if (!mOnBatteryScreenOffTimeBase.isRunning() && !mDistributeWakelockCpu) {
+            return 0;
+        }
+
+        mDistributeWakelockCpu = false;
+
         // How many timers should consume CPU?  Only want to include ones
         // that have already been in the list.
         for (int i=0; i<N; i++) {
@@ -2278,15 +2552,17 @@
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(elapsedRealtime);
             mScreenOn = true;
-            mScreenOnTimer.startRunningLocked(this, elapsedRealtime);
+            mScreenOnTimer.startRunningLocked(elapsedRealtime);
             if (mScreenBrightnessBin >= 0) {
-                mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(this,
-                        elapsedRealtime);
+                mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime);
             }
 
+            updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), false,
+                    SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000);
+
             // Fake a wake lock, so we consider the device waked as long
             // as the screen is on.
-            noteStartWakeLocked(-1, -1, "screen", WAKE_TYPE_PARTIAL, false);
+            noteStartWakeLocked(-1, -1, "screen", null, WAKE_TYPE_PARTIAL, false);
             
             // Update discharge amounts.
             if (mOnBatteryInternal) {
@@ -2303,14 +2579,16 @@
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(elapsedRealtime);
             mScreenOn = false;
-            mScreenOnTimer.stopRunningLocked(this, elapsedRealtime);
+            mScreenOnTimer.stopRunningLocked(elapsedRealtime);
             if (mScreenBrightnessBin >= 0) {
-                mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this,
-                        elapsedRealtime);
+                mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
             }
 
-            noteStopWakeLocked(-1, -1, "dummy", WAKE_TYPE_PARTIAL);
-            
+            noteStopWakeLocked(-1, -1, "screen", WAKE_TYPE_PARTIAL);
+
+            updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), true,
+                    SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000);
+
             // Update discharge amounts.
             if (mOnBatteryInternal) {
                 updateDischargeScreenLevelsLocked(true, false);
@@ -2332,10 +2610,9 @@
             addHistoryRecordLocked(elapsedRealtime);
             if (mScreenOn) {
                 if (mScreenBrightnessBin >= 0) {
-                    mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this,
-                            elapsedRealtime);
+                    mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
                 }
-                mScreenBrightnessTimer[bin].startRunningLocked(this, elapsedRealtime);
+                mScreenBrightnessTimer[bin].startRunningLocked(elapsedRealtime);
             }
             mScreenBrightnessBin = bin;
         }
@@ -2346,29 +2623,31 @@
     }
 
     public void noteUserActivityLocked(int uid, int event) {
-        uid = mapUid(uid);
-        getUidStatsLocked(uid).noteUserActivityLocked(event);
+        if (mOnBatteryInternal) {
+            uid = mapUid(uid);
+            getUidStatsLocked(uid).noteUserActivityLocked(event);
+        }
     }
 
-    public void noteDataConnectionActive(String label, boolean active) {
-        try {
-            int type = Integer.parseInt(label);
-            if (ConnectivityManager.isNetworkTypeMobile(type)) {
-                final long elapsedRealtime = SystemClock.elapsedRealtime();
-                if (mMobileRadioActive != active) {
-                    if (active) mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
-                    else mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
-                    if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
-                            + Integer.toHexString(mHistoryCur.states));
-                    addHistoryRecordLocked(elapsedRealtime);
-                    mMobileRadioActive = active;
-                    if (active) mMobileRadioActiveTimer.startRunningLocked(this, elapsedRealtime);
-                    else mMobileRadioActiveTimer.stopRunningLocked(this, elapsedRealtime);
+    public void noteDataConnectionActive(int type, boolean active) {
+        if (ConnectivityManager.isNetworkTypeMobile(type)) {
+            final long elapsedRealtime = SystemClock.elapsedRealtime();
+            if (mMobileRadioActive != active) {
+                if (active) mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
+                else mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
+                if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
+                        + Integer.toHexString(mHistoryCur.states));
+                addHistoryRecordLocked(elapsedRealtime);
+                mMobileRadioActive = active;
+                if (active) {
+                    mMobileRadioActiveTimer.startRunningLocked(elapsedRealtime);
+                    mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
+                } else {
+                    updateNetworkActivityLocked(NET_UPDATE_MOBILE, elapsedRealtime);
+                    mMobileRadioActiveTimer.stopRunningLocked(elapsedRealtime);
+                    mMobileRadioActivePerAppTimer.stopRunningLocked(elapsedRealtime);
                 }
             }
-        } catch (NumberFormatException e) {
-            Slog.w(TAG, "Bad data connection label: " + label, e);
-            return;
         }
     }
 
@@ -2380,7 +2659,7 @@
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(elapsedRealtime);
             mPhoneOn = true;
-            mPhoneOnTimer.startRunningLocked(this, elapsedRealtime);
+            mPhoneOnTimer.startRunningLocked(elapsedRealtime);
         }
     }
 
@@ -2392,7 +2671,7 @@
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(elapsedRealtime);
             mPhoneOn = false;
-            mPhoneOnTimer.stopRunningLocked(this, elapsedRealtime);
+            mPhoneOnTimer.stopRunningLocked(elapsedRealtime);
         }
     }
 
@@ -2403,7 +2682,7 @@
                 continue;
             }
             while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
-                mPhoneSignalStrengthsTimer[i].stopRunningLocked(this, elapsedRealtime);
+                mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime);
             }
         }
     }
@@ -2458,7 +2737,7 @@
                 newHistory = true;
                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: "
                         + Integer.toHexString(mHistoryCur.states));
-                mPhoneSignalScanningTimer.startRunningLocked(this, elapsedRealtime);
+                mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtime);
             }
         }
 
@@ -2469,7 +2748,7 @@
                 if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: "
                         + Integer.toHexString(mHistoryCur.states));
                 newHistory = true;
-                mPhoneSignalScanningTimer.stopRunningLocked(this, elapsedRealtime);
+                mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtime);
             }
         }
 
@@ -2484,13 +2763,12 @@
 
         if (mPhoneSignalStrengthBin != strengthBin) {
             if (mPhoneSignalStrengthBin >= 0) {
-                mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(this,
+                mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(
                         elapsedRealtime);
             }
             if (strengthBin >= 0) {
                 if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) {
-                    mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(this,
-                            elapsedRealtime);
+                    mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime);
                 }
                 mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_SIGNAL_STRENGTH_MASK)
                         | (strengthBin << HistoryItem.STATE_SIGNAL_STRENGTH_SHIFT);
@@ -2585,11 +2863,11 @@
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(elapsedRealtime);
             if (mPhoneDataConnectionType >= 0) {
-                mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(this,
+                mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(
                         elapsedRealtime);
             }
             mPhoneDataConnectionType = bin;
-            mPhoneDataConnectionsTimer[bin].startRunningLocked(this, elapsedRealtime);
+            mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtime);
         }
     }
 
@@ -2601,7 +2879,7 @@
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(elapsedRealtime);
             mWifiOn = true;
-            mWifiOnTimer.startRunningLocked(this, elapsedRealtime);
+            mWifiOnTimer.startRunningLocked(elapsedRealtime);
         }
     }
 
@@ -2613,7 +2891,7 @@
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(elapsedRealtime);
             mWifiOn = false;
-            mWifiOnTimer.stopRunningLocked(this, elapsedRealtime);
+            mWifiOnTimer.stopRunningLocked(elapsedRealtime);
         }
         if (mWifiOnUid >= 0) {
             getUidStatsLocked(mWifiOnUid).noteWifiStoppedLocked(elapsedRealtime);
@@ -2630,7 +2908,7 @@
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(SystemClock.elapsedRealtime());
             mAudioOn = true;
-            mAudioOnTimer.startRunningLocked(this, elapsedRealtime);
+            mAudioOnTimer.startRunningLocked(elapsedRealtime);
         }
         getUidStatsLocked(uid).noteAudioTurnedOnLocked(elapsedRealtime);
     }
@@ -2644,7 +2922,7 @@
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(SystemClock.elapsedRealtime());
             mAudioOn = false;
-            mAudioOnTimer.stopRunningLocked(this, elapsedRealtime);
+            mAudioOnTimer.stopRunningLocked(elapsedRealtime);
         }
         getUidStatsLocked(uid).noteAudioTurnedOffLocked(elapsedRealtime);
     }
@@ -2658,7 +2936,7 @@
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(SystemClock.elapsedRealtime());
             mVideoOn = true;
-            mVideoOnTimer.startRunningLocked(this, elapsedRealtime);
+            mVideoOnTimer.startRunningLocked(elapsedRealtime);
         }
         getUidStatsLocked(uid).noteVideoTurnedOnLocked(elapsedRealtime);
     }
@@ -2672,7 +2950,7 @@
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(SystemClock.elapsedRealtime());
             mVideoOn = false;
-            mVideoOnTimer.stopRunningLocked(this, elapsedRealtime);
+            mVideoOnTimer.stopRunningLocked(elapsedRealtime);
         }
         getUidStatsLocked(uid).noteVideoTurnedOffLocked(elapsedRealtime);
     }
@@ -2705,7 +2983,7 @@
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(SystemClock.elapsedRealtime());
             mGlobalWifiRunning = true;
-            mGlobalWifiRunningTimer.startRunningLocked(this, elapsedRealtime);
+            mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtime);
             int N = ws.size();
             for (int i=0; i<N; i++) {
                 int uid = mapUid(ws.get(i));
@@ -2742,7 +3020,7 @@
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(elapsedRealtime);
             mGlobalWifiRunning = false;
-            mGlobalWifiRunningTimer.stopRunningLocked(this, elapsedRealtime);
+            mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtime);
             int N = ws.size();
             for (int i=0; i<N; i++) {
                 int uid = mapUid(ws.get(i));
@@ -2758,10 +3036,10 @@
         if (mWifiState != wifiState) {
             final long elapsedRealtime = SystemClock.elapsedRealtime();
             if (mWifiState >= 0) {
-                mWifiStateTimer[mWifiState].stopRunningLocked(this, elapsedRealtime);
+                mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtime);
             }
             mWifiState = wifiState;
-            mWifiStateTimer[wifiState].startRunningLocked(this, elapsedRealtime);
+            mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime);
         }
     }
 
@@ -2773,7 +3051,7 @@
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(elapsedRealtime);
             mBluetoothOn = true;
-            mBluetoothOnTimer.startRunningLocked(this, elapsedRealtime);
+            mBluetoothOnTimer.startRunningLocked(elapsedRealtime);
         }
     }
 
@@ -2785,7 +3063,7 @@
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(elapsedRealtime);
             mBluetoothOn = false;
-            mBluetoothOnTimer.stopRunningLocked(this, elapsedRealtime);
+            mBluetoothOnTimer.stopRunningLocked(elapsedRealtime);
         }
     }
 
@@ -2794,11 +3072,10 @@
         if (mBluetoothState != bluetoothState) {
             final long elapsedRealtime = SystemClock.elapsedRealtime();
             if (mBluetoothState >= 0) {
-                mBluetoothStateTimer[mBluetoothState].stopRunningLocked(this,
-                        elapsedRealtime);
+                mBluetoothStateTimer[mBluetoothState].stopRunningLocked(elapsedRealtime);
             }
             mBluetoothState = bluetoothState;
-            mBluetoothStateTimer[bluetoothState].startRunningLocked(this, elapsedRealtime);
+            mBluetoothStateTimer[bluetoothState].startRunningLocked(elapsedRealtime);
         }
     }
 
@@ -2954,16 +3231,45 @@
         }
     }
 
+    private static String[] includeInStringArray(String[] array, String str) {
+        if (ArrayUtils.indexOf(array, str) >= 0) {
+            return array;
+        }
+        String[] newArray = new String[array.length+1];
+        System.arraycopy(array, 0, newArray, 0, array.length);
+        newArray[array.length] = str;
+        return newArray;
+    }
+
+    private static String[] excludeFromStringArray(String[] array, String str) {
+        int index = ArrayUtils.indexOf(array, str);
+        if (index >= 0) {
+            String[] newArray = new String[array.length-1];
+            if (index > 0) {
+                System.arraycopy(array, 0, newArray, 0, index);
+            }
+            if (index < array.length-1) {
+                System.arraycopy(array, index+1, newArray, index, array.length-index-1);
+            }
+            return newArray;
+        }
+        return array;
+    }
+
     public void noteNetworkInterfaceTypeLocked(String iface, int networkType) {
         if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
-            mMobileIfaces.add(iface);
+            mMobileIfaces = includeInStringArray(mMobileIfaces, iface);
+            if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mMobileIfaces);
         } else {
-            mMobileIfaces.remove(iface);
+            mMobileIfaces = excludeFromStringArray(mMobileIfaces, iface);
+            if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mMobileIfaces);
         }
         if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
-            mWifiIfaces.add(iface);
+            mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
+            if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
         } else {
-            mWifiIfaces.remove(iface);
+            mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
+            if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
         }
     }
 
@@ -2971,37 +3277,45 @@
         // During device boot, qtaguid isn't enabled until after the inital
         // loading of battery stats. Now that they're enabled, take our initial
         // snapshot for future delta calculation.
-        updateNetworkActivityLocked();
+        updateNetworkActivityLocked(NET_UPDATE_ALL, SystemClock.elapsedRealtime());
     }
 
-    @Override public long getScreenOnTime(long batteryRealtime, int which) {
-        return mScreenOnTimer.getTotalTimeLocked(batteryRealtime, which);
+    @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
+        return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
+    }
+
+    @Override public int getScreenOnCount(int which) {
+        return mScreenOnTimer.getCountLocked(which);
     }
 
     @Override public long getScreenBrightnessTime(int brightnessBin,
-            long batteryRealtime, int which) {
+            long elapsedRealtimeUs, int which) {
         return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
-                batteryRealtime, which);
+                elapsedRealtimeUs, which);
     }
 
     @Override public int getInputEventCount(int which) {
         return mInputEventCounter.getCountLocked(which);
     }
 
-    @Override public long getPhoneOnTime(long batteryRealtime, int which) {
-        return mPhoneOnTimer.getTotalTimeLocked(batteryRealtime, which);
+    @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
+        return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
+    }
+
+    @Override public int getPhoneOnCount(int which) {
+        return mPhoneOnTimer.getCountLocked(which);
     }
 
     @Override public long getPhoneSignalStrengthTime(int strengthBin,
-            long batteryRealtime, int which) {
+            long elapsedRealtimeUs, int which) {
         return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
-                batteryRealtime, which);
+                elapsedRealtimeUs, which);
     }
 
     @Override public long getPhoneSignalScanningTime(
-            long batteryRealtime, int which) {
+            long elapsedRealtimeUs, int which) {
         return mPhoneSignalScanningTimer.getTotalTimeLocked(
-                batteryRealtime, which);
+                elapsedRealtimeUs, which);
     }
 
     @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
@@ -3009,45 +3323,57 @@
     }
 
     @Override public long getPhoneDataConnectionTime(int dataType,
-            long batteryRealtime, int which) {
+            long elapsedRealtimeUs, int which) {
         return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
-                batteryRealtime, which);
+                elapsedRealtimeUs, which);
     }
 
     @Override public int getPhoneDataConnectionCount(int dataType, int which) {
         return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
     }
 
-    @Override public long getMobileRadioActiveTime(long batteryRealtime, int which) {
-        return mMobileRadioActiveTimer.getTotalTimeLocked(batteryRealtime, which);
+    @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
+        return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
     }
 
-    @Override public long getWifiOnTime(long batteryRealtime, int which) {
-        return mWifiOnTimer.getTotalTimeLocked(batteryRealtime, which);
+    @Override public int getMobileRadioActiveCount(int which) {
+        return mMobileRadioActiveTimer.getCountLocked(which);
     }
 
-    @Override public long getGlobalWifiRunningTime(long batteryRealtime, int which) {
-        return mGlobalWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which);
+    @Override public long getMobileRadioActiveUnknownTime(int which) {
+        return mMobileRadioActiveUnknownTime.getCountLocked(which);
+    }
+
+    @Override public int getMobileRadioActiveUnknownCount(int which) {
+        return (int)mMobileRadioActiveUnknownCount.getCountLocked(which);
+    }
+
+    @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) {
+        return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
+    }
+
+    @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) {
+        return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
     }
 
     @Override public long getWifiStateTime(int wifiState,
-            long batteryRealtime, int which) {
+            long elapsedRealtimeUs, int which) {
         return mWifiStateTimer[wifiState].getTotalTimeLocked(
-                batteryRealtime, which);
+                elapsedRealtimeUs, which);
     }
 
     @Override public int getWifiStateCount(int wifiState, int which) {
         return mWifiStateTimer[wifiState].getCountLocked(which);
     }
 
-    @Override public long getBluetoothOnTime(long batteryRealtime, int which) {
-        return mBluetoothOnTimer.getTotalTimeLocked(batteryRealtime, which);
+    @Override public long getBluetoothOnTime(long elapsedRealtimeUs, int which) {
+        return mBluetoothOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
     }
 
     @Override public long getBluetoothStateTime(int bluetoothState,
-            long batteryRealtime, int which) {
+            long elapsedRealtimeUs, int which) {
         return mBluetoothStateTimer[bluetoothState].getTotalTimeLocked(
-                batteryRealtime, which);
+                elapsedRealtimeUs, which);
     }
 
     @Override public int getBluetoothStateCount(int bluetoothState, int which) {
@@ -3121,6 +3447,8 @@
 
         LongSamplingCounter[] mNetworkByteActivityCounters;
         LongSamplingCounter[] mNetworkPacketActivityCounters;
+        LongSamplingCounter mMobileRadioActiveTime;
+        LongSamplingCounter mMobileRadioActiveCount;
 
         /**
          * The statistics we have collected for this uid's wake locks.
@@ -3150,14 +3478,14 @@
         public Uid(int uid) {
             mUid = uid;
             mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
-                    mWifiRunningTimers, mUnpluggables);
+                    mWifiRunningTimers, mOnBatteryTimeBase);
             mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
-                    mFullWifiLockTimers, mUnpluggables);
+                    mFullWifiLockTimers, mOnBatteryTimeBase);
             mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
-                    mWifiScanTimers, mUnpluggables);
+                    mWifiScanTimers, mOnBatteryTimeBase);
             mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS];
             mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
-                    mWifiMulticastTimers, mUnpluggables);
+                    mWifiMulticastTimers, mOnBatteryTimeBase);
         }
 
         @Override
@@ -3186,67 +3514,67 @@
         }
 
         @Override
-        public void noteWifiRunningLocked(long elapsedRealtime) {
+        public void noteWifiRunningLocked(long elapsedRealtimeMs) {
             if (!mWifiRunning) {
                 mWifiRunning = true;
                 if (mWifiRunningTimer == null) {
                     mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
-                            mWifiRunningTimers, mUnpluggables);
+                            mWifiRunningTimers, mOnBatteryTimeBase);
                 }
-                mWifiRunningTimer.startRunningLocked(BatteryStatsImpl.this, elapsedRealtime);
+                mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs);
             }
         }
 
         @Override
-        public void noteWifiStoppedLocked(long elapsedRealtime) {
+        public void noteWifiStoppedLocked(long elapsedRealtimeMs) {
             if (mWifiRunning) {
                 mWifiRunning = false;
-                mWifiRunningTimer.stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime);
+                mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs);
             }
         }
 
         @Override
-        public void noteFullWifiLockAcquiredLocked(long elapsedRealtime) {
+        public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) {
             if (!mFullWifiLockOut) {
                 mFullWifiLockOut = true;
                 if (mFullWifiLockTimer == null) {
                     mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
-                            mFullWifiLockTimers, mUnpluggables);
+                            mFullWifiLockTimers, mOnBatteryTimeBase);
                 }
-                mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this, elapsedRealtime);
+                mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs);
             }
         }
 
         @Override
-        public void noteFullWifiLockReleasedLocked(long elapsedRealtime) {
+        public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) {
             if (mFullWifiLockOut) {
                 mFullWifiLockOut = false;
-                mFullWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime);
+                mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs);
             }
         }
 
         @Override
-        public void noteWifiScanStartedLocked(long elapsedRealtime) {
+        public void noteWifiScanStartedLocked(long elapsedRealtimeMs) {
             if (!mWifiScanStarted) {
                 mWifiScanStarted = true;
                 if (mWifiScanTimer == null) {
                     mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
-                            mWifiScanTimers, mUnpluggables);
+                            mWifiScanTimers, mOnBatteryTimeBase);
                 }
-                mWifiScanTimer.startRunningLocked(BatteryStatsImpl.this, elapsedRealtime);
+                mWifiScanTimer.startRunningLocked(elapsedRealtimeMs);
             }
         }
 
         @Override
-        public void noteWifiScanStoppedLocked(long elapsedRealtime) {
+        public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) {
             if (mWifiScanStarted) {
                 mWifiScanStarted = false;
-                mWifiScanTimer.stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime);
+                mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs);
             }
         }
 
         @Override
-        public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtime) {
+        public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) {
             int bin = 0;
             while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS) {
                 csph = csph >> 3;
@@ -3257,67 +3585,66 @@
 
             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
-                        stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime);
+                        stopRunningLocked(elapsedRealtimeMs);
             }
             mWifiBatchedScanBinStarted = bin;
             if (mWifiBatchedScanTimer[bin] == null) {
                 makeWifiBatchedScanBin(bin, null);
             }
-            mWifiBatchedScanTimer[bin].startRunningLocked(BatteryStatsImpl.this, elapsedRealtime);
+            mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs);
         }
 
         @Override
-        public void noteWifiBatchedScanStoppedLocked(long elapsedRealtime) {
+        public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) {
             if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) {
                 mWifiBatchedScanTimer[mWifiBatchedScanBinStarted].
-                        stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime);
+                        stopRunningLocked(elapsedRealtimeMs);
                 mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED;
             }
         }
 
         @Override
-        public void noteWifiMulticastEnabledLocked(long elapsedRealtime) {
+        public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) {
             if (!mWifiMulticastEnabled) {
                 mWifiMulticastEnabled = true;
                 if (mWifiMulticastTimer == null) {
                     mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
-                            mWifiMulticastTimers, mUnpluggables);
+                            mWifiMulticastTimers, mOnBatteryTimeBase);
                 }
-                mWifiMulticastTimer.startRunningLocked(BatteryStatsImpl.this, elapsedRealtime);
+                mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
             }
         }
 
         @Override
-        public void noteWifiMulticastDisabledLocked(long elapsedRealtime) {
+        public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) {
             if (mWifiMulticastEnabled) {
                 mWifiMulticastEnabled = false;
-                mWifiMulticastTimer.stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime);
+                mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
             }
         }
 
         public StopwatchTimer createAudioTurnedOnTimerLocked() {
             if (mAudioTurnedOnTimer == null) {
                 mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
-                        null, mUnpluggables);
+                        null, mOnBatteryTimeBase);
             }
             return mAudioTurnedOnTimer;
         }
 
         @Override
-        public void noteAudioTurnedOnLocked(long elapsedRealtime) {
+        public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) {
             if (!mAudioTurnedOn) {
                 mAudioTurnedOn = true;
-                createAudioTurnedOnTimerLocked().startRunningLocked(BatteryStatsImpl.this,
-                        elapsedRealtime);
+                createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
             }
         }
 
         @Override
-        public void noteAudioTurnedOffLocked(long elapsedRealtime) {
+        public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) {
             if (mAudioTurnedOn) {
                 mAudioTurnedOn = false;
                 if (mAudioTurnedOnTimer != null) {
-                    mAudioTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime);
+                    mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
                 }
             }
         }
@@ -3325,26 +3652,25 @@
         public StopwatchTimer createVideoTurnedOnTimerLocked() {
             if (mVideoTurnedOnTimer == null) {
                 mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
-                        null, mUnpluggables);
+                        null, mOnBatteryTimeBase);
             }
             return mVideoTurnedOnTimer;
         }
 
         @Override
-        public void noteVideoTurnedOnLocked(long elapsedRealtime) {
+        public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) {
             if (!mVideoTurnedOn) {
                 mVideoTurnedOn = true;
-                createVideoTurnedOnTimerLocked().startRunningLocked(BatteryStatsImpl.this,
-                        elapsedRealtime);
+                createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs);
             }
         }
 
         @Override
-        public void noteVideoTurnedOffLocked(long elapsedRealtime) {
+        public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) {
             if (mVideoTurnedOn) {
                 mVideoTurnedOn = false;
                 if (mVideoTurnedOnTimer != null) {
-                    mVideoTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime);
+                    mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs);
                 }
             }
         }
@@ -3352,29 +3678,27 @@
         public StopwatchTimer createForegroundActivityTimerLocked() {
             if (mForegroundActivityTimer == null) {
                 mForegroundActivityTimer = new StopwatchTimer(
-                        Uid.this, FOREGROUND_ACTIVITY, null, mUnpluggables);
+                        Uid.this, FOREGROUND_ACTIVITY, null, mOnBatteryTimeBase);
             }
             return mForegroundActivityTimer;
         }
 
         @Override
-        public void noteActivityResumedLocked(long elapsedRealtime) {
+        public void noteActivityResumedLocked(long elapsedRealtimeMs) {
             // We always start, since we want multiple foreground PIDs to nest
-            createForegroundActivityTimerLocked().startRunningLocked(BatteryStatsImpl.this,
-                    elapsedRealtime);
+            createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs);
         }
 
         @Override
-        public void noteActivityPausedLocked(long elapsedRealtime) {
+        public void noteActivityPausedLocked(long elapsedRealtimeMs) {
             if (mForegroundActivityTimer != null) {
-                mForegroundActivityTimer.stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime);
+                mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs);
             }
         }
 
         public BatchTimer createVibratorOnTimerLocked() {
             if (mVibratorOnTimer == null) {
-                mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON,
-                        mUnpluggables, BatteryStatsImpl.this.mOnBatteryInternal);
+                mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON, mOnBatteryTimeBase);
             }
             return mVibratorOnTimer;
         }
@@ -3390,61 +3714,60 @@
         }
 
         @Override
-        public long getWifiRunningTime(long batteryRealtime, int which) {
+        public long getWifiRunningTime(long elapsedRealtimeUs, int which) {
             if (mWifiRunningTimer == null) {
                 return 0;
             }
-            return mWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which);
+            return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
         }
 
         @Override
-        public long getFullWifiLockTime(long batteryRealtime, int which) {
+        public long getFullWifiLockTime(long elapsedRealtimeUs, int which) {
             if (mFullWifiLockTimer == null) {
                 return 0;
             }
-            return mFullWifiLockTimer.getTotalTimeLocked(batteryRealtime, which);
+            return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
         }
 
         @Override
-        public long getWifiScanTime(long batteryRealtime, int which) {
+        public long getWifiScanTime(long elapsedRealtimeUs, int which) {
             if (mWifiScanTimer == null) {
                 return 0;
             }
-            return mWifiScanTimer.getTotalTimeLocked(batteryRealtime, which);
+            return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
         }
 
         @Override
-        public long getWifiBatchedScanTime(int csphBin, long batteryRealtime, int which) {
+        public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) {
             if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0;
             if (mWifiBatchedScanTimer[csphBin] == null) {
                 return 0;
             }
-            return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(batteryRealtime, which);
+            return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which);
         }
 
         @Override
-        public long getWifiMulticastTime(long batteryRealtime, int which) {
+        public long getWifiMulticastTime(long elapsedRealtimeUs, int which) {
             if (mWifiMulticastTimer == null) {
                 return 0;
             }
-            return mWifiMulticastTimer.getTotalTimeLocked(batteryRealtime,
-                                                          which);
+            return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
         }
 
         @Override
-        public long getAudioTurnedOnTime(long batteryRealtime, int which) {
+        public long getAudioTurnedOnTime(long elapsedRealtimeUs, int which) {
             if (mAudioTurnedOnTimer == null) {
                 return 0;
             }
-            return mAudioTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which);
+            return mAudioTurnedOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
         }
 
         @Override
-        public long getVideoTurnedOnTime(long batteryRealtime, int which) {
+        public long getVideoTurnedOnTime(long elapsedRealtimeUs, int which) {
             if (mVideoTurnedOnTimer == null) {
                 return 0;
             }
-            return mVideoTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which);
+            return mVideoTurnedOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
         }
 
         @Override
@@ -3493,10 +3816,10 @@
             }
             if (in == null) {
                 mWifiBatchedScanTimer[i] = new StopwatchTimer(this, WIFI_BATCHED_SCAN, collected,
-                        mUnpluggables);
+                        mOnBatteryTimeBase);
             } else {
                 mWifiBatchedScanTimer[i] = new StopwatchTimer(this, WIFI_BATCHED_SCAN, collected,
-                        mUnpluggables, in);
+                        mOnBatteryTimeBase, in);
             }
         }
 
@@ -3504,7 +3827,7 @@
         void initUserActivityLocked() {
             mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
             for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
-                mUserActivityCounters[i] = new Counter(mUnpluggables);
+                mUserActivityCounters[i] = new Counter(mOnBatteryTimeBase);
             }
         }
 
@@ -3521,6 +3844,14 @@
             }
         }
 
+        void noteMobileRadioActiveTimeLocked(long batteryUptime) {
+            if (mNetworkByteActivityCounters == null) {
+                initNetworkActivityLocked();
+            }
+            mMobileRadioActiveTime.addCountLocked(batteryUptime);
+            mMobileRadioActiveCount.addCountLocked(1);
+        }
+
         @Override
         public boolean hasNetworkActivity() {
             return mNetworkByteActivityCounters != null;
@@ -3546,13 +3877,27 @@
             }
         }
 
+        @Override
+        public long getMobileRadioActiveTime(int which) {
+            return mMobileRadioActiveTime != null
+                    ? mMobileRadioActiveTime.getCountLocked(which) : 0;
+        }
+
+        @Override
+        public int getMobileRadioActiveCount(int which) {
+            return mMobileRadioActiveCount != null
+                    ? (int)mMobileRadioActiveCount.getCountLocked(which) : 0;
+        }
+
         void initNetworkActivityLocked() {
             mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
             mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
             for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
-                mNetworkByteActivityCounters[i] = new LongSamplingCounter(mUnpluggables);
-                mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mUnpluggables);
+                mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
+                mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
             }
+            mMobileRadioActiveTime = new LongSamplingCounter(mOnBatteryTimeBase);
+            mMobileRadioActiveCount = new LongSamplingCounter(mOnBatteryTimeBase);
         }
 
         /**
@@ -3563,42 +3908,42 @@
             boolean active = false;
 
             if (mWifiRunningTimer != null) {
-                active |= !mWifiRunningTimer.reset(BatteryStatsImpl.this, false);
+                active |= !mWifiRunningTimer.reset(false);
                 active |= mWifiRunning;
             }
             if (mFullWifiLockTimer != null) {
-                active |= !mFullWifiLockTimer.reset(BatteryStatsImpl.this, false);
+                active |= !mFullWifiLockTimer.reset(false);
                 active |= mFullWifiLockOut;
             }
             if (mWifiScanTimer != null) {
-                active |= !mWifiScanTimer.reset(BatteryStatsImpl.this, false);
+                active |= !mWifiScanTimer.reset(false);
                 active |= mWifiScanStarted;
             }
             if (mWifiBatchedScanTimer != null) {
                 for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
                     if (mWifiBatchedScanTimer[i] != null) {
-                        active |= !mWifiBatchedScanTimer[i].reset(BatteryStatsImpl.this, false);
+                        active |= !mWifiBatchedScanTimer[i].reset(false);
                     }
                 }
                 active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED);
             }
             if (mWifiMulticastTimer != null) {
-                active |= !mWifiMulticastTimer.reset(BatteryStatsImpl.this, false);
+                active |= !mWifiMulticastTimer.reset(false);
                 active |= mWifiMulticastEnabled;
             }
             if (mAudioTurnedOnTimer != null) {
-                active |= !mAudioTurnedOnTimer.reset(BatteryStatsImpl.this, false);
+                active |= !mAudioTurnedOnTimer.reset(false);
                 active |= mAudioTurnedOn;
             }
             if (mVideoTurnedOnTimer != null) {
-                active |= !mVideoTurnedOnTimer.reset(BatteryStatsImpl.this, false);
+                active |= !mVideoTurnedOnTimer.reset(false);
                 active |= mVideoTurnedOn;
             }
             if (mForegroundActivityTimer != null) {
-                active |= !mForegroundActivityTimer.reset(BatteryStatsImpl.this, false);
+                active |= !mForegroundActivityTimer.reset(false);
             }
             if (mVibratorOnTimer != null) {
-                if (mVibratorOnTimer.reset(BatteryStatsImpl.this, false)) {
+                if (mVibratorOnTimer.reset(false)) {
                     mVibratorOnTimer.detach();
                     mVibratorOnTimer = null;
                 } else {
@@ -3617,6 +3962,8 @@
                     mNetworkByteActivityCounters[i].reset(false);
                     mNetworkPacketActivityCounters[i].reset(false);
                 }
+                mMobileRadioActiveTime.reset(false);
+                mMobileRadioActiveCount.reset(false);
             }
 
             if (mWakelockStats.size() > 0) {
@@ -3725,19 +4072,19 @@
             return !active;
         }
 
-        void writeToParcelLocked(Parcel out, long batteryRealtime) {
+        void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
             out.writeInt(mWakelockStats.size());
             for (Map.Entry<String, Uid.Wakelock> wakelockEntry : mWakelockStats.entrySet()) {
                 out.writeString(wakelockEntry.getKey());
                 Uid.Wakelock wakelock = wakelockEntry.getValue();
-                wakelock.writeToParcelLocked(out, batteryRealtime);
+                wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
             }
 
             out.writeInt(mSensorStats.size());
             for (Map.Entry<Integer, Uid.Sensor> sensorEntry : mSensorStats.entrySet()) {
                 out.writeInt(sensorEntry.getKey());
                 Uid.Sensor sensor = sensorEntry.getValue();
-                sensor.writeToParcelLocked(out, batteryRealtime);
+                sensor.writeToParcelLocked(out, elapsedRealtimeUs);
             }
 
             out.writeInt(mProcessStats.size());
@@ -3756,57 +4103,57 @@
 
             if (mWifiRunningTimer != null) {
                 out.writeInt(1);
-                mWifiRunningTimer.writeToParcel(out, batteryRealtime);
+                mWifiRunningTimer.writeToParcel(out, elapsedRealtimeUs);
             } else {
                 out.writeInt(0);
             }
             if (mFullWifiLockTimer != null) {
                 out.writeInt(1);
-                mFullWifiLockTimer.writeToParcel(out, batteryRealtime);
+                mFullWifiLockTimer.writeToParcel(out, elapsedRealtimeUs);
             } else {
                 out.writeInt(0);
             }
             if (mWifiScanTimer != null) {
                 out.writeInt(1);
-                mWifiScanTimer.writeToParcel(out, batteryRealtime);
+                mWifiScanTimer.writeToParcel(out, elapsedRealtimeUs);
             } else {
                 out.writeInt(0);
             }
             for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) {
                 if (mWifiBatchedScanTimer[i] != null) {
                     out.writeInt(1);
-                    mWifiBatchedScanTimer[i].writeToParcel(out, batteryRealtime);
+                    mWifiBatchedScanTimer[i].writeToParcel(out, elapsedRealtimeUs);
                 } else {
                     out.writeInt(0);
                 }
             }
             if (mWifiMulticastTimer != null) {
                 out.writeInt(1);
-                mWifiMulticastTimer.writeToParcel(out, batteryRealtime);
+                mWifiMulticastTimer.writeToParcel(out, elapsedRealtimeUs);
             } else {
                 out.writeInt(0);
             }
             if (mAudioTurnedOnTimer != null) {
                 out.writeInt(1);
-                mAudioTurnedOnTimer.writeToParcel(out, batteryRealtime);
+                mAudioTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
             } else {
                 out.writeInt(0);
             }
             if (mVideoTurnedOnTimer != null) {
                 out.writeInt(1);
-                mVideoTurnedOnTimer.writeToParcel(out, batteryRealtime);
+                mVideoTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs);
             } else {
                 out.writeInt(0);
             }
             if (mForegroundActivityTimer != null) {
                 out.writeInt(1);
-                mForegroundActivityTimer.writeToParcel(out, batteryRealtime);
+                mForegroundActivityTimer.writeToParcel(out, elapsedRealtimeUs);
             } else {
                 out.writeInt(0);
             }
             if (mVibratorOnTimer != null) {
                 out.writeInt(1);
-                mVibratorOnTimer.writeToParcel(out, batteryRealtime);
+                mVibratorOnTimer.writeToParcel(out, elapsedRealtimeUs);
             } else {
                 out.writeInt(0);
             }
@@ -3824,18 +4171,20 @@
                     mNetworkByteActivityCounters[i].writeToParcel(out);
                     mNetworkPacketActivityCounters[i].writeToParcel(out);
                 }
+                mMobileRadioActiveTime.writeToParcel(out);
+                mMobileRadioActiveCount.writeToParcel(out);
             } else {
                 out.writeInt(0);
             }
         }
 
-        void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
+        void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
             int numWakelocks = in.readInt();
             mWakelockStats.clear();
             for (int j = 0; j < numWakelocks; j++) {
                 String wakelockName = in.readString();
                 Uid.Wakelock wakelock = new Wakelock();
-                wakelock.readFromParcelLocked(unpluggables, in);
+                wakelock.readFromParcelLocked(timeBase, screenOffTimeBase, in);
                 // We will just drop some random set of wakelocks if
                 // the previous run of the system was an older version
                 // that didn't impose a limit.
@@ -3847,7 +4196,7 @@
             for (int k = 0; k < numSensors; k++) {
                 int sensorNumber = in.readInt();
                 Uid.Sensor sensor = new Sensor(sensorNumber);
-                sensor.readFromParcelLocked(mUnpluggables, in);
+                sensor.readFromParcelLocked(mOnBatteryTimeBase, in);
                 mSensorStats.put(sensorNumber, sensor);
             }
 
@@ -3872,21 +4221,21 @@
             mWifiRunning = false;
             if (in.readInt() != 0) {
                 mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING,
-                        mWifiRunningTimers, mUnpluggables, in);
+                        mWifiRunningTimers, mOnBatteryTimeBase, in);
             } else {
                 mWifiRunningTimer = null;
             }
             mFullWifiLockOut = false;
             if (in.readInt() != 0) {
                 mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
-                        mFullWifiLockTimers, mUnpluggables, in);
+                        mFullWifiLockTimers, mOnBatteryTimeBase, in);
             } else {
                 mFullWifiLockTimer = null;
             }
             mWifiScanStarted = false;
             if (in.readInt() != 0) {
                 mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN,
-                        mWifiScanTimers, mUnpluggables, in);
+                        mWifiScanTimers, mOnBatteryTimeBase, in);
             } else {
                 mWifiScanTimer = null;
             }
@@ -3901,40 +4250,39 @@
             mWifiMulticastEnabled = false;
             if (in.readInt() != 0) {
                 mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
-                        mWifiMulticastTimers, mUnpluggables, in);
+                        mWifiMulticastTimers, mOnBatteryTimeBase, in);
             } else {
                 mWifiMulticastTimer = null;
             }
             mAudioTurnedOn = false;
             if (in.readInt() != 0) {
                 mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
-                        null, mUnpluggables, in);
+                        null, mOnBatteryTimeBase, in);
             } else {
                 mAudioTurnedOnTimer = null;
             }
             mVideoTurnedOn = false;
             if (in.readInt() != 0) {
                 mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
-                        null, mUnpluggables, in);
+                        null, mOnBatteryTimeBase, in);
             } else {
                 mVideoTurnedOnTimer = null;
             }
             if (in.readInt() != 0) {
                 mForegroundActivityTimer = new StopwatchTimer(
-                        Uid.this, FOREGROUND_ACTIVITY, null, mUnpluggables, in);
+                        Uid.this, FOREGROUND_ACTIVITY, null, mOnBatteryTimeBase, in);
             } else {
                 mForegroundActivityTimer = null;
             }
             if (in.readInt() != 0) {
-                mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON,
-                        mUnpluggables, BatteryStatsImpl.this.mOnBatteryInternal, in);
+                mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON, mOnBatteryTimeBase, in);
             } else {
                 mVibratorOnTimer = null;
             }
             if (in.readInt() != 0) {
                 mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
                 for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
-                    mUserActivityCounters[i] = new Counter(mUnpluggables, in);
+                    mUserActivityCounters[i] = new Counter(mOnBatteryTimeBase, in);
                 }
             } else {
                 mUserActivityCounters = null;
@@ -3944,9 +4292,13 @@
                 mNetworkPacketActivityCounters
                         = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
                 for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
-                    mNetworkByteActivityCounters[i] = new LongSamplingCounter(mUnpluggables, in);
-                    mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mUnpluggables, in);
+                    mNetworkByteActivityCounters[i]
+                            = new LongSamplingCounter(mOnBatteryTimeBase, in);
+                    mNetworkPacketActivityCounters[i]
+                            = new LongSamplingCounter(mOnBatteryTimeBase, in);
                 }
+                mMobileRadioActiveTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
+                mMobileRadioActiveCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
             } else {
                 mNetworkByteActivityCounters = null;
                 mNetworkPacketActivityCounters = null;
@@ -3980,24 +4332,24 @@
              * return a new Timer, or null.
              */
             private StopwatchTimer readTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
-                    ArrayList<Unpluggable> unpluggables, Parcel in) {
+                    TimeBase timeBase, Parcel in) {
                 if (in.readInt() == 0) {
                     return null;
                 }
 
-                return new StopwatchTimer(Uid.this, type, pool, unpluggables, in);
+                return new StopwatchTimer(Uid.this, type, pool, timeBase, in);
             }
 
             boolean reset() {
                 boolean wlactive = false;
                 if (mTimerFull != null) {
-                    wlactive |= !mTimerFull.reset(BatteryStatsImpl.this, false);
+                    wlactive |= !mTimerFull.reset(false);
                 }
                 if (mTimerPartial != null) {
-                    wlactive |= !mTimerPartial.reset(BatteryStatsImpl.this, false);
+                    wlactive |= !mTimerPartial.reset(false);
                 }
                 if (mTimerWindow != null) {
-                    wlactive |= !mTimerWindow.reset(BatteryStatsImpl.this, false);
+                    wlactive |= !mTimerWindow.reset(false);
                 }
                 if (!wlactive) {
                     if (mTimerFull != null) {
@@ -4016,19 +4368,19 @@
                 return !wlactive;
             }
 
-            void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
+            void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
                 mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL,
-                        mPartialTimers, unpluggables, in);
+                        mPartialTimers, screenOffTimeBase, in);
                 mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL,
-                        mFullTimers, unpluggables, in);
+                        mFullTimers, timeBase, in);
                 mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW,
-                        mWindowTimers, unpluggables, in);
+                        mWindowTimers, timeBase, in);
             }
 
-            void writeToParcelLocked(Parcel out, long batteryRealtime) {
-                Timer.writeTimerToParcel(out, mTimerPartial, batteryRealtime);
-                Timer.writeTimerToParcel(out, mTimerFull, batteryRealtime);
-                Timer.writeTimerToParcel(out, mTimerWindow, batteryRealtime);
+            void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
+                Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs);
+                Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs);
+                Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs);
             }
 
             @Override
@@ -4050,8 +4402,7 @@
                 mHandle = handle;
             }
 
-            private StopwatchTimer readTimerFromParcel(ArrayList<Unpluggable> unpluggables,
-                    Parcel in) {
+            private StopwatchTimer readTimerFromParcel(TimeBase timeBase, Parcel in) {
                 if (in.readInt() == 0) {
                     return null;
                 }
@@ -4061,23 +4412,23 @@
                     pool = new ArrayList<StopwatchTimer>();
                     mSensorTimers.put(mHandle, pool);
                 }
-                return new StopwatchTimer(Uid.this, 0, pool, unpluggables, in);
+                return new StopwatchTimer(Uid.this, 0, pool, timeBase, in);
             }
 
             boolean reset() {
-                if (mTimer.reset(BatteryStatsImpl.this, true)) {
+                if (mTimer.reset(true)) {
                     mTimer = null;
                     return true;
                 }
                 return false;
             }
 
-            void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
-                mTimer = readTimerFromParcel(unpluggables, in);
+            void readFromParcelLocked(TimeBase timeBase, Parcel in) {
+                mTimer = readTimerFromParcel(timeBase, in);
             }
 
-            void writeToParcelLocked(Parcel out, long batteryRealtime) {
-                Timer.writeTimerToParcel(out, mTimer, batteryRealtime);
+            void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) {
+                Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs);
             }
 
             @Override
@@ -4094,7 +4445,7 @@
         /**
          * The statistics associated with a particular process.
          */
-        public final class Proc extends BatteryStats.Uid.Proc implements Unpluggable {
+        public final class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs {
             /**
              * Remains true until removed from the stats.
              */
@@ -4185,27 +4536,27 @@
             ArrayList<ExcessivePower> mExcessivePower;
 
             Proc() {
-                mUnpluggables.add(this);
+                mOnBatteryTimeBase.add(this);
                 mSpeedBins = new SamplingCounter[getCpuSpeedSteps()];
             }
 
-            public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+            public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
                 mUnpluggedUserTime = mUserTime;
                 mUnpluggedSystemTime = mSystemTime;
                 mUnpluggedForegroundTime = mForegroundTime;
                 mUnpluggedStarts = mStarts;
             }
 
-            public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+            public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
             }
 
             void detach() {
                 mActive = false;
-                mUnpluggables.remove(this);
+                mOnBatteryTimeBase.remove(this);
                 for (int i = 0; i < mSpeedBins.length; i++) {
                     SamplingCounter c = mSpeedBins[i];
                     if (c != null) {
-                        mUnpluggables.remove(c);
+                        mOnBatteryTimeBase.remove(c);
                         mSpeedBins[i] = null;
                     }
                 }
@@ -4334,7 +4685,7 @@
                 mSpeedBins = new SamplingCounter[bins >= steps ? bins : steps];
                 for (int i = 0; i < bins; i++) {
                     if (in.readInt() != 0) {
-                        mSpeedBins[i] = new SamplingCounter(mUnpluggables, in);
+                        mSpeedBins[i] = new SamplingCounter(mOnBatteryTimeBase, in);
                     }
                 }
 
@@ -4434,7 +4785,7 @@
                     if (amt != 0) {
                         SamplingCounter c = mSpeedBins[i];
                         if (c == null) {
-                            mSpeedBins[i] = c = new SamplingCounter(mUnpluggables);
+                            mSpeedBins[i] = c = new SamplingCounter(mOnBatteryTimeBase);
                         }
                         c.addCountAtomic(values[i]);
                     }
@@ -4455,7 +4806,7 @@
         /**
          * The statistics associated with a particular package.
          */
-        public final class Pkg extends BatteryStats.Uid.Pkg implements Unpluggable {
+        public final class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs {
             /**
              * Number of times this package has done something that could wake up the
              * device from sleep.
@@ -4486,18 +4837,18 @@
             final HashMap<String, Serv> mServiceStats = new HashMap<String, Serv>();
 
             Pkg() {
-                mUnpluggables.add(this);
+                mOnBatteryScreenOffTimeBase.add(this);
             }
 
-            public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+            public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
                 mUnpluggedWakeups = mWakeups;
             }
 
-            public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+            public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
             }
 
             void detach() {
-                mUnpluggables.remove(this);
+                mOnBatteryScreenOffTimeBase.remove(this);
             }
 
             void readFromParcelLocked(Parcel in) {
@@ -4556,7 +4907,7 @@
             /**
              * The statistics associated with a particular service.
              */
-            public final class Serv extends BatteryStats.Uid.Pkg.Serv implements Unpluggable {
+            public final class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs {
                 /**
                  * Total time (ms in battery uptime) the service has been left started.
                  */
@@ -4648,20 +4999,22 @@
                 int mUnpluggedLaunches;
 
                 Serv() {
-                    mUnpluggables.add(this);
+                    mOnBatteryTimeBase.add(this);
                 }
 
-                public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
-                    mUnpluggedStartTime = getStartTimeToNowLocked(batteryUptime);
+                public void onTimeStarted(long elapsedRealtime, long baseUptime,
+                        long baseRealtime) {
+                    mUnpluggedStartTime = getStartTimeToNowLocked(baseUptime);
                     mUnpluggedStarts = mStarts;
                     mUnpluggedLaunches = mLaunches;
                 }
 
-                public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) {
+                public void onTimeStopped(long elapsedRealtime, long baseUptime,
+                        long baseRealtime) {
                 }
 
                 void detach() {
-                    mUnpluggables.remove(this);
+                    mOnBatteryTimeBase.remove(this);
                 }
 
                 void readFromParcelLocked(Parcel in) {
@@ -4896,7 +5249,7 @@
                     t = wl.mTimerPartial;
                     if (t == null) {
                         t = new StopwatchTimer(Uid.this, WAKE_TYPE_PARTIAL,
-                                mPartialTimers, mUnpluggables);
+                                mPartialTimers, mOnBatteryScreenOffTimeBase);
                         wl.mTimerPartial = t;
                     }
                     return t;
@@ -4904,7 +5257,7 @@
                     t = wl.mTimerFull;
                     if (t == null) {
                         t = new StopwatchTimer(Uid.this, WAKE_TYPE_FULL,
-                                mFullTimers, mUnpluggables);
+                                mFullTimers, mOnBatteryTimeBase);
                         wl.mTimerFull = t;
                     }
                     return t;
@@ -4912,7 +5265,7 @@
                     t = wl.mTimerWindow;
                     if (t == null) {
                         t = new StopwatchTimer(Uid.this, WAKE_TYPE_WINDOW,
-                                mWindowTimers, mUnpluggables);
+                                mWindowTimers, mOnBatteryTimeBase);
                         wl.mTimerWindow = t;
                     }
                     return t;
@@ -4939,33 +5292,33 @@
                 timers = new ArrayList<StopwatchTimer>();
                 mSensorTimers.put(sensor, timers);
             }
-            t = new StopwatchTimer(Uid.this, BatteryStats.SENSOR, timers, mUnpluggables);
+            t = new StopwatchTimer(Uid.this, BatteryStats.SENSOR, timers, mOnBatteryTimeBase);
             se.mTimer = t;
             return t;
         }
 
-        public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtime) {
+        public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
             StopwatchTimer t = getWakeTimerLocked(name, type);
             if (t != null) {
-                t.startRunningLocked(BatteryStatsImpl.this, elapsedRealtime);
+                t.startRunningLocked(elapsedRealtimeMs);
             }
             if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
                 Pid p = getPidStatsLocked(pid);
                 if (p.mWakeStart == 0) {
-                    p.mWakeStart = elapsedRealtime;
+                    p.mWakeStart = elapsedRealtimeMs;
                 }
             }
         }
 
-        public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtime) {
+        public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
             StopwatchTimer t = getWakeTimerLocked(name, type);
             if (t != null) {
-                t.stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime);
+                t.stopRunningLocked(elapsedRealtimeMs);
             }
             if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
                 Pid p = mPids.get(pid);
                 if (p != null && p.mWakeStart != 0) {
-                    p.mWakeSum += elapsedRealtime - p.mWakeStart;
+                    p.mWakeSum += elapsedRealtimeMs - p.mWakeStart;
                     p.mWakeStart = 0;
                 }
             }
@@ -4985,32 +5338,32 @@
             }
         }
 
-        public void noteStartSensor(int sensor, long elapsedRealtime) {
+        public void noteStartSensor(int sensor, long elapsedRealtimeMs) {
             StopwatchTimer t = getSensorTimerLocked(sensor, true);
             if (t != null) {
-                t.startRunningLocked(BatteryStatsImpl.this, elapsedRealtime);
+                t.startRunningLocked(elapsedRealtimeMs);
             }
         }
 
-        public void noteStopSensor(int sensor, long elapsedRealtime) {
+        public void noteStopSensor(int sensor, long elapsedRealtimeMs) {
             // Don't create a timer if one doesn't already exist
             StopwatchTimer t = getSensorTimerLocked(sensor, false);
             if (t != null) {
-                t.stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime);
+                t.stopRunningLocked(elapsedRealtimeMs);
             }
         }
 
-        public void noteStartGps(long elapsedRealtime) {
+        public void noteStartGps(long elapsedRealtimeMs) {
             StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true);
             if (t != null) {
-                t.startRunningLocked(BatteryStatsImpl.this, elapsedRealtime);
+                t.startRunningLocked(elapsedRealtimeMs);
             }
         }
 
-        public void noteStopGps(long elapsedRealtime) {
+        public void noteStopGps(long elapsedRealtimeMs) {
             StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false);
             if (t != null) {
-                t.stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime);
+                t.stopRunningLocked(elapsedRealtimeMs);
             }
         }
 
@@ -5023,43 +5376,46 @@
         mFile = new JournaledFile(new File(filename), new File(filename + ".tmp"));
         mHandler = new MyHandler(handler.getLooper());
         mStartCount++;
-        mScreenOnTimer = new StopwatchTimer(null, -1, null, mUnpluggables);
+        mScreenOnTimer = new StopwatchTimer(null, -1, null, mOnBatteryTimeBase);
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
-            mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mUnpluggables);
+            mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mOnBatteryTimeBase);
         }
-        mInputEventCounter = new Counter(mUnpluggables);
-        mPhoneOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables);
+        mInputEventCounter = new Counter(mOnBatteryTimeBase);
+        mPhoneOnTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase);
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
-            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i, null, mUnpluggables);
+            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i, null,
+                    mOnBatteryTimeBase);
         }
-        mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mUnpluggables);
+        mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mOnBatteryTimeBase);
         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
-            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i, null, mUnpluggables);
+            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i, null,
+                    mOnBatteryTimeBase);
         }
         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
-            mNetworkByteActivityCounters[i] = new LongSamplingCounter(mUnpluggables);
-            mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mUnpluggables);
+            mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
+            mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase);
         }
-        mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mUnpluggables);
-        mWifiOnTimer = new StopwatchTimer(null, -3, null, mUnpluggables);
-        mGlobalWifiRunningTimer = new StopwatchTimer(null, -4, null, mUnpluggables);
+        mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase);
+        mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase);
+        mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase);
+        mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase);
+        mWifiOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase);
+        mGlobalWifiRunningTimer = new StopwatchTimer(null, -4, null, mOnBatteryTimeBase);
         for (int i=0; i<NUM_WIFI_STATES; i++) {
-            mWifiStateTimer[i] = new StopwatchTimer(null, -600-i, null, mUnpluggables);
+            mWifiStateTimer[i] = new StopwatchTimer(null, -600-i, null, mOnBatteryTimeBase);
         }
-        mBluetoothOnTimer = new StopwatchTimer(null, -5, null, mUnpluggables);
+        mBluetoothOnTimer = new StopwatchTimer(null, -5, null, mOnBatteryTimeBase);
         for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
-            mBluetoothStateTimer[i] = new StopwatchTimer(null, -500-i, null, mUnpluggables);
+            mBluetoothStateTimer[i] = new StopwatchTimer(null, -500-i, null, mOnBatteryTimeBase);
         }
-        mAudioOnTimer = new StopwatchTimer(null, -6, null, mUnpluggables);
-        mVideoOnTimer = new StopwatchTimer(null, -7, null, mUnpluggables);
+        mAudioOnTimer = new StopwatchTimer(null, -6, null, mOnBatteryTimeBase);
+        mVideoOnTimer = new StopwatchTimer(null, -7, null, mOnBatteryTimeBase);
         mOnBattery = mOnBatteryInternal = false;
-        initTimes();
-        mTrackBatteryPastUptime = 0;
-        mTrackBatteryPastRealtime = 0;
-        mUptimeStart = mTrackBatteryUptimeStart = SystemClock.uptimeMillis() * 1000;
-        mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000;
-        mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart);
-        mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart);
+        long uptime = SystemClock.uptimeMillis() * 1000;
+        long realtime = SystemClock.elapsedRealtime() * 1000;
+        initTimes(uptime, realtime);
+        mUptimeStart = uptime;
+        mRealtimeStart = realtime;
         mDischargeStartLevel = 0;
         mDischargeUnplugLevel = 0;
         mDischargeCurrentLevel = 0;
@@ -5235,14 +5591,12 @@
         return mScreenOn;
     }
 
-    void initTimes() {
+    void initTimes(long uptime, long realtime) {
         mStartClockTime = System.currentTimeMillis();
-        mBatteryRealtime = mTrackBatteryPastUptime = 0;
-        mBatteryUptime = mTrackBatteryPastRealtime = 0;
-        mUptimeStart = mTrackBatteryUptimeStart = SystemClock.uptimeMillis() * 1000;
-        mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000;
-        mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart);
-        mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart);
+        mOnBatteryTimeBase.init(uptime, realtime);
+        mOnBatteryScreenOffTimeBase.init(uptime, realtime);
+        mUptimeStart = uptime;
+        mRealtimeStart = realtime;
     }
 
     void initDischarge() {
@@ -5263,14 +5617,9 @@
         pullPendingStateUpdatesLocked();
         addHistoryRecordLocked(mSecRealtime);
         mDischargeCurrentLevel = mDischargeUnplugLevel = mHistoryCur.batteryLevel;
-        if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) != 0) {
-            mTrackBatteryPastUptime = 0;
-            mTrackBatteryPastRealtime = 0;
-        } else {
-            mTrackBatteryUptimeStart = uptime;
-            mTrackBatteryRealtimeStart = realtime;
-            mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime);
-            mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime);
+        mOnBatteryTimeBase.reset(uptime, realtime);
+        mOnBatteryScreenOffTimeBase.reset(uptime, realtime);
+        if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
             if (mScreenOn) {
                 mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
                 mDischargeScreenOffUnplugLevel = 0;
@@ -5286,35 +5635,38 @@
 
     private void resetAllStatsLocked() {
         mStartCount = 0;
-        initTimes();
-        mScreenOnTimer.reset(this, false);
+        initTimes(SystemClock.uptimeMillis() * 1000, SystemClock.elapsedRealtime() * 1000);
+        mScreenOnTimer.reset(false);
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
-            mScreenBrightnessTimer[i].reset(this, false);
+            mScreenBrightnessTimer[i].reset(false);
         }
         mInputEventCounter.reset(false);
-        mPhoneOnTimer.reset(this, false);
-        mAudioOnTimer.reset(this, false);
-        mVideoOnTimer.reset(this, false);
+        mPhoneOnTimer.reset(false);
+        mAudioOnTimer.reset(false);
+        mVideoOnTimer.reset(false);
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
-            mPhoneSignalStrengthsTimer[i].reset(this, false);
+            mPhoneSignalStrengthsTimer[i].reset(false);
         }
-        mPhoneSignalScanningTimer.reset(this, false);
+        mPhoneSignalScanningTimer.reset(false);
         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
-            mPhoneDataConnectionsTimer[i].reset(this, false);
+            mPhoneDataConnectionsTimer[i].reset(false);
         }
         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
             mNetworkByteActivityCounters[i].reset(false);
             mNetworkPacketActivityCounters[i].reset(false);
         }
-        mMobileRadioActiveTimer.reset(this, false);
-        mWifiOnTimer.reset(this, false);
-        mGlobalWifiRunningTimer.reset(this, false);
+        mMobileRadioActiveTimer.reset(false);
+        mMobileRadioActivePerAppTimer.reset(false);
+        mMobileRadioActiveUnknownTime.reset(false);
+        mMobileRadioActiveUnknownCount.reset(false);
+        mWifiOnTimer.reset(false);
+        mGlobalWifiRunningTimer.reset(false);
         for (int i=0; i<NUM_WIFI_STATES; i++) {
-            mWifiStateTimer[i].reset(this, false);
+            mWifiStateTimer[i].reset(false);
         }
-        mBluetoothOnTimer.reset(this, false);
+        mBluetoothOnTimer.reset(false);
         for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
-            mBluetoothStateTimer[i].reset(this, false);
+            mBluetoothStateTimer[i].reset(false);
         }
 
         for (int i=0; i<mUidStats.size(); i++) {
@@ -5326,7 +5678,7 @@
 
         if (mKernelWakelockStats.size() > 0) {
             for (SamplingTimer timer : mKernelWakelockStats.values()) {
-                mUnpluggables.remove(timer);
+                mOnBatteryScreenOffTimeBase.remove(timer);
             }
             mKernelWakelockStats.clear();
         }
@@ -5376,15 +5728,12 @@
         }
     }
     
-    void setOnBattery(boolean onBattery, int oldStatus, int level) {
-        synchronized(this) {
-            setOnBatteryLocked(onBattery, oldStatus, level);
-        }
-    }
-
     public void pullPendingStateUpdatesLocked() {
         updateKernelWakelocksLocked();
-        updateNetworkActivityLocked();
+        updateNetworkActivityLocked(NET_UPDATE_ALL, SystemClock.elapsedRealtime());
+        if (mOnBatteryInternal) {
+            updateDischargeScreenLevelsLocked(mScreenOn, mScreenOn);
+        }
     }
 
     void setOnBatteryLocked(boolean onBattery, int oldStatus, int level) {
@@ -5417,10 +5766,6 @@
             if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(mSecRealtime);
-            mTrackBatteryUptimeStart = uptime;
-            mTrackBatteryRealtimeStart = realtime;
-            mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime);
-            mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime);
             mDischargeCurrentLevel = mDischargeUnplugLevel = level;
             if (mScreenOn) {
                 mDischargeScreenOnUnplugLevel = level;
@@ -5431,7 +5776,7 @@
             }
             mDischargeAmountScreenOn = 0;
             mDischargeAmountScreenOff = 0;
-            doUnplugLocked(realtime, mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime);
+            updateTimeBasesLocked(true, !mScreenOn, uptime, realtime);
             if (reset) {
                 initActiveHistoryEventsLocked(mSecRealtime);
             }
@@ -5442,15 +5787,13 @@
             if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(mSecRealtime);
-            mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart;
-            mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart;
             mDischargeCurrentLevel = level;
             if (level < mDischargeUnplugLevel) {
                 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
                 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
             }
             updateDischargeScreenLevelsLocked(mScreenOn, mScreenOn);
-            doPlugLocked(realtime, getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime));
+            updateTimeBasesLocked(false, !mScreenOn, uptime, realtime);
         }
         if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
             if (mFile != null) {
@@ -5549,8 +5892,8 @@
 
             SamplingTimer kwlt = mKernelWakelockStats.get(name);
             if (kwlt == null) {
-                kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal,
-                        true /* track reported values */);
+                kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase,
+                        true /* track reported val */);
                 mKernelWakelockStats.put(name, kwlt);
             }
             kwlt.updateCurrentReportedCount(kws.mCount);
@@ -5569,58 +5912,124 @@
         }
     }
 
-    private void updateNetworkActivityLocked() {
+    static final int NET_UPDATE_MOBILE = 1<<0;
+    static final int NET_UPDATE_WIFI = 1<<1;
+    static final int NET_UPDATE_ALL = 0xffff;
+
+    private void updateNetworkActivityLocked(int which, long elapsedRealtimeMs) {
         if (!SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) return;
 
-        final NetworkStats snapshot;
-        try {
-            snapshot = mNetworkStatsFactory.readNetworkStatsDetail();
-        } catch (IOException e) {
-            Log.wtf(TAG, "Failed to read network stats", e);
-            return;
+        if ((which&NET_UPDATE_MOBILE) != 0 && mMobileIfaces.length > 0) {
+            final NetworkStats snapshot;
+            final NetworkStats last = mCurMobileSnapshot;
+            try {
+                snapshot = mNetworkStatsFactory.readNetworkStatsDetail(UID_ALL,
+                        mMobileIfaces, NetworkStats.TAG_NONE, mLastMobileSnapshot);
+            } catch (IOException e) {
+                Log.wtf(TAG, "Failed to read mobile network stats", e);
+                return;
+            }
+
+            mCurMobileSnapshot = snapshot;
+            mLastMobileSnapshot = last;
+
+            if (mOnBatteryInternal) {
+                final NetworkStats delta = NetworkStats.subtract(snapshot, last,
+                        null, null, mTmpNetworkStats);
+                mTmpNetworkStats = delta;
+
+                long radioTime = mMobileRadioActivePerAppTimer.checkpointRunningLocked(
+                        elapsedRealtimeMs);
+                long totalPackets = delta.getTotalPackets();
+
+                final int size = delta.size();
+                for (int i = 0; i < size; i++) {
+                    final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
+
+                    if (entry.rxBytes == 0 || entry.txBytes == 0) continue;
+
+                    final Uid u = getUidStatsLocked(entry.uid);
+                    u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
+                            entry.rxPackets);
+                    u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
+                            entry.txPackets);
+
+                    if (radioTime > 0) {
+                        // Distribute total radio active time in to this app.
+                        long appPackets = entry.rxPackets + entry.txPackets;
+                        long appRadioTime = (radioTime*appPackets)/totalPackets;
+                        u.noteMobileRadioActiveTimeLocked(appRadioTime);
+                        // Remove this app from the totals, so that we don't lose any time
+                        // due to rounding.
+                        radioTime -= appRadioTime;
+                        totalPackets -= appPackets;
+                    }
+
+                    mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
+                            entry.rxBytes);
+                    mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
+                            entry.txBytes);
+                    mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
+                            entry.rxPackets);
+                    mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
+                            entry.txPackets);
+                }
+
+                if (radioTime > 0) {
+                    // Whoops, there is some radio time we can't blame on an app!
+                    mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
+                    mMobileRadioActiveUnknownCount.addCountLocked(1);
+                }
+            }
         }
 
-        if (mLastSnapshot == null) {
-            mLastSnapshot = snapshot;
-            return;
-        }
+        if ((which&NET_UPDATE_WIFI) != 0 && mWifiIfaces.length > 0) {
+            final NetworkStats snapshot;
+            final NetworkStats last = mCurWifiSnapshot;
+            try {
+                snapshot = mNetworkStatsFactory.readNetworkStatsDetail(UID_ALL,
+                        mWifiIfaces, NetworkStats.TAG_NONE, mLastWifiSnapshot);
+            } catch (IOException e) {
+                Log.wtf(TAG, "Failed to read wifi network stats", e);
+                return;
+            }
 
-        final NetworkStats delta = snapshot.subtract(mLastSnapshot);
-        mLastSnapshot = snapshot;
+            mCurWifiSnapshot = snapshot;
+            mLastWifiSnapshot = last;
 
-        NetworkStats.Entry entry = null;
-        final int size = delta.size();
-        for (int i = 0; i < size; i++) {
-            entry = delta.getValues(i, entry);
+            if (mOnBatteryInternal) {
+                final NetworkStats delta = NetworkStats.subtract(snapshot, last,
+                        null, null, mTmpNetworkStats);
+                mTmpNetworkStats = delta;
 
-            if (entry.rxBytes == 0 || entry.txBytes == 0) continue;
-            if (entry.tag != NetworkStats.TAG_NONE) continue;
+                final int size = delta.size();
+                for (int i = 0; i < size; i++) {
+                    final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
 
-            final Uid u = getUidStatsLocked(entry.uid);
+                    if (DEBUG) {
+                        final NetworkStats.Entry cur = snapshot.getValues(i, null);
+                        Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
+                                + " tx=" + entry.txBytes + ", cur rx=" + cur.rxBytes
+                                + " tx=" + cur.txBytes);
+                    }
 
-            if (mMobileIfaces.contains(entry.iface)) {
-                u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
-                        entry.rxPackets);
-                u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
-                        entry.txPackets);
+                    if (entry.rxBytes == 0 || entry.txBytes == 0) continue;
 
-                mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(entry.rxBytes);
-                mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(entry.txBytes);
-                mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
-                        entry.rxPackets);
-                mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
-                        entry.txPackets);
+                    final Uid u = getUidStatsLocked(entry.uid);
+                    u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
+                            entry.rxPackets);
+                    u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
+                            entry.txPackets);
 
-            } else if (mWifiIfaces.contains(entry.iface)) {
-                u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes, entry.rxPackets);
-                u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes, entry.txPackets);
-
-                mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(entry.rxBytes);
-                mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(entry.txBytes);
-                mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
-                        entry.rxPackets);
-                mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
-                        entry.txPackets);
+                    mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
+                            entry.rxBytes);
+                    mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
+                            entry.txBytes);
+                    mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
+                            entry.rxPackets);
+                    mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
+                            entry.txPackets);
+                }
             }
         }
     }
@@ -5639,7 +6048,7 @@
             case STATS_SINCE_CHARGED: return mUptime + (curTime-mUptimeStart);
             case STATS_LAST: return mLastUptime;
             case STATS_CURRENT: return (curTime-mUptimeStart);
-            case STATS_SINCE_UNPLUGGED: return (curTime-mTrackBatteryUptimeStart);
+            case STATS_SINCE_UNPLUGGED: return (curTime- mOnBatteryTimeBase.getUptimeStart());
         }
         return 0;
     }
@@ -5650,69 +6059,43 @@
             case STATS_SINCE_CHARGED: return mRealtime + (curTime-mRealtimeStart);
             case STATS_LAST: return mLastRealtime;
             case STATS_CURRENT: return (curTime-mRealtimeStart);
-            case STATS_SINCE_UNPLUGGED: return (curTime-mTrackBatteryRealtimeStart);
+            case STATS_SINCE_UNPLUGGED: return (curTime- mOnBatteryTimeBase.getRealtimeStart());
         }
         return 0;
     }
 
     @Override
     public long computeBatteryUptime(long curTime, int which) {
-        switch (which) {
-            case STATS_SINCE_CHARGED:
-                return mBatteryUptime + getBatteryUptime(curTime);
-            case STATS_LAST:
-                return mBatteryLastUptime;
-            case STATS_CURRENT:
-                return getBatteryUptime(curTime);
-            case STATS_SINCE_UNPLUGGED:
-                return getBatteryUptimeLocked(curTime) - mUnpluggedBatteryUptime;
-        }
-        return 0;
+        return mOnBatteryTimeBase.computeUptime(curTime, which);
     }
 
     @Override
     public long computeBatteryRealtime(long curTime, int which) {
-        switch (which) {
-            case STATS_SINCE_CHARGED:
-                return mBatteryRealtime + getBatteryRealtimeLocked(curTime);
-            case STATS_LAST:
-                return mBatteryLastRealtime;
-            case STATS_CURRENT:
-                return getBatteryRealtimeLocked(curTime);
-            case STATS_SINCE_UNPLUGGED:
-                return getBatteryRealtimeLocked(curTime) - mUnpluggedBatteryRealtime;
-        }
-        return 0;
+        return mOnBatteryTimeBase.computeRealtime(curTime, which);
     }
 
-    long getBatteryUptimeLocked(long curTime) {
-        long time = mTrackBatteryPastUptime;
-        if (mOnBatteryInternal) {
-            time += curTime - mTrackBatteryUptimeStart;
-        }
-        return time;
+    @Override
+    public long computeBatteryScreenOffUptime(long curTime, int which) {
+        return mOnBatteryScreenOffTimeBase.computeUptime(curTime, which);
+    }
+
+    @Override
+    public long computeBatteryScreenOffRealtime(long curTime, int which) {
+        return mOnBatteryScreenOffTimeBase.computeRealtime(curTime, which);
     }
 
     long getBatteryUptimeLocked() {
-        return getBatteryUptime(SystemClock.uptimeMillis() * 1000);
+        return mOnBatteryTimeBase.getUptime(SystemClock.uptimeMillis() * 1000);
     }
 
     @Override
     public long getBatteryUptime(long curTime) {
-        return getBatteryUptimeLocked(curTime);
-    }
-
-    long getBatteryRealtimeLocked(long curTime) {
-        long time = mTrackBatteryPastRealtime;
-        if (mOnBatteryInternal) {
-            time += curTime - mTrackBatteryRealtimeStart;
-        }
-        return time;
+        return mOnBatteryTimeBase.getUptime(curTime);
     }
 
     @Override
     public long getBatteryRealtime(long curTime) {
-        return getBatteryRealtimeLocked(curTime);
+        return mOnBatteryTimeBase.getRealtime(curTime);
     }
 
     @Override
@@ -5890,7 +6273,7 @@
                                     time = (time*uidRunningTime)/totalRunningTime;
                                     SamplingCounter uidSc = uidProc.mSpeedBins[sb];
                                     if (uidSc == null) {
-                                        uidSc = new SamplingCounter(mUnpluggables);
+                                        uidSc = new SamplingCounter(mOnBatteryTimeBase);
                                         uidProc.mSpeedBins[sb] = uidSc;
                                     }
                                     uidSc.mCount.addAndGet((int)time);
@@ -6174,11 +6557,11 @@
         readHistory(in, true);
 
         mStartCount = in.readInt();
-        mBatteryUptime = in.readLong();
-        mBatteryRealtime = in.readLong();
         mUptime = in.readLong();
         mRealtime = in.readLong();
         mStartClockTime = in.readLong();
+        mOnBatteryTimeBase.readSummaryFromParcel(in);
+        mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
         mDischargeUnplugLevel = in.readInt();
         mDischargeCurrentLevel = in.readInt();
         mLowDischargeAmountSinceCharge = in.readInt();
@@ -6209,6 +6592,9 @@
         }
         mMobileRadioActive = false;
         mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
+        mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
+        mMobileRadioActiveUnknownTime.readSummaryFromParcelLocked(in);
+        mMobileRadioActiveUnknownCount.readSummaryFromParcelLocked(in);
         mWifiOn = false;
         mWifiOnTimer.readSummaryFromParcelLocked(in);
         mGlobalWifiRunning = false;
@@ -6304,6 +6690,8 @@
                     u.mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
                     u.mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
                 }
+                u.mMobileRadioActiveTime.readSummaryFromParcelLocked(in);
+                u.mMobileRadioActiveCount.readSummaryFromParcelLocked(in);
             }
 
             int NW = in.readInt();
@@ -6357,7 +6745,7 @@
                 p.mSpeedBins = new SamplingCounter[NSB];
                 for (int i=0; i<NSB; i++) {
                     if (in.readInt() != 0) {
-                        p.mSpeedBins[i] = new SamplingCounter(mUnpluggables);
+                        p.mSpeedBins[i] = new SamplingCounter(mOnBatteryTimeBase);
                         p.mSpeedBins[i].readSummaryFromParcelLocked(in);
                     }
                 }
@@ -6402,52 +6790,53 @@
 
         final long NOW_SYS = SystemClock.uptimeMillis() * 1000;
         final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000;
-        final long NOW = getBatteryUptimeLocked(NOW_SYS);
-        final long NOWREAL = getBatteryRealtimeLocked(NOWREAL_SYS);
 
         out.writeInt(VERSION);
 
         writeHistory(out, true);
 
         out.writeInt(mStartCount);
-        out.writeLong(computeBatteryUptime(NOW_SYS, STATS_SINCE_CHARGED));
-        out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
         out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED));
         out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
         out.writeLong(mStartClockTime);
+        mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
+        mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
         out.writeInt(mDischargeUnplugLevel);
         out.writeInt(mDischargeCurrentLevel);
         out.writeInt(getLowDischargeAmountSinceCharge());
         out.writeInt(getHighDischargeAmountSinceCharge());
         out.writeInt(getDischargeAmountScreenOnSinceCharge());
         out.writeInt(getDischargeAmountScreenOffSinceCharge());
-        
-        mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+
+        mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
-            mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
+            mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         }
         mInputEventCounter.writeSummaryFromParcelLocked(out);
-        mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+        mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
-            mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
+            mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         }
-        mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+        mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
-            mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
+            mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         }
         for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
             mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
             mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
         }
-        mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL);
-        mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
-        mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+        mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+        mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+        mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out);
+        mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out);
+        mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+        mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         for (int i=0; i<NUM_WIFI_STATES; i++) {
-            mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
+            mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         }
-        mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+        mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
-            mBluetoothStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
+            mBluetoothStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         }
 
         out.writeInt(mKernelWakelockStats.size());
@@ -6456,7 +6845,7 @@
             if (kwlt != null) {
                 out.writeInt(1);
                 out.writeString(ent.getKey());
-                ent.getValue().writeSummaryFromParcelLocked(out, NOWREAL);
+                ent.getValue().writeSummaryFromParcelLocked(out, NOWREAL_SYS);
             } else {
                 out.writeInt(0);
             }
@@ -6471,57 +6860,57 @@
 
             if (u.mWifiRunningTimer != null) {
                 out.writeInt(1);
-                u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+                u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
             } else {
                 out.writeInt(0);
             }
             if (u.mFullWifiLockTimer != null) {
                 out.writeInt(1);
-                u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+                u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
             } else {
                 out.writeInt(0);
             }
             if (u.mWifiScanTimer != null) {
                 out.writeInt(1);
-                u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+                u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
             } else {
                 out.writeInt(0);
             }
             for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) {
                 if (u.mWifiBatchedScanTimer[i] != null) {
                     out.writeInt(1);
-                    u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
+                    u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
                 } else {
                     out.writeInt(0);
                 }
             }
             if (u.mWifiMulticastTimer != null) {
                 out.writeInt(1);
-                u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+                u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
             } else {
                 out.writeInt(0);
             }
             if (u.mAudioTurnedOnTimer != null) {
                 out.writeInt(1);
-                u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+                u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
             } else {
                 out.writeInt(0);
             }
             if (u.mVideoTurnedOnTimer != null) {
                 out.writeInt(1);
-                u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+                u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
             } else {
                 out.writeInt(0);
             }
             if (u.mForegroundActivityTimer != null) {
                 out.writeInt(1);
-                u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+                u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
             } else {
                 out.writeInt(0);
             }
             if (u.mVibratorOnTimer != null) {
                 out.writeInt(1);
-                u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+                u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
             } else {
                 out.writeInt(0);
             }
@@ -6543,6 +6932,8 @@
                     u.mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out);
                     u.mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out);
                 }
+                u.mMobileRadioActiveTime.writeSummaryFromParcelLocked(out);
+                u.mMobileRadioActiveCount.writeSummaryFromParcelLocked(out);
             }
 
             int NW = u.mWakelockStats.size();
@@ -6554,19 +6945,19 @@
                     Uid.Wakelock wl = ent.getValue();
                     if (wl.mTimerFull != null) {
                         out.writeInt(1);
-                        wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL);
+                        wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
                     } else {
                         out.writeInt(0);
                     }
                     if (wl.mTimerPartial != null) {
                         out.writeInt(1);
-                        wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL);
+                        wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
                     } else {
                         out.writeInt(0);
                     }
                     if (wl.mTimerWindow != null) {
                         out.writeInt(1);
-                        wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL);
+                        wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
                     } else {
                         out.writeInt(0);
                     }
@@ -6582,7 +6973,7 @@
                     Uid.Sensor se = ent.getValue();
                     if (se.mTimer != null) {
                         out.writeInt(1);
-                        se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+                        se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
                     } else {
                         out.writeInt(0);
                     }
@@ -6629,7 +7020,8 @@
                                 : ps.mServiceStats.entrySet()) {
                             out.writeString(sent.getKey());
                             BatteryStatsImpl.Uid.Pkg.Serv ss = sent.getValue();
-                            long time = ss.getStartTimeToNowLocked(NOW);
+                            long time = ss.getStartTimeToNowLocked(
+                                    mOnBatteryTimeBase.getUptime(NOW_SYS));
                             out.writeLong(time);
                             out.writeInt(ss.mStarts);
                             out.writeInt(ss.mLaunches);
@@ -6653,49 +7045,7 @@
         readHistory(in, false);
 
         mStartCount = in.readInt();
-        mBatteryUptime = in.readLong();
-        mBatteryLastUptime = 0;
-        mBatteryRealtime = in.readLong();
-        mBatteryLastRealtime = 0;
         mStartClockTime = in.readLong();
-        mScreenOn = false;
-        mScreenOnTimer = new StopwatchTimer(null, -1, null, mUnpluggables, in);
-        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
-            mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i,
-                    null, mUnpluggables, in);
-        }
-        mInputEventCounter = new Counter(mUnpluggables, in);
-        mPhoneOn = false;
-        mPhoneOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
-        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
-            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i,
-                    null, mUnpluggables, in);
-        }
-        mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mUnpluggables, in);
-        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
-            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i,
-                    null, mUnpluggables, in);
-        }
-        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
-            mNetworkByteActivityCounters[i] = new LongSamplingCounter(mUnpluggables, in);
-            mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mUnpluggables, in);
-        }
-        mMobileRadioActive = false;
-        mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mUnpluggables, in);
-        mWifiOn = false;
-        mWifiOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
-        mGlobalWifiRunning = false;
-        mGlobalWifiRunningTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
-        for (int i=0; i<NUM_WIFI_STATES; i++) {
-            mWifiStateTimer[i] = new StopwatchTimer(null, -600-i,
-                    null, mUnpluggables, in);
-        }
-        mBluetoothOn = false;
-        mBluetoothOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
-        for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
-            mBluetoothStateTimer[i] = new StopwatchTimer(null, -500-i,
-                    null, mUnpluggables, in);
-        }
         mUptime = in.readLong();
         mUptimeStart = in.readLong();
         mLastUptime = 0;
@@ -6704,12 +7054,51 @@
         mLastRealtime = 0;
         mOnBattery = in.readInt() != 0;
         mOnBatteryInternal = false; // we are no longer really running.
-        mTrackBatteryPastUptime = in.readLong();
-        mTrackBatteryUptimeStart = in.readLong();
-        mTrackBatteryPastRealtime = in.readLong();
-        mTrackBatteryRealtimeStart = in.readLong();
-        mUnpluggedBatteryUptime = in.readLong();
-        mUnpluggedBatteryRealtime = in.readLong();
+        mOnBatteryTimeBase.readFromParcel(in);
+        mOnBatteryScreenOffTimeBase.readFromParcel(in);
+
+        mScreenOn = false;
+        mScreenOnTimer = new StopwatchTimer(null, -1, null, mOnBatteryTimeBase, in);
+        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
+            mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mOnBatteryTimeBase,
+                    in);
+        }
+        mInputEventCounter = new Counter(mOnBatteryTimeBase, in);
+        mPhoneOn = false;
+        mPhoneOnTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in);
+        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
+            mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i,
+                    null, mOnBatteryTimeBase, in);
+        }
+        mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mOnBatteryTimeBase, in);
+        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
+            mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i,
+                    null, mOnBatteryTimeBase, in);
+        }
+        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+            mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
+            mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
+        }
+        mMobileRadioActive = false;
+        mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase, in);
+        mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase,
+                in);
+        mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
+        mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
+        mWifiOn = false;
+        mWifiOnTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in);
+        mGlobalWifiRunning = false;
+        mGlobalWifiRunningTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in);
+        for (int i=0; i<NUM_WIFI_STATES; i++) {
+            mWifiStateTimer[i] = new StopwatchTimer(null, -600-i,
+                    null, mOnBatteryTimeBase, in);
+        }
+        mBluetoothOn = false;
+        mBluetoothOnTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in);
+        for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
+            mBluetoothStateTimer[i] = new StopwatchTimer(null, -500-i,
+                    null, mOnBatteryTimeBase, in);
+        }
         mDischargeUnplugLevel = in.readInt();
         mDischargeCurrentLevel = in.readInt();
         mLowDischargeAmountSinceCharge = in.readInt();
@@ -6729,7 +7118,7 @@
             if (in.readInt() != 0) {
                 String wakelockName = in.readString();
                 in.readInt(); // Extra 0/1 written by Timer.writeTimerToParcel
-                SamplingTimer kwlt = new SamplingTimer(mUnpluggables, mOnBattery, in);
+                SamplingTimer kwlt = new SamplingTimer(mOnBatteryTimeBase, in);
                 mKernelWakelockStats.put(wakelockName, kwlt);
             }
         }
@@ -6750,7 +7139,7 @@
         for (int i = 0; i < numUids; i++) {
             int uid = in.readInt();
             Uid u = new Uid(uid);
-            u.readFromParcelLocked(mUnpluggables, in);
+            u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in);
             mUidStats.append(uid, u);
         }
     }
@@ -6770,55 +7159,53 @@
 
         final long uSecUptime = SystemClock.uptimeMillis() * 1000;
         final long uSecRealtime = SystemClock.elapsedRealtime() * 1000;
-        final long batteryUptime = getBatteryUptimeLocked(uSecUptime);
-        final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime);
+        final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime);
+        final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime);
 
         out.writeInt(MAGIC);
 
         writeHistory(out, false);
 
         out.writeInt(mStartCount);
-        out.writeLong(mBatteryUptime);
-        out.writeLong(mBatteryRealtime);
         out.writeLong(mStartClockTime);
-        mScreenOnTimer.writeToParcel(out, batteryRealtime);
-        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
-            mScreenBrightnessTimer[i].writeToParcel(out, batteryRealtime);
-        }
-        mInputEventCounter.writeToParcel(out);
-        mPhoneOnTimer.writeToParcel(out, batteryRealtime);
-        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
-            mPhoneSignalStrengthsTimer[i].writeToParcel(out, batteryRealtime);
-        }
-        mPhoneSignalScanningTimer.writeToParcel(out, batteryRealtime);
-        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
-            mPhoneDataConnectionsTimer[i].writeToParcel(out, batteryRealtime);
-        }
-        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
-            mNetworkByteActivityCounters[i].writeToParcel(out);
-            mNetworkPacketActivityCounters[i].writeToParcel(out);
-        }
-        mMobileRadioActiveTimer.writeToParcel(out, batteryRealtime);
-        mWifiOnTimer.writeToParcel(out, batteryRealtime);
-        mGlobalWifiRunningTimer.writeToParcel(out, batteryRealtime);
-        for (int i=0; i<NUM_WIFI_STATES; i++) {
-            mWifiStateTimer[i].writeToParcel(out, batteryRealtime);
-        }
-        mBluetoothOnTimer.writeToParcel(out, batteryRealtime);
-        for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
-            mBluetoothStateTimer[i].writeToParcel(out, batteryRealtime);
-        }
         out.writeLong(mUptime);
         out.writeLong(mUptimeStart);
         out.writeLong(mRealtime);
         out.writeLong(mRealtimeStart);
         out.writeInt(mOnBattery ? 1 : 0);
-        out.writeLong(batteryUptime);
-        out.writeLong(mTrackBatteryUptimeStart);
-        out.writeLong(batteryRealtime);
-        out.writeLong(mTrackBatteryRealtimeStart);
-        out.writeLong(mUnpluggedBatteryUptime);
-        out.writeLong(mUnpluggedBatteryRealtime);
+        mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
+        mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime);
+
+        mScreenOnTimer.writeToParcel(out, uSecRealtime);
+        for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
+            mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
+        }
+        mInputEventCounter.writeToParcel(out);
+        mPhoneOnTimer.writeToParcel(out, uSecRealtime);
+        for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
+            mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
+        }
+        mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime);
+        for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
+            mPhoneDataConnectionsTimer[i].writeToParcel(out, uSecRealtime);
+        }
+        for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) {
+            mNetworkByteActivityCounters[i].writeToParcel(out);
+            mNetworkPacketActivityCounters[i].writeToParcel(out);
+        }
+        mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime);
+        mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime);
+        mMobileRadioActiveUnknownTime.writeToParcel(out);
+        mMobileRadioActiveUnknownCount.writeToParcel(out);
+        mWifiOnTimer.writeToParcel(out, uSecRealtime);
+        mGlobalWifiRunningTimer.writeToParcel(out, uSecRealtime);
+        for (int i=0; i<NUM_WIFI_STATES; i++) {
+            mWifiStateTimer[i].writeToParcel(out, uSecRealtime);
+        }
+        mBluetoothOnTimer.writeToParcel(out, uSecRealtime);
+        for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
+            mBluetoothStateTimer[i].writeToParcel(out, uSecRealtime);
+        }
         out.writeInt(mDischargeUnplugLevel);
         out.writeInt(mDischargeCurrentLevel);
         out.writeInt(mLowDischargeAmountSinceCharge);
@@ -6838,7 +7225,7 @@
                 if (kwlt != null) {
                     out.writeInt(1);
                     out.writeString(ent.getKey());
-                    Timer.writeTimerToParcel(out, kwlt, batteryRealtime);
+                    Timer.writeTimerToParcel(out, kwlt, uSecRealtime);
                 } else {
                     out.writeInt(0);
                 }
@@ -6856,7 +7243,7 @@
                 out.writeInt(mUidStats.keyAt(i));
                 Uid uid = mUidStats.valueAt(i);
 
-                uid.writeToParcelLocked(out, batteryRealtime);
+                uid.writeToParcelLocked(out, uSecRealtime);
             }
         } else {
             out.writeInt(0);
@@ -6879,9 +7266,12 @@
         pullPendingStateUpdatesLocked();
     }
 
-    public void dumpLocked(Context context, PrintWriter pw, boolean isUnpluggedOnly, int reqUid,
-            boolean historyOnly) {
+    public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
         if (DEBUG) {
+            pw.println("mOnBatteryTimeBase:");
+            mOnBatteryTimeBase.dump(pw, "  ");
+            pw.println("mOnBatteryScreenOffTimeBase:");
+            mOnBatteryScreenOffTimeBase.dump(pw, "  ");
             Printer pr = new PrintWriterPrinter(pw);
             pr.println("*** Screen timer:");
             mScreenOnTimer.logState(pr, "  ");
@@ -6920,6 +7310,6 @@
                 mBluetoothStateTimer[i].logState(pr, "  ");
             }
         }
-        super.dumpLocked(context, pw, isUnpluggedOnly, reqUid, historyOnly);
+        super.dumpLocked(context, pw, flags, reqUid, histStart);
     }
 }
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index bf62745..05c57e8 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -244,9 +244,11 @@
     }
 
     static void preload() {
+        Log.d(TAG, "begin preload");
         preloadClasses();
         preloadResources();
         preloadOpenGL();
+        Log.d(TAG, "end preload");
     }
 
     private static void preloadOpenGL() {
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 325a27d..e51345c 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -32,7 +32,9 @@
  * this file.
  */
 interface IInputMethodManager {
+    // TODO: Use ParceledListSlice instead
     List<InputMethodInfo> getInputMethodList();
+    // TODO: Use ParceledListSlice instead
     List<InputMethodInfo> getEnabledInputMethodList();
     List<InputMethodSubtype> getEnabledInputMethodSubtypeList(in String imiId,
             boolean allowsImplicitlySelectedSubtypes);
diff --git a/core/java/com/android/internal/view/RotationPolicy.java b/core/java/com/android/internal/view/RotationPolicy.java
index 9fefd00..b479cb1 100644
--- a/core/java/com/android/internal/view/RotationPolicy.java
+++ b/core/java/com/android/internal/view/RotationPolicy.java
@@ -58,7 +58,9 @@
         PackageManager pm = context.getPackageManager();
         return pm.hasSystemFeature(PackageManager.FEATURE_SENSOR_ACCELEROMETER)
                 && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT)
-                && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE);
+                && pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE)
+                && context.getResources().getBoolean(
+                        com.android.internal.R.bool.config_supportAutoRotation);
     }
 
     /**
@@ -184,6 +186,7 @@
      */
     public static abstract class RotationPolicyListener {
         final ContentObserver mObserver = new ContentObserver(new Handler()) {
+            @Override
             public void onChange(boolean selfChange, Uri uri) {
                 RotationPolicyListener.this.onChange();
             }
diff --git a/core/java/com/android/internal/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java
new file mode 100644
index 0000000..cc8ce2c
--- /dev/null
+++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import android.animation.TimeInterpolator;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.FrameLayout;
+
+/**
+ * Special layout that finishes its activity when swiped away.
+ */
+public class SwipeDismissLayout extends FrameLayout {
+    private static final String TAG = "SwipeDismissLayout";
+
+    private static final float TRANSLATION_MIN_ALPHA = 0.5f;
+
+    public interface OnDismissedListener {
+        void onDismissed(SwipeDismissLayout layout);
+    }
+
+    public interface OnSwipeProgressChangedListener {
+        /**
+         * Called when the layout has been swiped and the position of the window should change.
+         *
+         * @param progress A number in [-1, 1] representing how far to the left
+         * or right the window has been swiped. Negative values are swipes
+         * left, and positives are right.
+         * @param translate A number in [-w, w], where w is the width of the
+         * layout. This is equivalent to progress * layout.getWidth().
+         */
+        void onSwipeProgressChanged(SwipeDismissLayout layout, float progress, float translate);
+
+        void onSwipeCancelled(SwipeDismissLayout layout);
+    }
+
+    // Cached ViewConfiguration and system-wide constant values
+    private int mSlop;
+    private int mMinFlingVelocity;
+    private int mMaxFlingVelocity;
+    private long mAnimationTime;
+    private TimeInterpolator mCancelInterpolator;
+    private TimeInterpolator mDismissInterpolator;
+
+    // Transient properties
+    private int mActiveTouchId;
+    private float mDownX;
+    private float mDownY;
+    private boolean mSwiping;
+    private boolean mDismissed;
+    private boolean mDiscardIntercept;
+    private VelocityTracker mVelocityTracker;
+    private float mTranslationX;
+
+    private OnDismissedListener mDismissedListener;
+    private OnSwipeProgressChangedListener mProgressListener;
+
+    public SwipeDismissLayout(Context context) {
+        super(context);
+        init(context);
+    }
+
+    public SwipeDismissLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(context);
+    }
+
+    public SwipeDismissLayout(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init(context);
+    }
+
+    private void init(Context context) {
+        ViewConfiguration vc = ViewConfiguration.get(getContext());
+        mSlop = vc.getScaledTouchSlop();
+        mMinFlingVelocity = vc.getScaledMinimumFlingVelocity() * 16;
+        mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity();
+        mAnimationTime = getContext().getResources().getInteger(
+                android.R.integer.config_shortAnimTime);
+        mCancelInterpolator = new DecelerateInterpolator(1.5f);
+        mDismissInterpolator = new AccelerateInterpolator(1.5f);
+    }
+
+    public void setOnDismissedListener(OnDismissedListener listener) {
+        mDismissedListener = listener;
+    }
+
+    public void setOnSwipeProgressChangedListener(OnSwipeProgressChangedListener listener) {
+        mProgressListener = listener;
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        // offset because the view is translated during swipe
+        ev.offsetLocation(mTranslationX, 0);
+
+        switch (ev.getActionMasked()) {
+            case MotionEvent.ACTION_DOWN:
+                resetMembers();
+                mDownX = ev.getRawX();
+                mDownY = ev.getRawY();
+                mActiveTouchId = ev.getPointerId(0);
+                mVelocityTracker = VelocityTracker.obtain();
+                mVelocityTracker.addMovement(ev);
+                break;
+
+            case MotionEvent.ACTION_CANCEL:
+            case MotionEvent.ACTION_UP:
+                resetMembers();
+                break;
+
+            case MotionEvent.ACTION_MOVE:
+                if (mVelocityTracker == null || mDiscardIntercept) {
+                    break;
+                }
+
+                int pointerIndex = ev.findPointerIndex(mActiveTouchId);
+                float dx = ev.getRawX() - mDownX;
+                float x = ev.getX(pointerIndex);
+                float y = ev.getY(pointerIndex);
+                if (dx != 0 && canScroll(this, false, dx, x, y)) {
+                    mDiscardIntercept = true;
+                    break;
+                }
+                updateSwiping(ev);
+                break;
+        }
+
+        return !mDiscardIntercept && mSwiping;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        if (mVelocityTracker == null) {
+            return super.onTouchEvent(ev);
+        }
+        switch (ev.getActionMasked()) {
+            case MotionEvent.ACTION_UP:
+                updateDismiss(ev);
+                if (mDismissed) {
+                    dismiss();
+                } else if (mSwiping) {
+                    cancel();
+                }
+                resetMembers();
+                break;
+
+            case MotionEvent.ACTION_CANCEL:
+                cancel();
+                resetMembers();
+                break;
+
+            case MotionEvent.ACTION_MOVE:
+                mVelocityTracker.addMovement(ev);
+                updateSwiping(ev);
+                updateDismiss(ev);
+                if (mSwiping) {
+                    setProgress(ev.getRawX() - mDownX);
+                    break;
+                }
+        }
+        return true;
+    }
+
+    private void setProgress(float deltaX) {
+        mTranslationX = deltaX;
+        if (mProgressListener != null) {
+            mProgressListener.onSwipeProgressChanged(this, deltaX / getWidth(), deltaX);
+        }
+    }
+
+    private void dismiss() {
+        if (mDismissedListener != null) {
+            mDismissedListener.onDismissed(this);
+        }
+    }
+
+    protected void cancel() {
+        if (mProgressListener != null) {
+            mProgressListener.onSwipeCancelled(this);
+        }
+    }
+
+    /**
+     * Resets internal members when canceling.
+     */
+    private void resetMembers() {
+        if (mVelocityTracker != null) {
+            mVelocityTracker.recycle();
+        }
+        mVelocityTracker = null;
+        mTranslationX = 0;
+        mDownX = 0;
+        mDownY = 0;
+        mSwiping = false;
+        mDismissed = false;
+        mDiscardIntercept = false;
+    }
+
+    private void updateSwiping(MotionEvent ev) {
+        if (!mSwiping) {
+            float deltaX = ev.getRawX() - mDownX;
+            float deltaY = ev.getRawY() - mDownY;
+            mSwiping = deltaX > mSlop * 2 && Math.abs(deltaY) < mSlop * 2;
+        }
+    }
+
+    private void updateDismiss(MotionEvent ev) {
+        if (!mDismissed) {
+            mVelocityTracker.addMovement(ev);
+            mVelocityTracker.computeCurrentVelocity(1000);
+
+            float deltaX = ev.getRawX() - mDownX;
+            float velocityX = mVelocityTracker.getXVelocity();
+            float absVelocityX = Math.abs(velocityX);
+            float absVelocityY = Math.abs(mVelocityTracker.getYVelocity());
+
+            if (deltaX > getWidth() / 2) {
+                mDismissed = true;
+            } else if (absVelocityX >= mMinFlingVelocity
+                    && absVelocityX <= mMaxFlingVelocity
+                    && absVelocityY < absVelocityX / 2
+                    && velocityX > 0
+                    && deltaX > 0) {
+                mDismissed = true;
+            }
+        }
+    }
+
+    /**
+     * Tests scrollability within child views of v in the direction of dx.
+     *
+     * @param v View to test for horizontal scrollability
+     * @param checkV Whether the view v passed should itself be checked for scrollability (true),
+     *               or just its children (false).
+     * @param dx Delta scrolled in pixels. Only the sign of this is used.
+     * @param x X coordinate of the active touch point
+     * @param y Y coordinate of the active touch point
+     * @return true if child views of v can be scrolled by delta of dx.
+     */
+    protected boolean canScroll(View v, boolean checkV, float dx, float x, float y) {
+        if (v instanceof ViewGroup) {
+            final ViewGroup group = (ViewGroup) v;
+            final int scrollX = v.getScrollX();
+            final int scrollY = v.getScrollY();
+            final int count = group.getChildCount();
+            for (int i = count - 1; i >= 0; i--) {
+                final View child = group.getChildAt(i);
+                if (x + scrollX >= child.getLeft() && x + scrollX < child.getRight() &&
+                        y + scrollY >= child.getTop() && y + scrollY < child.getBottom() &&
+                        canScroll(child, true, dx, x + scrollX - child.getLeft(),
+                                y + scrollY - child.getTop())) {
+                    return true;
+                }
+            }
+        }
+
+        return checkV && v.canScrollHorizontally((int) -dx);
+    }
+}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index d8041c5..a09c314 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -136,7 +136,6 @@
 	android_hardware_UsbDevice.cpp \
 	android_hardware_UsbDeviceConnection.cpp \
 	android_hardware_UsbRequest.cpp \
-	android_debug_JNITest.cpp \
 	android_util_FileObserver.cpp \
 	android/opengl/poly_clip.cpp.arm \
 	android/opengl/util.cpp.arm \
@@ -165,9 +164,8 @@
 	$(TOP)/frameworks/av/include \
 	$(TOP)/system/media/camera/include \
 	external/skia/src/core \
-	external/skia/src/pdf \
+	external/skia/src/effects \
 	external/skia/src/images \
-	external/skia/include/utils \
 	external/sqlite/dist \
 	external/sqlite/android \
 	external/expat/lib \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 100f71d..06e4717 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -133,7 +133,6 @@
 extern int register_android_database_SQLiteConnection(JNIEnv* env);
 extern int register_android_database_SQLiteGlobal(JNIEnv* env);
 extern int register_android_database_SQLiteDebug(JNIEnv* env);
-extern int register_android_debug_JNITest(JNIEnv* env);
 extern int register_android_nio_utils(JNIEnv* env);
 extern int register_android_text_format_Time(JNIEnv* env);
 extern int register_android_os_Debug(JNIEnv* env);
@@ -397,16 +396,16 @@
  *
  * This will cut up "extraOptsBuf" as we chop it into individual options.
  *
+ * If "quotingArg" is non-null, it is passed before each extra option in mOptions.
+ *
  * Adds the strings, if any, to mOptions.
  */
-void AndroidRuntime::parseExtraOpts(char* extraOptsBuf)
+void AndroidRuntime::parseExtraOpts(char* extraOptsBuf, const char* quotingArg)
 {
     JavaVMOption opt;
-    char* start;
-    char* end;
-
     memset(&opt, 0, sizeof(opt));
-    start = extraOptsBuf;
+    char* start = extraOptsBuf;
+    char* end = NULL;
     while (*start != '\0') {
         while (*start == ' ')                   /* skip leading whitespace */
             start++;
@@ -420,6 +419,11 @@
             *end++ = '\0';          /* mark end, advance to indicate more */
 
         opt.optionString = start;
+        if (quotingArg != NULL) {
+            JavaVMOption quotingOpt;
+            quotingOpt.optionString = quotingArg;
+            mOptions.add(quotingOpt);
+        }
         mOptions.add(opt);
         start = end;
     }
@@ -451,6 +455,9 @@
     char gctypeOptsBuf[sizeof("-Xgc:")-1 + PROPERTY_VALUE_MAX];
     char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX];
     char jitcodecachesizeOptsBuf[sizeof("-Xjitcodecachesize:")-1 + PROPERTY_VALUE_MAX];
+    char dalvikVmLibBuf[PROPERTY_VALUE_MAX];
+    char dex2oatFlagsBuf[PROPERTY_VALUE_MAX];
+    char dex2oatImageFlagsBuf[PROPERTY_VALUE_MAX];
     char extraOptsBuf[PROPERTY_VALUE_MAX];
     char* stackTraceFile = NULL;
     bool checkJni = false;
@@ -743,9 +750,22 @@
         mOptions.add(opt);
     }
 
+    // libart tolerates libdvm flags, but not vice versa, so only pass these if libart.
+    property_get("persist.sys.dalvik.vm.lib.1", dalvikVmLibBuf, "libdvm.so");
+    if (strncmp(dalvikVmLibBuf, "libart", 6) == 0) {
+
+        // Extra options for DexClassLoader.
+        property_get("dalvik.vm.dex2oat-flags", dex2oatFlagsBuf, "");
+        parseExtraOpts(dex2oatFlagsBuf, "-Xcompiler-option");
+
+        // Extra options for boot.art/boot.oat image generation.
+        property_get("dalvik.vm.image-dex2oat-flags", dex2oatImageFlagsBuf, "");
+        parseExtraOpts(dex2oatImageFlagsBuf, "-Ximage-compiler-option");
+    }
+
     /* extra options; parse this late so it overrides others */
     property_get("dalvik.vm.extra-opts", extraOptsBuf, "");
-    parseExtraOpts(extraOptsBuf);
+    parseExtraOpts(extraOptsBuf, NULL);
 
     /* Set the properties for locale */
     {
@@ -761,6 +781,49 @@
         mOptions.add(opt);
     }
 
+    /*
+     * Set profiler options
+     */
+    {
+      char period[sizeof("-Xprofile-period:") + PROPERTY_VALUE_MAX];
+      char duration[sizeof("-Xprofile-duration:") + PROPERTY_VALUE_MAX];
+      char interval[sizeof("-Xprofile-interval:") + PROPERTY_VALUE_MAX];
+      char backoff[sizeof("-Xprofile-backoff:") + PROPERTY_VALUE_MAX];
+
+      // Number of seconds during profile runs.
+      strcpy(period, "-Xprofile-period:");
+      property_get("dalvik.vm.profile.period_secs", period+17, "10");
+      opt.optionString = period;
+      mOptions.add(opt);
+
+      // Length of each profile run (seconds).
+      strcpy(duration, "-Xprofile-duration:");
+      property_get("dalvik.vm.profile.duration_secs", duration+19, "30");
+      opt.optionString = duration;
+      mOptions.add(opt);
+
+
+      // Polling interval during profile run (microseconds).
+      strcpy(interval, "-Xprofile-interval:");
+      property_get("dalvik.vm.profile.interval_us", interval+19, "10000");
+      opt.optionString = interval;
+      mOptions.add(opt);
+
+      // Coefficient for period backoff.  The the period is multiplied
+      // by this value after each profile run.
+      strcpy(backoff, "-Xprofile-backoff:");
+      property_get("dalvik.vm.profile.backoff_coeff", backoff+18, "2.0");
+      opt.optionString = backoff;
+      mOptions.add(opt);
+    }
+
+    /*
+     * We don't have /tmp on the device, but we often have an SD card.  Apps
+     * shouldn't use this, but some test suites might want to exercise it.
+     */
+    opt.optionString = "-Djava.io.tmpdir=/sdcard";
+    mOptions.add(opt);
+
     initArgs.version = JNI_VERSION_1_4;
     initArgs.options = mOptions.editArray();
     initArgs.nOptions = mOptions.size();
@@ -1095,7 +1158,6 @@
 }
 
 static const RegJNIRec gRegJNI[] = {
-    REG_JNI(register_android_debug_JNITest),
     REG_JNI(register_com_android_internal_os_RuntimeInit),
     REG_JNI(register_android_os_SystemClock),
     REG_JNI(register_android_util_EventLog),
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index fae93ba..e8feacb 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -125,12 +125,18 @@
 static SkPixelRef* installPixelRef(SkBitmap* bitmap, SkStreamRewindable* stream,
         int sampleSize, bool ditherImage) {
 
+    SkImageInfo bitmapInfo;
+    if (!bitmap->asImageInfo(&bitmapInfo)) {
+        ALOGW("bitmap has unknown configuration so no memory has been allocated");
+        return NULL;
+    }
+
     SkImageRef* pr;
     // only use ashmem for large images, since mmaps come at a price
     if (bitmap->getSize() >= 32 * 1024) {
-        pr = new SkImageRef_ashmem(stream, bitmap->config(), sampleSize);
+        pr = new SkImageRef_ashmem(bitmapInfo, stream, sampleSize);
     } else {
-        pr = new SkImageRef_GlobalPool(stream, bitmap->config(), sampleSize);
+        pr = new SkImageRef_GlobalPool(bitmapInfo, stream, sampleSize);
     }
     pr->setDitherImage(ditherImage);
     bitmap->setPixelRef(pr)->unref();
@@ -192,8 +198,15 @@
             return false;
         }
 
+        SkImageInfo bitmapInfo;
+        if (!bitmap->asImageInfo(&bitmapInfo)) {
+            ALOGW("unable to reuse a bitmap as the target has an unknown bitmap configuration");
+            return false;
+        }
+
         // Create a new pixelref with the new ctable that wraps the previous pixelref
-        SkPixelRef* pr = new AndroidPixelRef(*static_cast<AndroidPixelRef*>(mPixelRef), ctable);
+        SkPixelRef* pr = new AndroidPixelRef(*static_cast<AndroidPixelRef*>(mPixelRef),
+                bitmapInfo, bitmap->rowBytes(), ctable);
 
         bitmap->setPixelRef(pr)->unref();
         // since we're already allocated, we lockPixels right away
@@ -418,7 +431,7 @@
         }
 
         SkPaint paint;
-        paint.setFilterBitmap(true);
+        paint.setFilterLevel(SkPaint::kLow_FilterLevel);
 
         SkCanvas canvas(*outputBitmap);
         canvas.scale(sx, sy);
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index e98d45b..7420055 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -555,7 +555,7 @@
                 if (paint) {
                     filteredPaint = *paint;
                 }
-                filteredPaint.setFilterBitmap(true);
+                filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
                 canvas->drawBitmap(*bitmap, left_, top_, &filteredPaint);
             } else {
                 canvas->drawBitmap(*bitmap, left_, top_, paint);
@@ -570,7 +570,7 @@
             if (paint) {
                 filteredPaint = *paint;
             }
-            filteredPaint.setFilterBitmap(true);
+            filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
 
             canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint);
 
@@ -593,7 +593,7 @@
             if (paint) {
                 filteredPaint = *paint;
             }
-            filteredPaint.setFilterBitmap(true);
+            filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
             canvas->drawBitmapRect(*bitmap, srcPtr, dst, &filteredPaint);
         } else {
             canvas->drawBitmapRect(*bitmap, srcPtr, dst, paint);
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 66f9f3d..98edbdb 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -444,8 +444,9 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-AndroidPixelRef::AndroidPixelRef(JNIEnv* env, void* storage, size_t size, jbyteArray storageObj,
-        SkColorTable* ctable) : SkMallocPixelRef(storage, size, ctable, (storageObj == NULL)),
+AndroidPixelRef::AndroidPixelRef(JNIEnv* env, const SkImageInfo& info, void* storage,
+        size_t rowBytes, jbyteArray storageObj, SkColorTable* ctable) :
+        SkMallocPixelRef(info, storage, rowBytes, ctable, (storageObj == NULL)),
         fWrappedPixelRef(NULL) {
     SkASSERT(storage);
     SkASSERT(env);
@@ -463,10 +464,11 @@
 
 }
 
-AndroidPixelRef::AndroidPixelRef(AndroidPixelRef& wrappedPixelRef, SkColorTable* ctable) :
-        SkMallocPixelRef(wrappedPixelRef.getAddr(), wrappedPixelRef.getSize(), ctable, false),
+AndroidPixelRef::AndroidPixelRef(AndroidPixelRef& wrappedPixelRef, const SkImageInfo& info,
+        size_t rowBytes, SkColorTable* ctable) :
+        SkMallocPixelRef(info, wrappedPixelRef.getAddr(), rowBytes, ctable, false),
         fWrappedPixelRef(wrappedPixelRef.fWrappedPixelRef ?
-            wrappedPixelRef.fWrappedPixelRef : &wrappedPixelRef)
+                wrappedPixelRef.fWrappedPixelRef : &wrappedPixelRef)
 {
     SkASSERT(fWrappedPixelRef);
     SkSafeRef(fWrappedPixelRef);
@@ -568,6 +570,14 @@
                           "bitmap size exceeds 32bits");
         return NULL;
     }
+
+    SkImageInfo bitmapInfo;
+    if (!bitmap->asImageInfo(&bitmapInfo)) {
+        jniThrowException(env, "java/lang/IllegalArgumentException",
+                "unknown bitmap configuration");
+        return NULL;
+    }
+
     size_t size = size64.get32();
     jbyteArray arrayObj = (jbyteArray) env->CallObjectMethod(gVMRuntime,
                                                              gVMRuntime_newNonMovableArray,
@@ -581,7 +591,8 @@
         return NULL;
     }
     SkASSERT(addr);
-    SkPixelRef* pr = new AndroidPixelRef(env, (void*) addr, size, arrayObj, ctable);
+    SkPixelRef* pr = new AndroidPixelRef(env, bitmapInfo, (void*) addr,
+            bitmap->rowBytes(), arrayObj, ctable);
     bitmap->setPixelRef(pr)->unref();
     // since we're already allocated, we lockPixels right away
     // HeapAllocator behaves this way too
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 5f29604..cb154aa 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -92,15 +92,16 @@
 
 class AndroidPixelRef : public SkMallocPixelRef {
 public:
-    AndroidPixelRef(JNIEnv* env, void* storage, size_t size, jbyteArray storageObj,
-                    SkColorTable* ctable);
+    AndroidPixelRef(JNIEnv* env, const SkImageInfo& info, void* storage, size_t rowBytes,
+            jbyteArray storageObj, SkColorTable* ctable);
 
     /**
      * Creates an AndroidPixelRef that wraps (and refs) another to reuse/share
      * the same storage and java byte array refcounting, yet have a different
      * color table.
      */
-    AndroidPixelRef(AndroidPixelRef& wrappedPixelRef, SkColorTable* ctable);
+    AndroidPixelRef(AndroidPixelRef& wrappedPixelRef, const SkImageInfo& info,
+            size_t rowBytes, SkColorTable* ctable);
 
     virtual ~AndroidPixelRef();
 
diff --git a/core/jni/android/graphics/MaskFilter.cpp b/core/jni/android/graphics/MaskFilter.cpp
index f331af7..5573366 100644
--- a/core/jni/android/graphics/MaskFilter.cpp
+++ b/core/jni/android/graphics/MaskFilter.cpp
@@ -1,5 +1,6 @@
 #include "GraphicsJNI.h"
 #include "SkMaskFilter.h"
+#include "SkBlurMask.h"
 #include "SkBlurMaskFilter.h"
 #include "SkTableMaskFilter.h"
 
@@ -19,8 +20,9 @@
     }
 
     static jlong createBlur(JNIEnv* env, jobject, jfloat radius, jint blurStyle) {
-        SkMaskFilter* filter = SkBlurMaskFilter::Create(SkFloatToScalar(radius),
-                                        (SkBlurMaskFilter::BlurStyle)blurStyle);
+        SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(SkFloatToScalar(radius));
+        SkMaskFilter* filter = SkBlurMaskFilter::Create(
+                (SkBlurMaskFilter::BlurStyle)blurStyle, sigma);
         ThrowIAE_IfNull(env, filter);
         return reinterpret_cast<jlong>(filter);
     }
@@ -34,10 +36,9 @@
             direction[i] = SkFloatToScalar(values[i]);
         }
 
-        SkMaskFilter* filter =  SkBlurMaskFilter::CreateEmboss(direction,
-                                                      SkFloatToScalar(ambient),
-                                                      SkFloatToScalar(specular),
-                                                      SkFloatToScalar(radius));
+        SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(SkFloatToScalar(radius));
+        SkMaskFilter* filter =  SkBlurMaskFilter::CreateEmboss(sigma,
+                direction, SkFloatToScalar(ambient), SkFloatToScalar(specular));
         ThrowIAE_IfNull(env, filter);
         return reinterpret_cast<jlong>(filter);
     }
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 6c81f06..189fe47 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -155,7 +155,8 @@
 
     static void setFilterBitmap(JNIEnv* env, jobject paint, jboolean filterBitmap) {
         NPE_CHECK_RETURN_VOID(env, paint);
-        GraphicsJNI::getNativePaint(env, paint)->setFilterBitmap(filterBitmap);
+        GraphicsJNI::getNativePaint(env, paint)->setFilterLevel(
+                filterBitmap ? SkPaint::kLow_FilterLevel : SkPaint::kNone_FilterLevel);
     }
 
     static void setDither(JNIEnv* env, jobject paint, jboolean dither) {
diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp
index 6bbf45a..e580d36 100644
--- a/core/jni/android/graphics/Path.cpp
+++ b/core/jni/android/graphics/Path.cpp
@@ -25,7 +25,7 @@
 #include <android_runtime/AndroidRuntime.h>
 
 #include "SkPath.h"
-#include "pathops/SkPathOps.h"
+#include "SkPathOps.h"
 
 #include <Caches.h>
 #include <vector>
@@ -72,11 +72,16 @@
         *dst = *src;
     }
 
+    static jboolean isConvex(JNIEnv* env, jobject clazz, jlong objHandle) {
+        SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
+        return obj->isConvex();
+    }
+
     static jint getFillType(JNIEnv* env, jobject clazz, jlong objHandle) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         return obj->getFillType();
     }
- 
+
     static void setFillType(JNIEnv* env, jobject clazz, jlong pathHandle, jint ftHandle) {
         SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
         SkPath::FillType ft = static_cast<SkPath::FillType>(ftHandle);
@@ -524,6 +529,7 @@
     {"native_reset","(J)V", (void*) SkPathGlue::reset},
     {"native_rewind","(J)V", (void*) SkPathGlue::rewind},
     {"native_set","(JJ)V", (void*) SkPathGlue::assign},
+    {"native_isConvex","(J)Z", (void*) SkPathGlue::isConvex},
     {"native_getFillType","(J)I", (void*) SkPathGlue::getFillType},
     {"native_setFillType","(JI)V", (void*) SkPathGlue::setFillType},
     {"native_isEmpty","(J)Z", (void*) SkPathGlue::isEmpty},
diff --git a/core/jni/android/graphics/Region.cpp b/core/jni/android/graphics/Region.cpp
index bcf1273..912968a 100644
--- a/core/jni/android/graphics/Region.cpp
+++ b/core/jni/android/graphics/Region.cpp
@@ -214,7 +214,7 @@
 
     SkRegion* region = new SkRegion;
     size_t size = p->readInt32();
-    region->readFromMemory(p->readInplace(size));
+    region->readFromMemory(p->readInplace(size), size);
 
     return reinterpret_cast<jlong>(region);
 }
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index 3047440..1fe6358 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -520,7 +520,7 @@
     SkiaShader* shaderB = reinterpret_cast<SkiaShader *>(shaderBHandle);
     SkXfermode* mode = reinterpret_cast<SkXfermode *>(modeHandle);
     SkXfermode::Mode skiaMode;
-    if (!SkXfermode::IsMode(mode, &skiaMode)) {
+    if (!SkXfermode::AsMode(mode, &skiaMode)) {
         // TODO: Support other modes
         skiaMode = SkXfermode::kSrcOver_Mode;
     }
diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp
index a17f328..a91c622 100644
--- a/core/jni/android/opengl/util.cpp
+++ b/core/jni/android/opengl/util.cpp
@@ -27,7 +27,7 @@
 #include <GLES/gl.h>
 #include <ETC1/etc1.h>
 
-#include <core/SkBitmap.h>
+#include <SkBitmap.h>
 
 #include "android_runtime/AndroidRuntime.h"
 
diff --git a/core/jni/android_debug_JNITest.cpp b/core/jni/android_debug_JNITest.cpp
deleted file mode 100644
index 9147284..0000000
--- a/core/jni/android_debug_JNITest.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/* //device/libs/android_runtime/android_debug_JNITest.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.
-*/
-
-#define LOG_TAG "DebugJNI"
-
-#include "jni.h"
-#include "nativehelper/JNIHelp.h"
-#include "utils/Log.h"
-#include "utils/misc.h"
-//#include "android_runtime/AndroidRuntime.h"
-
-namespace android {
-
-/*
- * Implements:
- *  native int part1(int intArg, double doubleArg, String stringArg,
- *      int[] arrayArg)
- */
-static jint android_debug_JNITest_part1(JNIEnv* env, jobject object,
-    jint intArg, jdouble doubleArg, jstring stringArg, jobjectArray arrayArg)
-{
-    jclass clazz;
-    jmethodID part2id;
-    jsize arrayLen;
-    jint arrayVal;
-    int result = -2;
-
-    ALOGI("JNI test: in part1, intArg=%d, doubleArg=%.3f\n", intArg, doubleArg);
-
-    /* find "int part2(double doubleArg, int fromArray, String stringArg)" */
-    clazz = env->GetObjectClass(object);
-    part2id = env->GetMethodID(clazz,
-                "part2", "(DILjava/lang/String;)I");
-    if (part2id == NULL) {
-        ALOGE("JNI test: unable to find part2\n");
-        return -1;
-    }
-
-    /* get the length of the array */
-    arrayLen = env->GetArrayLength(arrayArg);
-    ALOGI("  array size is %d\n", arrayLen);
-
-    /*
-     * Get the last element in the array.
-     * Use the Get<type>ArrayElements functions instead if you need access
-     * to multiple elements.
-     */
-    arrayVal = (int) env->GetObjectArrayElement(arrayArg, arrayLen-1);
-    ALOGI("  array val is %d\n", arrayVal);
-
-    /* call this->part2 */
-    result = env->CallIntMethod(object, part2id,
-        doubleArg, arrayVal, stringArg);
-
-    return result;
-}
-
-/*
- * Implements:
- *  private static native int part3(String stringArg);
- */
-static jint android_debug_JNITest_part3(JNIEnv* env, jclass clazz,
-    jstring stringArg)
-{
-    const char* utfChars;
-    jboolean isCopy;
-
-    ALOGI("JNI test: in part3\n");
-
-    utfChars = env->GetStringUTFChars(stringArg, &isCopy);
-
-    ALOGI("  String is '%s', isCopy=%d\n", (const char*) utfChars, isCopy);
-
-    env->ReleaseStringUTFChars(stringArg, utfChars);
-
-    return 2000;
-}
-
-/*
- * JNI registration.
- */
-static JNINativeMethod gMethods[] = {
-    /* name, signature, funcPtr */
-    { "part1",      "(IDLjava/lang/String;[I)I",
-            (void*) android_debug_JNITest_part1 },
-    { "part3",      "(Ljava/lang/String;)I",
-            (void*) android_debug_JNITest_part3 },
-};
-int register_android_debug_JNITest(JNIEnv* env)
-{
-    return jniRegisterNativeMethods(env, "android/debug/JNITest",
-        gMethods, NELEM(gMethods));
-}
-
-#if 0
-/* trampoline into C++ */
-extern "C"
-int register_android_debug_JNITest_C(JNIEnv* env)
-{
-    return android::register_android_debug_JNITest(env);
-}
-#endif
-
-}; // namespace android
-
diff --git a/core/jni/android_hardware_UsbDeviceConnection.cpp b/core/jni/android_hardware_UsbDeviceConnection.cpp
index c10b963f..467a9a1 100644
--- a/core/jni/android_hardware_UsbDeviceConnection.cpp
+++ b/core/jni/android_hardware_UsbDeviceConnection.cpp
@@ -123,20 +123,45 @@
     return (ret == 0) ? JNI_TRUE : JNI_FALSE;
 }
 
-static jint
+static jboolean
 android_hardware_UsbDeviceConnection_release_interface(JNIEnv *env, jobject thiz, jint interfaceID)
 {
     struct usb_device* device = get_device_from_object(env, thiz);
     if (!device) {
         ALOGE("device is closed in native_release_interface");
-        return -1;
+        return JNI_FALSE;
     }
     int ret = usb_device_release_interface(device, interfaceID);
     if (ret == 0) {
         // allow kernel to reconnect its driver
         usb_device_connect_kernel_driver(device, interfaceID, true);
     }
-    return ret;
+    return (ret == 0) ? JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean
+android_hardware_UsbDeviceConnection_set_interface(JNIEnv *env, jobject thiz, jint interfaceID,
+        jint alternateSetting)
+{
+    struct usb_device* device = get_device_from_object(env, thiz);
+    if (!device) {
+        ALOGE("device is closed in native_set_interface");
+        return JNI_FALSE;
+    }
+    int ret = usb_device_set_interface(device, interfaceID, alternateSetting);
+    return (ret == 0) ? JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean
+android_hardware_UsbDeviceConnection_set_configuration(JNIEnv *env, jobject thiz, jint configurationID)
+{
+    struct usb_device* device = get_device_from_object(env, thiz);
+    if (!device) {
+        ALOGE("device is closed in native_set_configuration");
+        return JNI_FALSE;
+    }
+    int ret = usb_device_set_configuration(device, configurationID);
+    return (ret == 0) ? JNI_TRUE : JNI_FALSE;
 }
 
 static jint
@@ -229,6 +254,8 @@
     {"native_get_desc",         "()[B", (void *)android_hardware_UsbDeviceConnection_get_desc},
     {"native_claim_interface",  "(IZ)Z",(void *)android_hardware_UsbDeviceConnection_claim_interface},
     {"native_release_interface","(I)Z", (void *)android_hardware_UsbDeviceConnection_release_interface},
+    {"native_set_interface","(II)Z",    (void *)android_hardware_UsbDeviceConnection_set_interface},
+    {"native_set_configuration","(I)Z", (void *)android_hardware_UsbDeviceConnection_set_configuration},
     {"native_control_request",  "(IIII[BIII)I",
                                         (void *)android_hardware_UsbDeviceConnection_control_request},
     {"native_bulk_request",     "(I[BIII)I",
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 9c357de..0132b5f 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -18,6 +18,7 @@
 
 #define LOG_TAG "AudioRecord-JNI"
 
+#include <inttypes.h>
 #include <jni.h>
 #include <JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
@@ -311,7 +312,7 @@
     if (lpRecorder == NULL) {
         return;
     }
-    ALOGV("About to delete lpRecorder: %x\n", (int)lpRecorder.get());
+    ALOGV("About to delete lpRecorder: %" PRIxPTR "\n", lpRecorder.get());
     lpRecorder->stop();
 
     audiorecord_callback_cookie *lpCookie = (audiorecord_callback_cookie *)env->GetLongField(
@@ -324,7 +325,7 @@
     // delete the callback information
     if (lpCookie) {
         Mutex::Autolock l(sLock);
-        ALOGV("deleting lpCookie: %x\n", (int)lpCookie);
+        ALOGV("deleting lpCookie: %" PRIxPTR "\n", lpCookie);
         while (lpCookie->busy) {
             if (lpCookie->cond.waitRelative(sLock,
                                             milliseconds(CALLBACK_COND_WAIT_TIMEOUT_MS)) !=
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 8c7b34a..7e958e7 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -263,7 +263,7 @@
 
     // compute the frame count
     const size_t bytesPerSample = audio_bytes_per_sample(format);
-    int frameCount = buffSizeInBytes / (nbChannels * bytesPerSample);
+    size_t frameCount = buffSizeInBytes / (nbChannels * bytesPerSample);
 
     jclass clazz = env->GetObjectClass(thiz);
     if (clazz == NULL) {
diff --git a/core/jni/android_opengl_EGL14.cpp b/core/jni/android_opengl_EGL14.cpp
index 5b0a4b2..19e4d99 100644
--- a/core/jni/android_opengl_EGL14.cpp
+++ b/core/jni/android_opengl_EGL14.cpp
@@ -69,22 +69,22 @@
     jclass eglconfigClassLocal = _env->FindClass("android/opengl/EGLConfig");
     eglconfigClass = (jclass) _env->NewGlobalRef(eglconfigClassLocal);
 
-    egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getHandle", "()I");
-    eglcontextGetHandleID = _env->GetMethodID(eglcontextClass, "getHandle", "()I");
-    eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getHandle", "()I");
-    eglconfigGetHandleID = _env->GetMethodID(eglconfigClass, "getHandle", "()I");
+    egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getNativeHandle", "()J");
+    eglcontextGetHandleID = _env->GetMethodID(eglcontextClass, "getNativeHandle", "()J");
+    eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getNativeHandle", "()J");
+    eglconfigGetHandleID = _env->GetMethodID(eglconfigClass, "getNativeHandle", "()J");
 
 
-    egldisplayConstructor = _env->GetMethodID(egldisplayClass, "<init>", "(I)V");
-    eglcontextConstructor = _env->GetMethodID(eglcontextClass, "<init>", "(I)V");
-    eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(I)V");
-    eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(I)V");
+    egldisplayConstructor = _env->GetMethodID(egldisplayClass, "<init>", "(J)V");
+    eglcontextConstructor = _env->GetMethodID(eglcontextClass, "<init>", "(J)V");
+    eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(J)V");
+    eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(J)V");
 
-    jobject localeglNoContextObject = _env->NewObject(eglcontextClass, eglcontextConstructor, (jint)EGL_NO_CONTEXT);
+    jobject localeglNoContextObject = _env->NewObject(eglcontextClass, eglcontextConstructor, reinterpret_cast<jlong>(EGL_NO_CONTEXT));
     eglNoContextObject = _env->NewGlobalRef(localeglNoContextObject);
-    jobject localeglNoDisplayObject = _env->NewObject(egldisplayClass, egldisplayConstructor, (jint)EGL_NO_DISPLAY);
+    jobject localeglNoDisplayObject = _env->NewObject(egldisplayClass, egldisplayConstructor, reinterpret_cast<jlong>(EGL_NO_DISPLAY));
     eglNoDisplayObject = _env->NewGlobalRef(localeglNoDisplayObject);
-    jobject localeglNoSurfaceObject = _env->NewObject(eglsurfaceClass, eglsurfaceConstructor, (jint)EGL_NO_SURFACE);
+    jobject localeglNoSurfaceObject = _env->NewObject(eglsurfaceClass, eglsurfaceConstructor, reinterpret_cast<jlong>(EGL_NO_SURFACE));
     eglNoSurfaceObject = _env->NewGlobalRef(localeglNoSurfaceObject);
 
 
@@ -106,7 +106,8 @@
                           "Object is set to null.");
     }
 
-    return (void*) (_env->CallIntMethod(obj, mid));
+    jlong handle = _env->CallLongMethod(obj, mid);
+    return reinterpret_cast<void*>(handle);
 }
 
 static jobject
@@ -126,7 +127,7 @@
            return eglNoSurfaceObject;
     }
 
-    return _env->NewObject(cls, con, (jint)handle);
+    return _env->NewObject(cls, con, reinterpret_cast<jlong>(handle));
 }
 
 // --------------------------------------------------------------------------
@@ -142,14 +143,26 @@
 /* EGLDisplay eglGetDisplay ( EGLNativeDisplayType display_id ) */
 static jobject
 android_eglGetDisplay
-  (JNIEnv *_env, jobject _this, jint display_id) {
+  (JNIEnv *_env, jobject _this, jlong display_id) {
     EGLDisplay _returnValue = (EGLDisplay) 0;
     _returnValue = eglGetDisplay(
-        (EGLNativeDisplayType)display_id
+        reinterpret_cast<EGLNativeDisplayType>(display_id)
     );
     return toEGLHandle(_env, egldisplayClass, egldisplayConstructor, _returnValue);
 }
 
+/* EGLDisplay eglGetDisplay ( EGLNativeDisplayType display_id ) */
+static jobject
+android_eglGetDisplayInt
+  (JNIEnv *_env, jobject _this, jint display_id) {
+
+    if ((EGLNativeDisplayType)display_id != EGL_DEFAULT_DISPLAY) {
+        jniThrowException(_env, "java/lang/UnsupportedOperationException", "eglGetDisplay");
+        return 0;
+    }
+    return android_eglGetDisplay(_env, _this, display_id);
+}
+
 /* EGLBoolean eglInitialize ( EGLDisplay dpy, EGLint *major, EGLint *minor ) */
 static jboolean
 android_eglInitialize
@@ -852,7 +865,7 @@
 /* EGLSurface eglCreatePbufferFromClientBuffer ( EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list ) */
 static jobject
 android_eglCreatePbufferFromClientBuffer
-  (JNIEnv *_env, jobject _this, jobject dpy, jint buftype, jint buffer, jobject config, jintArray attrib_list_ref, jint offset) {
+  (JNIEnv *_env, jobject _this, jobject dpy, jint buftype, jlong buffer, jobject config, jintArray attrib_list_ref, jint offset) {
     jint _exception = 0;
     const char * _exceptionType = NULL;
     const char * _exceptionMessage = NULL;
@@ -897,7 +910,7 @@
     _returnValue = eglCreatePbufferFromClientBuffer(
         (EGLDisplay)dpy_native,
         (EGLenum)buftype,
-        (EGLClientBuffer)buffer,
+        reinterpret_cast<EGLClientBuffer>(buffer),
         (EGLConfig)config_native,
         (EGLint *)attrib_list
     );
@@ -913,6 +926,16 @@
     return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
 }
 
+static jobject
+android_eglCreatePbufferFromClientBufferInt
+  (JNIEnv *_env, jobject _this, jobject dpy, jint buftype, jint buffer, jobject config, jintArray attrib_list_ref, jint offset) {
+    if(sizeof(void*) != sizeof(uint32_t)) {
+        jniThrowException(_env, "java/lang/UnsupportedOperationException", "eglCreatePbufferFromClientBuffer");
+        return 0;
+    }
+    return android_eglCreatePbufferFromClientBuffer(_env, _this, dpy, buftype, buffer, config, attrib_list_ref, offset);
+}
+
 /* EGLBoolean eglSurfaceAttrib ( EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value ) */
 static jboolean
 android_eglSurfaceAttrib
@@ -1207,7 +1230,8 @@
 static JNINativeMethod methods[] = {
 {"_nativeClassInit", "()V", (void*)nativeClassInit },
 {"eglGetError", "()I", (void *) android_eglGetError },
-{"eglGetDisplay", "(I)Landroid/opengl/EGLDisplay;", (void *) android_eglGetDisplay },
+{"eglGetDisplay", "(I)Landroid/opengl/EGLDisplay;", (void *) android_eglGetDisplayInt },
+{"eglGetDisplay", "(J)Landroid/opengl/EGLDisplay;", (void *) android_eglGetDisplay },
 {"eglInitialize", "(Landroid/opengl/EGLDisplay;[II[II)Z", (void *) android_eglInitialize },
 {"eglTerminate", "(Landroid/opengl/EGLDisplay;)Z", (void *) android_eglTerminate },
 {"eglQueryString", "(Landroid/opengl/EGLDisplay;I)Ljava/lang/String;", (void *) android_eglQueryString__Landroind_opengl_EGLDisplay_2I },
@@ -1224,7 +1248,8 @@
 {"eglQueryAPI", "()I", (void *) android_eglQueryAPI },
 {"eglWaitClient", "()Z", (void *) android_eglWaitClient },
 {"eglReleaseThread", "()Z", (void *) android_eglReleaseThread },
-{"eglCreatePbufferFromClientBuffer", "(Landroid/opengl/EGLDisplay;IILandroid/opengl/EGLConfig;[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePbufferFromClientBuffer },
+{"eglCreatePbufferFromClientBuffer", "(Landroid/opengl/EGLDisplay;IILandroid/opengl/EGLConfig;[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePbufferFromClientBufferInt },
+{"eglCreatePbufferFromClientBuffer", "(Landroid/opengl/EGLDisplay;IJLandroid/opengl/EGLConfig;[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreatePbufferFromClientBuffer },
 {"eglSurfaceAttrib", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;II)Z", (void *) android_eglSurfaceAttrib },
 {"eglBindTexImage", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;I)Z", (void *) android_eglBindTexImage },
 {"eglReleaseTexImage", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLSurface;I)Z", (void *) android_eglReleaseTexImage },
diff --git a/core/jni/android_opengl_EGLExt.cpp b/core/jni/android_opengl_EGLExt.cpp
index 5179ddc..15899f5 100644
--- a/core/jni/android_opengl_EGLExt.cpp
+++ b/core/jni/android_opengl_EGLExt.cpp
@@ -70,22 +70,22 @@
     jclass eglconfigClassLocal = _env->FindClass("android/opengl/EGLConfig");
     eglconfigClass = (jclass) _env->NewGlobalRef(eglconfigClassLocal);
 
-    egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getHandle", "()I");
-    eglcontextGetHandleID = _env->GetMethodID(eglcontextClass, "getHandle", "()I");
-    eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getHandle", "()I");
-    eglconfigGetHandleID = _env->GetMethodID(eglconfigClass, "getHandle", "()I");
+    egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getNativeHandle", "()J");
+    eglcontextGetHandleID = _env->GetMethodID(eglcontextClass, "getNativeHandle", "()J");
+    eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getNativeHandle", "()J");
+    eglconfigGetHandleID = _env->GetMethodID(eglconfigClass, "getNativeHandle", "()J");
 
 
-    egldisplayConstructor = _env->GetMethodID(egldisplayClass, "<init>", "(I)V");
-    eglcontextConstructor = _env->GetMethodID(eglcontextClass, "<init>", "(I)V");
-    eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(I)V");
-    eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(I)V");
+    egldisplayConstructor = _env->GetMethodID(egldisplayClass, "<init>", "(J)V");
+    eglcontextConstructor = _env->GetMethodID(eglcontextClass, "<init>", "(J)V");
+    eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(J)V");
+    eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(J)V");
 
-    jobject localeglNoContextObject = _env->NewObject(eglcontextClass, eglcontextConstructor, (jint)EGL_NO_CONTEXT);
+    jobject localeglNoContextObject = _env->NewObject(eglcontextClass, eglcontextConstructor, reinterpret_cast<jlong>(EGL_NO_CONTEXT));
     eglNoContextObject = _env->NewGlobalRef(localeglNoContextObject);
-    jobject localeglNoDisplayObject = _env->NewObject(egldisplayClass, egldisplayConstructor, (jint)EGL_NO_DISPLAY);
+    jobject localeglNoDisplayObject = _env->NewObject(egldisplayClass, egldisplayConstructor, reinterpret_cast<jlong>(EGL_NO_DISPLAY));
     eglNoDisplayObject = _env->NewGlobalRef(localeglNoDisplayObject);
-    jobject localeglNoSurfaceObject = _env->NewObject(eglsurfaceClass, eglsurfaceConstructor, (jint)EGL_NO_SURFACE);
+    jobject localeglNoSurfaceObject = _env->NewObject(eglsurfaceClass, eglsurfaceConstructor, reinterpret_cast<jlong>(EGL_NO_SURFACE));
     eglNoSurfaceObject = _env->NewGlobalRef(localeglNoSurfaceObject);
 
 
@@ -107,7 +107,7 @@
                           "Object is set to null.");
     }
 
-    return (void*) (_env->CallIntMethod(obj, mid));
+    return reinterpret_cast<void*>(_env->CallLongMethod(obj, mid));
 }
 
 static jobject
@@ -127,7 +127,7 @@
            return eglNoSurfaceObject;
     }
 
-    return _env->NewObject(cls, con, (jint)handle);
+    return _env->NewObject(cls, con, reinterpret_cast<jlong>(handle));
 }
 
 // --------------------------------------------------------------------------
diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp
index cc34e99..21e19e1 100644
--- a/core/jni/android_opengl_GLES10.cpp
+++ b/core/jni/android_opengl_GLES10.cpp
@@ -111,7 +111,7 @@
             getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void*>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
diff --git a/core/jni/android_opengl_GLES10Ext.cpp b/core/jni/android_opengl_GLES10Ext.cpp
index 9284384..bc83234 100644
--- a/core/jni/android_opengl_GLES10Ext.cpp
+++ b/core/jni/android_opengl_GLES10Ext.cpp
@@ -111,7 +111,7 @@
             getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void*>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
diff --git a/core/jni/android_opengl_GLES11.cpp b/core/jni/android_opengl_GLES11.cpp
index 871e84d..a45f269 100644
--- a/core/jni/android_opengl_GLES11.cpp
+++ b/core/jni/android_opengl_GLES11.cpp
@@ -111,7 +111,7 @@
             getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void*>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
@@ -578,7 +578,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -679,7 +679,7 @@
         (GLenum)mode,
         (GLsizei)count,
         (GLenum)type,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
     if (_exception) {
         jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -2302,7 +2302,7 @@
     glNormalPointer(
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -2529,7 +2529,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -2937,7 +2937,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
diff --git a/core/jni/android_opengl_GLES11Ext.cpp b/core/jni/android_opengl_GLES11Ext.cpp
index 3e038ad..05728ef 100644
--- a/core/jni/android_opengl_GLES11Ext.cpp
+++ b/core/jni/android_opengl_GLES11Ext.cpp
@@ -111,7 +111,7 @@
             getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void*>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
diff --git a/core/jni/android_opengl_GLES20.cpp b/core/jni/android_opengl_GLES20.cpp
index db03b70..d3e5014 100644
--- a/core/jni/android_opengl_GLES20.cpp
+++ b/core/jni/android_opengl_GLES20.cpp
@@ -111,7 +111,7 @@
             getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void*>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
@@ -1180,7 +1180,7 @@
         (GLenum)mode,
         (GLsizei)count,
         (GLenum)type,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
     if (_exception) {
         jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -1804,7 +1804,7 @@
         (GLsizei *)length,
         (GLint *)size,
         (GLenum *)type,
-        (char *)name
+        reinterpret_cast<char *>(name)
     );
     if (_typeArray) {
         releasePointer(_env, _typeArray, type, JNI_TRUE);
@@ -2132,7 +2132,7 @@
         (GLsizei *)length,
         (GLint *)size,
         (GLenum *)type,
-        (char *)name
+        reinterpret_cast<char *>(name)
     );
     if (_typeArray) {
         releasePointer(_env, _typeArray, type, JNI_TRUE);
@@ -3212,7 +3212,7 @@
         (GLuint)shader,
         (GLsizei)bufsize,
         (GLsizei *)length,
-        (char *)source
+        reinterpret_cast<char *>(source)
     );
     if (_array) {
         releasePointer(_env, _array, length, JNI_TRUE);
@@ -5985,7 +5985,7 @@
         (GLenum)type,
         (GLboolean)normalized,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
diff --git a/core/jni/android_opengl_GLES30.cpp b/core/jni/android_opengl_GLES30.cpp
index 4c62a75..8821352 100644
--- a/core/jni/android_opengl_GLES30.cpp
+++ b/core/jni/android_opengl_GLES30.cpp
@@ -111,7 +111,7 @@
             getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void*>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
@@ -370,7 +370,7 @@
         (GLuint)end,
         (GLsizei)count,
         (GLenum)type,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -419,7 +419,7 @@
         (GLint)border,
         (GLenum)format,
         (GLenum)type,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -470,7 +470,7 @@
         (GLsizei)depth,
         (GLenum)format,
         (GLenum)type,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -534,7 +534,7 @@
         (GLsizei)depth,
         (GLint)border,
         (GLsizei)imageSize,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -585,7 +585,7 @@
         (GLsizei)depth,
         (GLenum)format,
         (GLsizei)imageSize,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -2134,7 +2134,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
diff --git a/core/jni/android_os_SystemClock.cpp b/core/jni/android_os_SystemClock.cpp
index 5f4d570..62478442 100644
--- a/core/jni/android_os_SystemClock.cpp
+++ b/core/jni/android_os_SystemClock.cpp
@@ -19,13 +19,6 @@
  * System clock functions.
  */
 
-#ifdef HAVE_ANDROID_OS
-#include <linux/ioctl.h>
-#include <linux/rtc.h>
-#include <utils/Atomic.h>
-#include <linux/android_alarm.h>
-#endif
-
 #include <sys/time.h>
 #include <limits.h>
 #include <fcntl.h>
@@ -43,109 +36,6 @@
 
 namespace android {
 
-static int setCurrentTimeMillisAlarmDriver(struct timeval *tv)
-{
-    struct timespec ts;
-    int fd;
-    int res;
-
-    fd = open("/dev/alarm", O_RDWR);
-    if(fd < 0) {
-        ALOGV("Unable to open alarm driver: %s\n", strerror(errno));
-        return -1;
-    }
-    ts.tv_sec = tv->tv_sec;
-    ts.tv_nsec = tv->tv_usec * 1000;
-    res = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts);
-    if (res < 0)
-        ALOGV("ANDROID_ALARM_SET_RTC ioctl failed: %s\n", strerror(errno));
-    close(fd);
-    return res;
-}
-
-static int setCurrentTimeMillisRtc(struct timeval *tv)
-{
-    struct rtc_time rtc;
-    struct tm tm, *gmtime_res;
-    int fd;
-    int res;
-
-    fd = open("/dev/rtc0", O_RDWR);
-    if (fd < 0) {
-        ALOGV("Unable to open RTC driver: %s\n", strerror(errno));
-        return -1;
-    }
-
-    res = settimeofday(tv, NULL);
-    if (res < 0) {
-        ALOGV("settimeofday() failed: %s\n", strerror(errno));
-        goto done;
-    }
-
-    gmtime_res = gmtime_r(&tv->tv_sec, &tm);
-    if (!gmtime_res) {
-        ALOGV("gmtime_r() failed: %s\n", strerror(errno));
-        res = -1;
-        goto done;
-    }
-
-    memset(&rtc, 0, sizeof(rtc));
-    rtc.tm_sec = tm.tm_sec;
-    rtc.tm_min = tm.tm_min;
-    rtc.tm_hour = tm.tm_hour;
-    rtc.tm_mday = tm.tm_mday;
-    rtc.tm_mon = tm.tm_mon;
-    rtc.tm_year = tm.tm_year;
-    rtc.tm_wday = tm.tm_wday;
-    rtc.tm_yday = tm.tm_yday;
-    rtc.tm_isdst = tm.tm_isdst;
-    res = ioctl(fd, RTC_SET_TIME, &rtc);
-    if (res < 0)
-        ALOGV("RTC_SET_TIME ioctl failed: %s\n", strerror(errno));
-done:
-    close(fd);
-    return res;
-}
-
-/*
- * Set the current time.  This only works when running as root.
- */
-static int setCurrentTimeMillis(int64_t millis)
-{
-    struct timeval tv;
-    int ret;
-
-    if (millis <= 0 || millis / 1000LL >= INT_MAX) {
-        return -1;
-    }
-
-    tv.tv_sec = (time_t) (millis / 1000LL);
-    tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL);
-
-    ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec);
-
-    ret = setCurrentTimeMillisAlarmDriver(&tv);
-    if (ret < 0)
-        ret = setCurrentTimeMillisRtc(&tv);
-
-    if(ret < 0) {
-        ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno));
-        ret = -1;
-    }
-    return ret;
-}
-
-/*
- * native public static void setCurrentTimeMillis(long millis)
- *
- * Set the current time.  This only works when running as root.
- */
-static jboolean android_os_SystemClock_setCurrentTimeMillis(JNIEnv* env,
-    jobject clazz, jlong millis)
-{
-    return (setCurrentTimeMillis(millis) == 0);
-}
-
 /*
  * native public static long uptimeMillis();
  */
@@ -230,8 +120,6 @@
  */
 static JNINativeMethod gMethods[] = {
     /* name, signature, funcPtr */
-    { "setCurrentTimeMillis",      "(J)Z",
-            (void*) android_os_SystemClock_setCurrentTimeMillis },
     { "uptimeMillis",      "()J",
             (void*) android_os_SystemClock_uptimeMillis },
     { "elapsedRealtime",      "()J",
diff --git a/core/jni/android_view_DisplayList.cpp b/core/jni/android_view_DisplayList.cpp
index e47e23c..c8952c1 100644
--- a/core/jni/android_view_DisplayList.cpp
+++ b/core/jni/android_view_DisplayList.cpp
@@ -41,18 +41,6 @@
 // DisplayList view properties
 // ----------------------------------------------------------------------------
 
-static void android_view_DisplayList_reset(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
-    displayList->reset();
-}
-
-static jint android_view_DisplayList_getDisplayListSize(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
-    return displayList->getSize();
-}
-
 static void android_view_DisplayList_setDisplayListName(JNIEnv* env,
         jobject clazz, jlong displayListPtr, jstring name) {
     DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
@@ -69,6 +57,11 @@
     displayList->output();
 }
 
+static jlong android_view_DisplayList_create(JNIEnv* env, jobject clazz) {
+    DisplayList* displayList = new DisplayList();
+    return reinterpret_cast<jlong>(displayList);
+}
+
 static void android_view_DisplayList_destroyDisplayList(JNIEnv* env,
         jobject clazz, jlong displayListPtr) {
     DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
@@ -285,18 +278,6 @@
     displayList->offsetTopBottom(offset);
 }
 
-static void android_view_DisplayList_getMatrix(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, jlong matrixPtr) {
-    DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
-    SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
-    SkMatrix* source = displayList->getStaticMatrix();
-    if (source) {
-        matrix->setConcat(SkMatrix::I(), *source);
-    } else {
-        matrix->setIdentity();
-    }
-}
-
 static jboolean android_view_DisplayList_hasOverlappingRendering(JNIEnv* env,
         jobject clazz, jlong displayListPtr) {
     DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
@@ -403,13 +384,12 @@
 
 static JNINativeMethod gMethods[] = {
 #ifdef USE_OPENGL_RENDERER
+    { "nCreate",               "()J",    (void*) android_view_DisplayList_create },
     { "nDestroyDisplayList",   "(J)V",   (void*) android_view_DisplayList_destroyDisplayList },
-    { "nGetDisplayListSize",   "(J)I",   (void*) android_view_DisplayList_getDisplayListSize },
     { "nSetDisplayListName",   "(JLjava/lang/String;)V",
             (void*) android_view_DisplayList_setDisplayListName },
     { "nOutput",               "(J)V",  (void*) android_view_DisplayList_output },
 
-    { "nReset",                "(J)V",   (void*) android_view_DisplayList_reset },
     { "nSetCaching",           "(JZ)V",  (void*) android_view_DisplayList_setCaching },
     { "nSetStaticMatrix",      "(JJ)V",  (void*) android_view_DisplayList_setStaticMatrix },
     { "nSetAnimationMatrix",   "(JJ)V",  (void*) android_view_DisplayList_setAnimationMatrix },
@@ -445,7 +425,6 @@
     { "nOffsetLeftAndRight",   "(JF)V",  (void*) android_view_DisplayList_offsetLeftAndRight },
     { "nOffsetTopAndBottom",   "(JF)V",  (void*) android_view_DisplayList_offsetTopAndBottom },
 
-    { "nGetMatrix",               "(JJ)V", (void*) android_view_DisplayList_getMatrix },
     { "nHasOverlappingRendering", "(J)Z",  (void*) android_view_DisplayList_hasOverlappingRendering },
     { "nGetAlpha",                "(J)F",  (void*) android_view_DisplayList_getAlpha },
     { "nGetLeft",                 "(J)F",  (void*) android_view_DisplayList_getLeft },
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index dd089f2..a4e6679 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -116,14 +116,12 @@
 // ----------------------------------------------------------------------------
 
 static void android_view_GLES20Canvas_initAtlas(JNIEnv* env, jobject clazz,
-        jobject graphicBuffer, jintArray atlasMapArray, jint count) {
+        jobject graphicBuffer, jlongArray atlasMapArray, jint count) {
 
     sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer);
-    jint* atlasMap = env->GetIntArrayElements(atlasMapArray, NULL);
-
-    Caches::getInstance().assetAtlas.init(buffer, atlasMap, count);
-
-    env->ReleaseIntArrayElements(atlasMapArray, atlasMap, 0);
+    jlong* jAtlasMap = env->GetLongArrayElements(atlasMapArray, NULL);
+    Caches::getInstance().assetAtlas.init(buffer, jAtlasMap, count);
+    env->ReleaseLongArrayElements(atlasMapArray, jAtlasMap, 0);
 }
 
 // ----------------------------------------------------------------------------
@@ -866,22 +864,15 @@
 // Display lists
 // ----------------------------------------------------------------------------
 
-static jint android_view_GLES20Canvas_getDisplayList(JNIEnv* env,
-        jobject clazz, jlong rendererPtr, jlong displayListPtr) {
-    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
-    return reinterpret_cast<jint>(renderer->getDisplayList(displayList));
-}
-
-static jint android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env,
-        jobject clazz) {
-    return reinterpret_cast<jint>(new DisplayListRenderer);
-}
-
-static void android_view_GLES20Canvas_resetDisplayListRenderer(JNIEnv* env,
+static jlong android_view_GLES20Canvas_finishRecording(JNIEnv* env,
         jobject clazz, jlong rendererPtr) {
     DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
-    renderer->reset();
+    return reinterpret_cast<jlong>(renderer->finishRecording());
+}
+
+static jlong android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env,
+        jobject clazz) {
+    return reinterpret_cast<jlong>(new DisplayListRenderer);
 }
 
 static jint android_view_GLES20Canvas_drawDisplayList(JNIEnv* env,
@@ -1002,7 +993,7 @@
     { "nInitCaches",        "()Z",             (void*) android_view_GLES20Canvas_initCaches },
     { "nTerminateCaches",   "()V",             (void*) android_view_GLES20Canvas_terminateCaches },
 
-    { "nInitAtlas",         "(Landroid/view/GraphicBuffer;[II)V",
+    { "nInitAtlas",         "(Landroid/view/GraphicBuffer;[JI)V",
             (void*) android_view_GLES20Canvas_initAtlas },
 
     { "nCreateRenderer",    "()J",             (void*) android_view_GLES20Canvas_createRenderer },
@@ -1096,12 +1087,11 @@
     { "nGetClipBounds",     "(JLandroid/graphics/Rect;)Z",
             (void*) android_view_GLES20Canvas_getClipBounds },
 
-    { "nGetDisplayList",         "(JJ)J",      (void*) android_view_GLES20Canvas_getDisplayList },
+    { "nFinishRecording",        "(J)J",      (void*) android_view_GLES20Canvas_finishRecording },
     { "nDrawDisplayList",        "(JJLandroid/graphics/Rect;I)I",
             (void*) android_view_GLES20Canvas_drawDisplayList },
 
     { "nCreateDisplayListRenderer", "()J",     (void*) android_view_GLES20Canvas_createDisplayListRenderer },
-    { "nResetDisplayListRenderer",  "(J)V",    (void*) android_view_GLES20Canvas_resetDisplayListRenderer },
 
     { "nInterrupt",              "(J)V",       (void*) android_view_GLES20Canvas_interrupt },
     { "nResume",                 "(J)V",       (void*) android_view_GLES20Canvas_resume },
diff --git a/core/jni/android_view_GLRenderer.cpp b/core/jni/android_view_GLRenderer.cpp
index 5c5b52c..5ea8460 100644
--- a/core/jni/android_view_GLRenderer.cpp
+++ b/core/jni/android_view_GLRenderer.cpp
@@ -27,6 +27,7 @@
 #include <utils/Timers.h>
 
 #include <Caches.h>
+#include <DisplayList.h>
 #include <Extensions.h>
 #include <LayerRenderer.h>
 
@@ -139,6 +140,14 @@
     LayerRenderer::destroyLayer(layer);
 }
 
+static void android_view_GLRenderer_swapDisplayListData(JNIEnv* env, jobject clazz,
+        jlong displayListPtr, jlong newDataPtr) {
+    using namespace android::uirenderer;
+    DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
+    DisplayListData* newData = reinterpret_cast<DisplayListData*>(newDataPtr);
+    displayList->setData(newData);
+}
+
 #endif // USE_OPENGL_RENDERER
 
 // ----------------------------------------------------------------------------
@@ -169,6 +178,7 @@
 
     { "getSystemTime",         "()J",   (void*) android_view_GLRenderer_getSystemTime },
     { "nDestroyLayer",         "(J)V",  (void*) android_view_GLRenderer_destroyLayer },
+    { "nSwapDisplayListData",  "(JJ)V", (void*) android_view_GLRenderer_swapDisplayListData },
 #endif
 
     { "setupShadersDiskCache", "(Ljava/lang/String;)V",
diff --git a/core/jni/android_view_HardwareLayer.cpp b/core/jni/android_view_HardwareLayer.cpp
index 8a0a011..5b21e94 100644
--- a/core/jni/android_view_HardwareLayer.cpp
+++ b/core/jni/android_view_HardwareLayer.cpp
@@ -88,13 +88,11 @@
 }
 
 static void android_view_HardwareLayer_setLayerPaint(JNIEnv* env, jobject clazz,
-        jlong layerUpdaterPtr, jlong paintPtr, jlong colorFilterPtr) {
+        jlong layerUpdaterPtr, jlong paintPtr) {
     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
     if (layer) {
         SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
-        SkColorFilter* colorFilter = reinterpret_cast<SkColorFilter*>(colorFilterPtr);
         layer->setPaint(paint);
-        layer->setColorFilter(colorFilter);
     }
 }
 
@@ -162,7 +160,7 @@
     { "nDestroyLayerUpdater",    "(J)V",       (void*) android_view_HardwareLayer_destroyLayerUpdater },
 
     { "nPrepare",                "(JIIZ)Z",    (void*) android_view_HardwareLayer_prepare },
-    { "nSetLayerPaint",          "(JJJ)V",     (void*) android_view_HardwareLayer_setLayerPaint },
+    { "nSetLayerPaint",          "(JJ)V",      (void*) android_view_HardwareLayer_setLayerPaint },
     { "nSetTransform",           "(JJ)V",      (void*) android_view_HardwareLayer_setTransform },
     { "nSetSurfaceTexture",      "(JLandroid/graphics/SurfaceTexture;Z)V",
             (void*) android_view_HardwareLayer_setSurfaceTexture },
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 480d0ac..c5ab284 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -61,54 +61,21 @@
 
 class ScreenshotPixelRef : public SkPixelRef {
 public:
-    ScreenshotPixelRef(SkColorTable* ctable) {
-        fCTable = ctable;
-        SkSafeRef(ctable);
+    ScreenshotPixelRef(const SkImageInfo& info, ScreenshotClient* screenshot) :
+      SkPixelRef(info),
+      mScreenshot(screenshot) {
         setImmutable();
     }
 
     virtual ~ScreenshotPixelRef() {
-        SkSafeUnref(fCTable);
-    }
-
-    status_t update(const sp<IBinder>& display, int width, int height,
-            int minLayer, int maxLayer, bool allLayers,
-            bool useIdentityTransform) {
-        status_t res = (width > 0 && height > 0)
-                ? (allLayers
-                        ? mScreenshot.update(display, width, height,
-                                useIdentityTransform)
-                        : mScreenshot.update(display, width, height,
-                                minLayer, maxLayer, useIdentityTransform))
-                : mScreenshot.update(display, useIdentityTransform);
-        if (res != NO_ERROR) {
-            return res;
-        }
-
-        return NO_ERROR;
-    }
-
-    uint32_t getWidth() const {
-        return mScreenshot.getWidth();
-    }
-
-    uint32_t getHeight() const {
-        return mScreenshot.getHeight();
-    }
-
-    uint32_t getStride() const {
-        return mScreenshot.getStride();
-    }
-
-    uint32_t getFormat() const {
-        return mScreenshot.getFormat();
+        delete mScreenshot;
     }
 
 protected:
     // overrides from SkPixelRef
     virtual void* onLockPixels(SkColorTable** ct) {
-        *ct = fCTable;
-        return (void*)mScreenshot.getPixels();
+        *ct = NULL;
+        return (void*)mScreenshot->getPixels();
     }
 
     virtual void onUnlockPixels() {
@@ -116,8 +83,7 @@
 
     SK_DECLARE_UNFLATTENABLE_OBJECT()
 private:
-    ScreenshotClient mScreenshot;
-    SkColorTable*    fCTable;
+    ScreenshotClient* mScreenshot;
 
     typedef SkPixelRef INHERITED;
 };
@@ -150,20 +116,6 @@
     ctrl->decStrong((void *)nativeCreate);
 }
 
-static inline SkBitmap::Config convertPixelFormat(PixelFormat format) {
-    /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
-        we can map to SkBitmap::kARGB_8888_Config, and optionally call
-        bitmap.setAlphaType(kOpaque_SkAlphaType) on the resulting SkBitmap
-        (as an accelerator)
-    */
-    switch (format) {
-    case PIXEL_FORMAT_RGBX_8888:    return SkBitmap::kARGB_8888_Config;
-    case PIXEL_FORMAT_RGBA_8888:    return SkBitmap::kARGB_8888_Config;
-    case PIXEL_FORMAT_RGB_565:      return SkBitmap::kRGB_565_Config;
-    default:                        return SkBitmap::kNo_Config;
-    }
-}
-
 static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, jobject displayTokenObj,
         jint width, jint height, jint minLayer, jint maxLayer, bool allLayers,
         bool useIdentityTransform) {
@@ -172,26 +124,57 @@
         return NULL;
     }
 
-    ScreenshotPixelRef* pixels = new ScreenshotPixelRef(NULL);
-    if (pixels->update(displayToken, width, height,
-            minLayer, maxLayer, allLayers, useIdentityTransform) != NO_ERROR) {
-        delete pixels;
+    ScreenshotClient* screenshot = new ScreenshotClient();
+    status_t res;
+    if (width > 0 && height > 0) {
+        if (allLayers) {
+            res = screenshot->update(displayToken, width, height, useIdentityTransform);
+        } else {
+            res = screenshot->update(displayToken, width, height, minLayer, maxLayer,
+                    useIdentityTransform);
+        }
+    } else {
+        res = screenshot->update(displayToken, useIdentityTransform);
+    }
+    if (res != NO_ERROR) {
+        delete screenshot;
         return NULL;
     }
 
-    uint32_t w = pixels->getWidth();
-    uint32_t h = pixels->getHeight();
-    uint32_t s = pixels->getStride();
-    uint32_t f = pixels->getFormat();
-    ssize_t bpr = s * android::bytesPerPixel(f);
+    SkImageInfo screenshotInfo;
+    screenshotInfo.fWidth = screenshot->getWidth();
+    screenshotInfo.fHeight = screenshot->getHeight();
 
-    SkBitmap* bitmap = new SkBitmap();
-    bitmap->setConfig(convertPixelFormat(f), w, h, bpr);
-    if (f == PIXEL_FORMAT_RGBX_8888) {
-        bitmap->setAlphaType(kOpaque_SkAlphaType);
+    switch (screenshot->getFormat()) {
+        case PIXEL_FORMAT_RGBX_8888: {
+            screenshotInfo.fColorType = kRGBA_8888_SkColorType;
+            screenshotInfo.fAlphaType = kIgnore_SkAlphaType;
+            break;
+        }
+        case PIXEL_FORMAT_RGBA_8888: {
+            screenshotInfo.fColorType = kRGBA_8888_SkColorType;
+            screenshotInfo.fAlphaType = kPremul_SkAlphaType;
+            break;
+        }
+        case PIXEL_FORMAT_RGB_565: {
+            screenshotInfo.fColorType = kRGB_565_SkColorType;
+            screenshotInfo.fAlphaType = kIgnore_SkAlphaType;
+            break;
+        }
+        default: {
+            delete screenshot;
+            return NULL;
+        }
     }
 
-    if (w > 0 && h > 0) {
+    // takes ownership of ScreenshotClient
+    ScreenshotPixelRef* pixels = new ScreenshotPixelRef(screenshotInfo, screenshot);
+    const ssize_t rowBytes =
+            screenshot->getStride() * android::bytesPerPixel(screenshot->getFormat());
+
+    SkBitmap* bitmap = new SkBitmap();
+    bitmap->setConfig(screenshotInfo, (size_t)rowBytes);
+    if (screenshotInfo.fWidth > 0 && screenshotInfo.fHeight > 0) {
         bitmap->setPixelRef(pixels)->unref();
         bitmap->lockPixels();
     } else {
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index bc5c06e..444c8be 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -103,6 +103,14 @@
     proxy->setup(width, height);
 }
 
+static void android_view_ThreadedRenderer_swapDisplayListData(JNIEnv* env, jobject clazz,
+        jlong proxyPtr, jlong displayListPtr, jlong newDataPtr) {
+    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+    DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
+    DisplayListData* newData = reinterpret_cast<DisplayListData*>(newDataPtr);
+    proxy->swapDisplayListData(displayList, newData);
+}
+
 static void android_view_ThreadedRenderer_drawDisplayList(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jlong displayListPtr, jint dirtyLeft, jint dirtyTop,
         jint dirtyRight, jint dirtyBottom) {
@@ -183,10 +191,11 @@
     { "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize },
     { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
     { "nSetup", "(JII)V", (void*) android_view_ThreadedRenderer_setup },
-    { "nDrawDisplayList", "(JJIIII)V", (void*) android_view_ThreadedRenderer_drawDisplayList},
-    { "nDestroyCanvas", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvas},
-    { "nAttachFunctor", "(JJ)V", (void*) android_view_ThreadedRenderer_attachFunctor},
-    { "nDetachFunctor", "(JJ)V", (void*) android_view_ThreadedRenderer_detachFunctor},
+    { "nSwapDisplayListData", "(JJJ)V", (void*) android_view_ThreadedRenderer_swapDisplayListData },
+    { "nDrawDisplayList", "(JJIIII)V", (void*) android_view_ThreadedRenderer_drawDisplayList },
+    { "nDestroyCanvas", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvas },
+    { "nAttachFunctor", "(JJ)V", (void*) android_view_ThreadedRenderer_attachFunctor },
+    { "nDetachFunctor", "(JJ)V", (void*) android_view_ThreadedRenderer_detachFunctor },
     { "nRunWithGlContext", "(JLjava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_runWithGlContext },
     { "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
     { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
index 0b9ad9b..c84a466 100644
--- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
+++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
@@ -37,6 +37,7 @@
 
 static struct {
     jfieldID size;
+    jfieldID capacity;
     jfieldID iface;
     jfieldID uid;
     jfieldID set;
@@ -49,7 +50,6 @@
 } gNetworkStatsClassInfo;
 
 struct stats_line {
-    int32_t idx;
     char iface[32];
     int32_t uid;
     int32_t set;
@@ -60,8 +60,41 @@
     int64_t txPackets;
 };
 
+static jobjectArray get_string_array(JNIEnv* env, jobject obj, jfieldID field, int size, bool grow)
+{
+    if (!grow) {
+        jobjectArray array = (jobjectArray)env->GetObjectField(obj, field);
+        if (array != NULL) {
+            return array;
+        }
+    }
+    return env->NewObjectArray(size, gStringClass, NULL);
+}
+
+static jintArray get_int_array(JNIEnv* env, jobject obj, jfieldID field, int size, bool grow)
+{
+    if (!grow) {
+        jintArray array = (jintArray)env->GetObjectField(obj, field);
+        if (array != NULL) {
+            return array;
+        }
+    }
+    return env->NewIntArray(size);
+}
+
+static jlongArray get_long_array(JNIEnv* env, jobject obj, jfieldID field, int size, bool grow)
+{
+    if (!grow) {
+        jlongArray array = (jlongArray)env->GetObjectField(obj, field);
+        if (array != NULL) {
+            return array;
+        }
+    }
+    return env->NewLongArray(size);
+}
+
 static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats,
-        jstring path, jint limitUid) {
+        jstring path, jint limitUid, jobjectArray limitIfacesObj, jint limitTag) {
     ScopedUtfChars path8(env, path);
     if (path8.c_str() == NULL) {
         return -1;
@@ -72,50 +105,146 @@
         return -1;
     }
 
+    Vector<String8> limitIfaces;
+    if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) {
+        int num = env->GetArrayLength(limitIfacesObj);
+        limitIfaces.setCapacity(num);
+        for (int i=0; i<num; i++) {
+            jstring string = (jstring)env->GetObjectArrayElement(limitIfacesObj, i);
+            ScopedUtfChars string8(env, string);
+            if (string8.c_str() != NULL) {
+                limitIfaces.add(String8(string8.c_str()));
+            }
+        }
+    }
+
     Vector<stats_line> lines;
 
     int lastIdx = 1;
+    int idx;
     char buffer[384];
     while (fgets(buffer, sizeof(buffer), fp) != NULL) {
         stats_line s;
         int64_t rawTag;
-        if (sscanf(buffer, "%d %31s 0x%llx %u %u %llu %llu %llu %llu", &s.idx,
-                s.iface, &rawTag, &s.uid, &s.set, &s.rxBytes, &s.rxPackets,
-                &s.txBytes, &s.txPackets) == 9) {
-            if (s.idx != lastIdx + 1) {
-                ALOGE("inconsistent idx=%d after lastIdx=%d", s.idx, lastIdx);
-                return -1;
+        char* pos = buffer;
+        char* endPos;
+        // First field is the index.
+        idx = (int)strtol(pos, &endPos, 10);
+        //ALOGI("Index #%d: %s", idx, buffer);
+        if (pos == endPos) {
+            // Skip lines that don't start with in index.  In particular,
+            // this will skip the initial header line.
+            continue;
+        }
+        if (idx != lastIdx + 1) {
+            ALOGE("inconsistent idx=%d after lastIdx=%d: %s", idx, lastIdx, buffer);
+            fclose(fp);
+            return -1;
+        }
+        lastIdx = idx;
+        pos = endPos;
+        // Skip whitespace.
+        while (*pos == ' ') {
+            pos++;
+        }
+        // Next field is iface.
+        int ifaceIdx = 0;
+        while (*pos != ' ' && *pos != 0 && ifaceIdx < (int)(sizeof(s.iface)-1)) {
+            s.iface[ifaceIdx] = *pos;
+            ifaceIdx++;
+            pos++;
+        }
+        if (*pos != ' ') {
+            ALOGE("bad iface: %s", buffer);
+            fclose(fp);
+            return -1;
+        }
+        s.iface[ifaceIdx] = 0;
+        if (limitIfaces.size() > 0) {
+            // Is this an iface the caller is interested in?
+            int i = 0;
+            while (i < (int)limitIfaces.size()) {
+                if (limitIfaces[i] == s.iface) {
+                    break;
+                }
+                i++;
             }
-            lastIdx = s.idx;
-
-            s.tag = rawTag >> 32;
+            if (i >= (int)limitIfaces.size()) {
+                // Nothing matched; skip this line.
+                //ALOGI("skipping due to iface: %s", buffer);
+                continue;
+            }
+        }
+        // Skip whitespace.
+        while (*pos == ' ') {
+            pos++;
+        }
+        // Next field is tag.
+        rawTag = strtoll(pos, &endPos, 16);
+        //ALOGI("Index #%d: %s", idx, buffer);
+        if (pos == endPos) {
+            ALOGE("bad tag: %s", pos);
+            fclose(fp);
+            return -1;
+        }
+        s.tag = rawTag >> 32;
+        if (limitTag != -1 && s.tag != limitTag) {
+            //ALOGI("skipping due to tag: %s", buffer);
+            continue;
+        }
+        pos = endPos;
+        // Skip whitespace.
+        while (*pos == ' ') {
+            pos++;
+        }
+        // Parse remaining fields.
+        if (sscanf(pos, "%u %u %llu %llu %llu %llu",
+                &s.uid, &s.set, &s.rxBytes, &s.rxPackets,
+                &s.txBytes, &s.txPackets) == 6) {
+            if (limitUid != -1 && limitUid != s.uid) {
+                //ALOGI("skipping due to uid: %s", buffer);
+                continue;
+            }
             lines.push_back(s);
+        } else {
+            //ALOGI("skipping due to bad remaining fields: %s", pos);
         }
     }
 
     if (fclose(fp) != 0) {
+        ALOGE("Failed to close netstats file");
         return -1;
     }
 
     int size = lines.size();
+    bool grow = size > env->GetIntField(stats, gNetworkStatsClassInfo.capacity);
 
-    ScopedLocalRef<jobjectArray> iface(env, env->NewObjectArray(size, gStringClass, NULL));
+    ScopedLocalRef<jobjectArray> iface(env, get_string_array(env, stats,
+            gNetworkStatsClassInfo.iface, size, grow));
     if (iface.get() == NULL) return -1;
-    ScopedIntArrayRW uid(env, env->NewIntArray(size));
+    ScopedIntArrayRW uid(env, get_int_array(env, stats,
+            gNetworkStatsClassInfo.uid, size, grow));
     if (uid.get() == NULL) return -1;
-    ScopedIntArrayRW set(env, env->NewIntArray(size));
+    ScopedIntArrayRW set(env, get_int_array(env, stats,
+            gNetworkStatsClassInfo.set, size, grow));
     if (set.get() == NULL) return -1;
-    ScopedIntArrayRW tag(env, env->NewIntArray(size));
+    ScopedIntArrayRW tag(env, get_int_array(env, stats,
+            gNetworkStatsClassInfo.tag, size, grow));
     if (tag.get() == NULL) return -1;
-    ScopedLongArrayRW rxBytes(env, env->NewLongArray(size));
+    ScopedLongArrayRW rxBytes(env, get_long_array(env, stats,
+            gNetworkStatsClassInfo.rxBytes, size, grow));
     if (rxBytes.get() == NULL) return -1;
-    ScopedLongArrayRW rxPackets(env, env->NewLongArray(size));
+    ScopedLongArrayRW rxPackets(env, get_long_array(env, stats,
+            gNetworkStatsClassInfo.rxPackets, size, grow));
     if (rxPackets.get() == NULL) return -1;
-    ScopedLongArrayRW txBytes(env, env->NewLongArray(size));
+    ScopedLongArrayRW txBytes(env, get_long_array(env, stats,
+            gNetworkStatsClassInfo.txBytes, size, grow));
     if (txBytes.get() == NULL) return -1;
-    ScopedLongArrayRW txPackets(env, env->NewLongArray(size));
+    ScopedLongArrayRW txPackets(env, get_long_array(env, stats,
+            gNetworkStatsClassInfo.txPackets, size, grow));
     if (txPackets.get() == NULL) return -1;
-    ScopedLongArrayRW operations(env, env->NewLongArray(size));
+    ScopedLongArrayRW operations(env, get_long_array(env, stats,
+            gNetworkStatsClassInfo.operations, size, grow));
     if (operations.get() == NULL) return -1;
 
     for (int i = 0; i < size; i++) {
@@ -132,15 +261,18 @@
     }
 
     env->SetIntField(stats, gNetworkStatsClassInfo.size, size);
-    env->SetObjectField(stats, gNetworkStatsClassInfo.iface, iface.get());
-    env->SetObjectField(stats, gNetworkStatsClassInfo.uid, uid.getJavaArray());
-    env->SetObjectField(stats, gNetworkStatsClassInfo.set, set.getJavaArray());
-    env->SetObjectField(stats, gNetworkStatsClassInfo.tag, tag.getJavaArray());
-    env->SetObjectField(stats, gNetworkStatsClassInfo.rxBytes, rxBytes.getJavaArray());
-    env->SetObjectField(stats, gNetworkStatsClassInfo.rxPackets, rxPackets.getJavaArray());
-    env->SetObjectField(stats, gNetworkStatsClassInfo.txBytes, txBytes.getJavaArray());
-    env->SetObjectField(stats, gNetworkStatsClassInfo.txPackets, txPackets.getJavaArray());
-    env->SetObjectField(stats, gNetworkStatsClassInfo.operations, operations.getJavaArray());
+    if (grow) {
+        env->SetIntField(stats, gNetworkStatsClassInfo.capacity, size);
+        env->SetObjectField(stats, gNetworkStatsClassInfo.iface, iface.get());
+        env->SetObjectField(stats, gNetworkStatsClassInfo.uid, uid.getJavaArray());
+        env->SetObjectField(stats, gNetworkStatsClassInfo.set, set.getJavaArray());
+        env->SetObjectField(stats, gNetworkStatsClassInfo.tag, tag.getJavaArray());
+        env->SetObjectField(stats, gNetworkStatsClassInfo.rxBytes, rxBytes.getJavaArray());
+        env->SetObjectField(stats, gNetworkStatsClassInfo.rxPackets, rxPackets.getJavaArray());
+        env->SetObjectField(stats, gNetworkStatsClassInfo.txBytes, txBytes.getJavaArray());
+        env->SetObjectField(stats, gNetworkStatsClassInfo.txPackets, txPackets.getJavaArray());
+        env->SetObjectField(stats, gNetworkStatsClassInfo.operations, operations.getJavaArray());
+    }
 
     return 0;
 }
@@ -157,7 +289,7 @@
 
 static JNINativeMethod gMethods[] = {
         { "nativeReadNetworkStatsDetail",
-                "(Landroid/net/NetworkStats;Ljava/lang/String;I)I",
+                "(Landroid/net/NetworkStats;Ljava/lang/String;I[Ljava/lang/String;I)I",
                 (void*) readNetworkStatsDetail }
 };
 
@@ -170,6 +302,7 @@
 
     jclass clazz = env->FindClass("android/net/NetworkStats");
     gNetworkStatsClassInfo.size = env->GetFieldID(clazz, "size", "I");
+    gNetworkStatsClassInfo.capacity = env->GetFieldID(clazz, "capacity", "I");
     gNetworkStatsClassInfo.iface = env->GetFieldID(clazz, "iface", "[Ljava/lang/String;");
     gNetworkStatsClassInfo.uid = env->GetFieldID(clazz, "uid", "[I");
     gNetworkStatsClassInfo.set = env->GetFieldID(clazz, "set", "[I");
diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
index 3035d15..3d421d5 100644
--- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
@@ -107,7 +107,7 @@
 
 static jint* beginNativeAttribList(JNIEnv *_env, jintArray attrib_list) {
     if (attrib_list != NULL) {
-        return (jint *)_env->GetPrimitiveArrayCritical(attrib_list, (jboolean *)0);
+        return _env->GetIntArrayElements(attrib_list, (jboolean *)0);
     } else {
         return(jint*) gNull_attrib_base;
     }
@@ -115,7 +115,7 @@
 
 static void endNativeAttributeList(JNIEnv *_env, jintArray attrib_list, jint* attrib_base) {
     if (attrib_list != NULL) {
-        _env->ReleasePrimitiveArrayCritical(attrib_list, attrib_base, JNI_ABORT);
+        _env->ReleaseIntArrayElements(attrib_list, attrib_base, JNI_ABORT);
     }
 }
 
@@ -154,9 +154,9 @@
     EGLBoolean success = EGL_FALSE;
     int len = _env->GetArrayLength(value);
     if (len) {
-        jint* base = (jint *)_env->GetPrimitiveArrayCritical(value, (jboolean *)0);
+        jint* base = _env->GetIntArrayElements(value, (jboolean *)0);
         success = eglQueryContext(dpy, ctx, attribute, base);
-        _env->ReleasePrimitiveArrayCritical(value, base, JNI_ABORT);
+        _env->ReleaseIntArrayElements(value, base, JNI_ABORT);
     }
     return EglBoolToJBool(success);
 }
@@ -174,9 +174,9 @@
     EGLBoolean success = EGL_FALSE;
     int len = _env->GetArrayLength(value);
     if (len) {
-        jint* base = (jint *)_env->GetPrimitiveArrayCritical(value, (jboolean *)0);
+        jint* base = _env->GetIntArrayElements(value, (jboolean *)0);
         success = eglQuerySurface(dpy, sur, attribute, base);
-        _env->ReleasePrimitiveArrayCritical(value, base, JNI_ABORT);
+        _env->ReleaseIntArrayElements(value, base, JNI_ABORT);
     }
     return EglBoolToJBool(success);
 }
diff --git a/core/jni/com_google_android_gles_jni_GLImpl.cpp b/core/jni/com_google_android_gles_jni_GLImpl.cpp
index b3b0049..7975987 100644
--- a/core/jni/com_google_android_gles_jni_GLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_GLImpl.cpp
@@ -129,7 +129,7 @@
             getBasePointerID, buffer);
     if (pointer != 0L) {
         *array = NULL;
-        return (void *) (jint) pointer;
+        return reinterpret_cast<void *>(pointer);
     }
 
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
@@ -4359,7 +4359,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -4460,7 +4460,7 @@
         (GLenum)mode,
         (GLsizei)count,
         (GLenum)type,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
     if (_exception) {
         jniThrowException(_env, _exceptionType, _exceptionMessage);
@@ -6099,7 +6099,7 @@
     glNormalPointer(
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -6326,7 +6326,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -6756,7 +6756,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -7196,7 +7196,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
@@ -7232,7 +7232,7 @@
         (GLint)size,
         (GLenum)type,
         (GLsizei)stride,
-        (GLvoid *)offset
+        reinterpret_cast<GLvoid *>(offset)
     );
 }
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 30e6161..4c0ddeb 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1071,8 +1071,9 @@
         android:permissionGroupFlags="personalInfo"
         android:priority="370" />
 
-    <!-- Allows an application to monitor, modify, or abort outgoing
-         calls. -->
+    <!-- Allows an application to see the number being dialed during an outgoing
+         call with the option to redirect the call to a different number or
+         abort the call altogether. -->
     <permission android:name="android.permission.PROCESS_OUTGOING_CALLS"
         android:permissionGroup="android.permission-group.PHONE_CALLS"
         android:protectionLevel="dangerous"
diff --git a/core/res/res/anim/swipe_window_enter.xml b/core/res/res/anim/swipe_window_enter.xml
new file mode 100644
index 0000000..e1617e2
--- /dev/null
+++ b/core/res/res/anim/swipe_window_enter.xml
@@ -0,0 +1,26 @@
+<?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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+        android:interpolator="@interpolator/decelerate_quad" >
+    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+        android:fillEnabled="true" android:fillBefore="true"
+        android:fillAfter="true"
+        android:duration="@android:integer/config_activityDefaultDur" />
+</set>
diff --git a/core/res/res/anim/swipe_window_exit.xml b/core/res/res/anim/swipe_window_exit.xml
new file mode 100644
index 0000000..ed0c5d3
--- /dev/null
+++ b/core/res/res/anim/swipe_window_exit.xml
@@ -0,0 +1,26 @@
+<?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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+        android:interpolator="@interpolator/decelerate_quad" >
+    <translate android:fromXDelta="0%" android:toXDelta="100%"
+        android:fillEnabled="true" android:fillBefore="true"
+        android:fillAfter="true"
+        android:duration="400" />
+</set>
diff --git a/core/res/res/color/primary_text_disable_only_quantum_dark.xml b/core/res/res/color/primary_text_disable_only_quantum_dark.xml
index 2a6c33c..60a91f2 100644
--- a/core/res/res/color/primary_text_disable_only_quantum_dark.xml
+++ b/core/res/res/color/primary_text_disable_only_quantum_dark.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<!-- Copyright (C) 2014 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.
@@ -15,6 +15,6 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false" android:color="@android:color/bright_foreground_dark_disabled"/>
-    <item android:color="@android:color/bright_foreground_dark"/>
+    <item android:state_enabled="false" android:alpha="0.5" android:color="@android:color/bright_foreground_quantum_dark"/>
+    <item android:color="@android:color/bright_foreground_quantum_dark"/>
 </selector>
diff --git a/core/res/res/color/primary_text_disable_only_quantum_light.xml b/core/res/res/color/primary_text_disable_only_quantum_light.xml
index ff83f6a..ced9051 100644
--- a/core/res/res/color/primary_text_disable_only_quantum_light.xml
+++ b/core/res/res/color/primary_text_disable_only_quantum_light.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<!-- Copyright (C) 2014 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.
@@ -15,6 +15,6 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false" android:color="@android:color/bright_foreground_light_disabled"/>
-    <item android:color="@android:color/bright_foreground_light"/>
+    <item android:state_enabled="false" android:alpha="0.5" android:color="@android:color/bright_foreground_quantum_light"/>
+    <item android:color="@android:color/bright_foreground_quantum_light"/>
 </selector>
diff --git a/core/res/res/color/primary_text_nodisable_quantum_dark.xml b/core/res/res/color/primary_text_nodisable_quantum_dark.xml
deleted file mode 100644
index 1044428..0000000
--- a/core/res/res/color/primary_text_nodisable_quantum_dark.xml
+++ /dev/null
@@ -1,21 +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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_selected="true" android:color="@android:color/bright_foreground_dark_inverse"/>
-    <item android:state_activated="true" android:color="@android:color/bright_foreground_dark_inverse"/>
-    <item android:color="@android:color/bright_foreground_dark"/>
-</selector>
diff --git a/core/res/res/color/primary_text_nodisable_quantum_light.xml b/core/res/res/color/primary_text_nodisable_quantum_light.xml
deleted file mode 100644
index fde143f..0000000
--- a/core/res/res/color/primary_text_nodisable_quantum_light.xml
+++ /dev/null
@@ -1,21 +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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_selected="true" android:color="@android:color/bright_foreground_light"/>
-    <item android:state_activated="true" android:color="@android:color/bright_foreground_light"/>
-    <item android:color="@android:color/bright_foreground_light"/>
-</selector>
diff --git a/core/res/res/color/primary_text_quantum_dark.xml b/core/res/res/color/primary_text_quantum_dark.xml
deleted file mode 100644
index 65f49ae..0000000
--- a/core/res/res/color/primary_text_quantum_dark.xml
+++ /dev/null
@@ -1,24 +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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false" android:color="@android:color/bright_foreground_disabled_holo_dark"/>
-    <item android:state_window_focused="false" android:color="@android:color/bright_foreground_holo_dark"/>
-    <item android:state_pressed="true" android:color="@android:color/bright_foreground_holo_dark"/>
-    <item android:state_selected="true" android:color="@android:color/bright_foreground_holo_dark"/>
-    <item android:state_activated="true" android:color="@android:color/bright_foreground_holo_dark"/>
-    <item android:color="@android:color/bright_foreground_holo_dark"/>
-</selector>
diff --git a/core/res/res/color/primary_text_quantum_light.xml b/core/res/res/color/primary_text_quantum_light.xml
deleted file mode 100644
index 372745d..0000000
--- a/core/res/res/color/primary_text_quantum_light.xml
+++ /dev/null
@@ -1,24 +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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false" android:color="@android:color/bright_foreground_disabled_holo_light"/>
-    <item android:state_window_focused="false" android:color="@android:color/bright_foreground_holo_light"/>
-    <item android:state_pressed="true" android:color="@android:color/bright_foreground_holo_light"/>
-    <item android:state_selected="true" android:color="@android:color/bright_foreground_holo_light"/>
-    <item android:state_activated="true" android:color="@android:color/bright_foreground_holo_light"/>
-    <item android:color="@android:color/bright_foreground_holo_light"/>
-</selector>
diff --git a/core/res/res/color/search_url_text_quantum_dark.xml b/core/res/res/color/search_url_text_quantum_dark.xml
index 62337bd..5263fd7 100644
--- a/core/res/res/color/search_url_text_quantum_dark.xml
+++ b/core/res/res/color/search_url_text_quantum_dark.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<!-- Copyright (C) 2014 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.
diff --git a/core/res/res/color/search_url_text_quantum_light.xml b/core/res/res/color/search_url_text_quantum_light.xml
index 62337bd..5263fd7 100644
--- a/core/res/res/color/search_url_text_quantum_light.xml
+++ b/core/res/res/color/search_url_text_quantum_light.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<!-- Copyright (C) 2014 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.
diff --git a/core/res/res/color/secondary_text_nodisable_quantum_dark.xml b/core/res/res/color/secondary_text_nodisable_quantum_dark.xml
deleted file mode 100644
index 3ab25a0..0000000
--- a/core/res/res/color/secondary_text_nodisable_quantum_dark.xml
+++ /dev/null
@@ -1,21 +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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_selected="true" android:color="@android:color/dim_foreground_dark_inverse"/>
-    <item android:state_activated="true" android:color="@android:color/bright_foreground_dark_inverse"/>
-    <item android:color="@android:color/dim_foreground_dark"/>
-</selector>
diff --git a/core/res/res/color/secondary_text_nodisable_quantum_light.xml b/core/res/res/color/secondary_text_nodisable_quantum_light.xml
deleted file mode 100644
index 3ab25a0..0000000
--- a/core/res/res/color/secondary_text_nodisable_quantum_light.xml
+++ /dev/null
@@ -1,21 +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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_selected="true" android:color="@android:color/dim_foreground_dark_inverse"/>
-    <item android:state_activated="true" android:color="@android:color/bright_foreground_dark_inverse"/>
-    <item android:color="@android:color/dim_foreground_dark"/>
-</selector>
diff --git a/core/res/res/color/secondary_text_quantum_dark.xml b/core/res/res/color/secondary_text_quantum_dark.xml
deleted file mode 100644
index fb7a07a..0000000
--- a/core/res/res/color/secondary_text_quantum_dark.xml
+++ /dev/null
@@ -1,27 +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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_window_focused="false" android:state_enabled="false" android:color="@android:color/dim_foreground_disabled_holo_dark"/>
-    <item android:state_window_focused="false" android:color="@android:color/dim_foreground_holo_dark"/>
-    <item android:state_selected="true" android:state_enabled="false" android:color="@android:color/dim_foreground_disabled_holo_dark"/>
-    <item android:state_pressed="true" android:state_enabled="false" android:color="@android:color/dim_foreground_disabled_holo_dark"/>
-    <item android:state_selected="true" android:color="@android:color/dim_foreground_holo_dark"/>
-    <item android:state_activated="true" android:color="@android:color/bright_foreground_holo_dark"/>
-    <item android:state_pressed="true" android:color="@android:color/dim_foreground_holo_dark"/>
-    <item android:state_enabled="false" android:color="@android:color/dim_foreground_disabled_holo_dark"/>
-    <item android:color="@android:color/dim_foreground_holo_dark"/>
-</selector>
diff --git a/core/res/res/color/secondary_text_quantum_light.xml b/core/res/res/color/secondary_text_quantum_light.xml
deleted file mode 100644
index 744ace5..0000000
--- a/core/res/res/color/secondary_text_quantum_light.xml
+++ /dev/null
@@ -1,28 +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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_window_focused="false" android:state_enabled="false" android:color="@android:color/dim_foreground_disabled_holo_light"/>
-    <item android:state_window_focused="false" android:color="@android:color/dim_foreground_holo_light"/>
-    <!-- Since there is only one selector (for both light and dark), the light's selected state shouldn't be inversed like the dark's. -->
-    <item android:state_pressed="true" android:state_enabled="false" android:color="@android:color/dim_foreground_disabled_holo_light"/>
-    <item android:state_selected="true" android:state_enabled="false" android:color="@android:color/dim_foreground_disabled_holo_light"/>
-    <item android:state_pressed="true" android:color="@android:color/dim_foreground_holo_light"/>
-    <item android:state_selected="true" android:color="@android:color/dim_foreground_holo_light"/>
-    <item android:state_activated="true" android:color="@android:color/bright_foreground_holo_light"/>
-    <item android:state_enabled="false" android:color="@android:color/dim_foreground_disabled_holo_light"/>
-    <item android:color="@android:color/dim_foreground_holo_light"/>
-</selector>
diff --git a/core/res/res/color/tertiary_text_quantum_dark.xml b/core/res/res/color/tertiary_text_quantum_dark.xml
deleted file mode 100644
index cb39565..0000000
--- a/core/res/res/color/tertiary_text_quantum_dark.xml
+++ /dev/null
@@ -1,23 +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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false" android:color="#808080"/>
-    <item android:state_window_focused="false" android:color="#808080"/>
-    <item android:state_pressed="true" android:color="#808080"/>
-    <item android:state_selected="true" android:color="@android:color/dim_foreground_holo_light"/>
-    <item android:color="#808080"/>
-</selector>
diff --git a/core/res/res/color/tertiary_text_quantum_light.xml b/core/res/res/color/tertiary_text_quantum_light.xml
deleted file mode 100644
index b23162a..0000000
--- a/core/res/res/color/tertiary_text_quantum_light.xml
+++ /dev/null
@@ -1,23 +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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false" android:color="#808080"/>
-    <item android:state_window_focused="false" android:color="#808080"/>
-    <item android:state_pressed="true" android:color="#808080"/>
-    <item android:state_selected="true" android:color="#808080"/>
-    <item android:color="#808080"/>
-</selector>
diff --git a/core/res/res/drawable-hdpi/ab_solid_shadow_qntm.9.png b/core/res/res/drawable-hdpi/ab_solid_shadow_qntm.9.png
new file mode 100644
index 0000000..717ec1a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_solid_shadow_qntm.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_transparent_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_transparent_qntm_alpha.9.png
new file mode 100644
index 0000000..5fa4ec4
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_off_qntm_alpha.png
new file mode 100644
index 0000000..5bc1d90
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_on_qntm_alpha.png
new file mode 100644
index 0000000..e5de2c1
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_qntm_alpha.9.png b/core/res/res/drawable-hdpi/btn_qntm_alpha.9.png
new file mode 100644
index 0000000..171688f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_pressed_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_off_pressed_qntm_alpha.png
new file mode 100644
index 0000000..7bef530
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_off_pressed_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_off_qntm_alpha.png
new file mode 100644
index 0000000..ae50dd5
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_pressed_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_on_pressed_qntm_alpha.png
new file mode 100644
index 0000000..0678dbb
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_on_pressed_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_on_qntm_alpha.png
new file mode 100644
index 0000000..f332925
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_star_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_star_qntm_alpha.png
new file mode 100644
index 0000000..e11896f6
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_star_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/expander_close_qntm_alpha.9.png b/core/res/res/drawable-hdpi/expander_close_qntm_alpha.9.png
new file mode 100644
index 0000000..7bf9d90
--- /dev/null
+++ b/core/res/res/drawable-hdpi/expander_close_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/expander_open_qntm_alpha.9.png b/core/res/res/drawable-hdpi/expander_open_qntm_alpha.9.png
new file mode 100644
index 0000000..d427a20
--- /dev/null
+++ b/core/res/res/drawable-hdpi/expander_open_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/fastscroll_thumb_qntm_alpha.png b/core/res/res/drawable-hdpi/fastscroll_thumb_qntm_alpha.png
new file mode 100644
index 0000000..2000422d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/fastscroll_thumb_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/fastscroll_track_qntm_alpha.9.png b/core/res/res/drawable-hdpi/fastscroll_track_qntm_alpha.9.png
new file mode 100644
index 0000000..61ef6f6
--- /dev/null
+++ b/core/res/res/drawable-hdpi/fastscroll_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_ab_back_qntm_am_alpha.png b/core/res/res/drawable-hdpi/ic_ab_back_qntm_am_alpha.png
new file mode 100644
index 0000000..f0910d8
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_ab_back_qntm_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_cab_done_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_cab_done_qntm_alpha.png
new file mode 100644
index 0000000..5635459
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_cab_done_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_dialog_alert_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_dialog_alert_qntm_alpha.png
new file mode 100644
index 0000000..95cfb32
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_dialog_alert_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_find_next_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_find_next_qntm_alpha.png
new file mode 100644
index 0000000..6d5edac
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_find_next_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_find_previous_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_find_previous_qntm_alpha.png
new file mode 100644
index 0000000..a5921af
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_find_previous_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_copy_qntm_am_alpha.png b/core/res/res/drawable-hdpi/ic_menu_copy_qntm_am_alpha.png
new file mode 100644
index 0000000..d6d1f2f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_menu_copy_qntm_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_cut_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_menu_cut_qntm_alpha.png
new file mode 100644
index 0000000..ec8db6f6
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_menu_cut_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_find_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_menu_find_qntm_alpha.png
new file mode 100644
index 0000000..0f9d41f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_menu_find_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_moreoverflow_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_qntm_alpha.png
new file mode 100644
index 0000000..1ba1295
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_menu_moreoverflow_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_paste_qntm_am_alpha.png b/core/res/res/drawable-hdpi/ic_menu_paste_qntm_am_alpha.png
new file mode 100644
index 0000000..bf44722
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_menu_paste_qntm_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_search_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_menu_search_qntm_alpha.png
new file mode 100644
index 0000000..a0501b3
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_menu_search_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_selectall_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_menu_selectall_qntm_alpha.png
new file mode 100644
index 0000000..8539741
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_menu_selectall_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_menu_share_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_menu_share_qntm_alpha.png
new file mode 100644
index 0000000..0eacedd
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_menu_share_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_divider_qntm_alpha.9.png b/core/res/res/drawable-hdpi/list_divider_qntm_alpha.9.png
new file mode 100644
index 0000000..77845df
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_divider_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_section_divider_qntm_alpha.9.png b/core/res/res/drawable-hdpi/list_section_divider_qntm_alpha.9.png
new file mode 100644
index 0000000..20baf2a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_section_divider_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progress_primary_qntm_alpha.9.png b/core/res/res/drawable-hdpi/progress_primary_qntm_alpha.9.png
new file mode 100644
index 0000000..a278ed7
--- /dev/null
+++ b/core/res/res/drawable-hdpi/progress_primary_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progress_qntm_alpha.9.png b/core/res/res/drawable-hdpi/progress_qntm_alpha.9.png
new file mode 100644
index 0000000..b11de9e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/progress_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrollbar_handle_qntm_alpha.9.png b/core/res/res/drawable-hdpi/scrollbar_handle_qntm_alpha.9.png
new file mode 100644
index 0000000..a5166f2
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrollbar_handle_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_off_pressed_qntm_alpha.png b/core/res/res/drawable-hdpi/scrubber_control_off_pressed_qntm_alpha.png
new file mode 100644
index 0000000..10ce2bc
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_control_off_pressed_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_off_qntm_alpha.png b/core/res/res/drawable-hdpi/scrubber_control_off_qntm_alpha.png
new file mode 100644
index 0000000..f1023ea
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_control_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_on_pressed_qntm_alpha.png b/core/res/res/drawable-hdpi/scrubber_control_on_pressed_qntm_alpha.png
new file mode 100644
index 0000000..0678dbb
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_control_on_pressed_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_on_qntm_alpha.png b/core/res/res/drawable-hdpi/scrubber_control_on_qntm_alpha.png
new file mode 100644
index 0000000..15ceeee
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_control_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_primary_qntm_alpha.9.png b/core/res/res/drawable-hdpi/scrubber_primary_qntm_alpha.9.png
new file mode 100644
index 0000000..4cfb1a7
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_primary_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_qntm_am_alpha.9.png b/core/res/res/drawable-hdpi/spinner_qntm_am_alpha.9.png
new file mode 100644
index 0000000..66673d3
--- /dev/null
+++ b/core/res/res/drawable-hdpi/spinner_qntm_am_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_off_qntm_alpha.9.png b/core/res/res/drawable-hdpi/switch_off_qntm_alpha.9.png
new file mode 100644
index 0000000..90b1498
--- /dev/null
+++ b/core/res/res/drawable-hdpi/switch_off_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_on_qntm_alpha.9.png b/core/res/res/drawable-hdpi/switch_on_qntm_alpha.9.png
new file mode 100644
index 0000000..b535758
--- /dev/null
+++ b/core/res/res/drawable-hdpi/switch_on_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_track_qntm_alpha.9.png b/core/res/res/drawable-hdpi/switch_track_qntm_alpha.9.png
new file mode 100644
index 0000000..b11de9e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/switch_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_indicator_normal_qntm_alpha.9.png b/core/res/res/drawable-hdpi/tab_indicator_normal_qntm_alpha.9.png
new file mode 100644
index 0000000..233d409
--- /dev/null
+++ b/core/res/res/drawable-hdpi/tab_indicator_normal_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_indicator_selected_qntm_alpha.9.png b/core/res/res/drawable-hdpi/tab_indicator_selected_qntm_alpha.9.png
new file mode 100644
index 0000000..68b1dd7
--- /dev/null
+++ b/core/res/res/drawable-hdpi/tab_indicator_selected_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_cursor_qntm_alpha.9.png b/core/res/res/drawable-hdpi/text_cursor_qntm_alpha.9.png
new file mode 100644
index 0000000..0179433
--- /dev/null
+++ b/core/res/res/drawable-hdpi/text_cursor_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_activated_qntm_alpha.9.png b/core/res/res/drawable-hdpi/textfield_activated_qntm_alpha.9.png
new file mode 100644
index 0000000..7c77a45
--- /dev/null
+++ b/core/res/res/drawable-hdpi/textfield_activated_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_default_qntm_alpha.9.png b/core/res/res/drawable-hdpi/textfield_default_qntm_alpha.9.png
new file mode 100644
index 0000000..bc6da21
--- /dev/null
+++ b/core/res/res/drawable-hdpi/textfield_default_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ab_solid_shadow_qntm.9.png b/core/res/res/drawable-ldpi/ab_solid_shadow_qntm.9.png
new file mode 100644
index 0000000..098a315
--- /dev/null
+++ b/core/res/res/drawable-ldpi/ab_solid_shadow_qntm.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ab_transparent_qntm_alpha.9.png b/core/res/res/drawable-ldpi/ab_transparent_qntm_alpha.9.png
new file mode 100644
index 0000000..4d4cb4f
--- /dev/null
+++ b/core/res/res/drawable-ldpi/ab_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_check_off_qntm_alpha.png b/core/res/res/drawable-ldpi/btn_check_off_qntm_alpha.png
new file mode 100644
index 0000000..fbe176f
--- /dev/null
+++ b/core/res/res/drawable-ldpi/btn_check_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_check_on_qntm_alpha.png b/core/res/res/drawable-ldpi/btn_check_on_qntm_alpha.png
new file mode 100644
index 0000000..5fd18e5
--- /dev/null
+++ b/core/res/res/drawable-ldpi/btn_check_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_qntm_alpha.9.png b/core/res/res/drawable-ldpi/btn_qntm_alpha.9.png
new file mode 100644
index 0000000..1b648db
--- /dev/null
+++ b/core/res/res/drawable-ldpi/btn_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_radio_off_pressed_qntm_alpha.png b/core/res/res/drawable-ldpi/btn_radio_off_pressed_qntm_alpha.png
new file mode 100644
index 0000000..ac27576
--- /dev/null
+++ b/core/res/res/drawable-ldpi/btn_radio_off_pressed_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_radio_off_qntm_alpha.png b/core/res/res/drawable-ldpi/btn_radio_off_qntm_alpha.png
new file mode 100644
index 0000000..d17081f
--- /dev/null
+++ b/core/res/res/drawable-ldpi/btn_radio_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_radio_on_pressed_qntm_alpha.png b/core/res/res/drawable-ldpi/btn_radio_on_pressed_qntm_alpha.png
new file mode 100644
index 0000000..458abaf
--- /dev/null
+++ b/core/res/res/drawable-ldpi/btn_radio_on_pressed_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_radio_on_qntm_alpha.png b/core/res/res/drawable-ldpi/btn_radio_on_qntm_alpha.png
new file mode 100644
index 0000000..f31d37f
--- /dev/null
+++ b/core/res/res/drawable-ldpi/btn_radio_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/btn_star_qntm_alpha.png b/core/res/res/drawable-ldpi/btn_star_qntm_alpha.png
new file mode 100644
index 0000000..ae665fd
--- /dev/null
+++ b/core/res/res/drawable-ldpi/btn_star_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/expander_close_qntm_alpha.9.png b/core/res/res/drawable-ldpi/expander_close_qntm_alpha.9.png
new file mode 100644
index 0000000..19ac6f5
--- /dev/null
+++ b/core/res/res/drawable-ldpi/expander_close_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/expander_open_qntm_alpha.9.png b/core/res/res/drawable-ldpi/expander_open_qntm_alpha.9.png
new file mode 100644
index 0000000..e51f018
--- /dev/null
+++ b/core/res/res/drawable-ldpi/expander_open_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/fastscroll_thumb_qntm_alpha.png b/core/res/res/drawable-ldpi/fastscroll_thumb_qntm_alpha.png
new file mode 100644
index 0000000..c901730
--- /dev/null
+++ b/core/res/res/drawable-ldpi/fastscroll_thumb_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/fastscroll_track_qntm_alpha.9.png b/core/res/res/drawable-ldpi/fastscroll_track_qntm_alpha.9.png
new file mode 100644
index 0000000..833dac9
--- /dev/null
+++ b/core/res/res/drawable-ldpi/fastscroll_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_ab_back_qntm_am_alpha.png b/core/res/res/drawable-ldpi/ic_ab_back_qntm_am_alpha.png
new file mode 100644
index 0000000..96e86b6
--- /dev/null
+++ b/core/res/res/drawable-ldpi/ic_ab_back_qntm_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_cab_done_qntm_alpha.png b/core/res/res/drawable-ldpi/ic_cab_done_qntm_alpha.png
new file mode 100644
index 0000000..8ee0546
--- /dev/null
+++ b/core/res/res/drawable-ldpi/ic_cab_done_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_dialog_alert_qntm_alpha.png b/core/res/res/drawable-ldpi/ic_dialog_alert_qntm_alpha.png
new file mode 100644
index 0000000..f604e8b
--- /dev/null
+++ b/core/res/res/drawable-ldpi/ic_dialog_alert_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_find_next_qntm_alpha.png b/core/res/res/drawable-ldpi/ic_find_next_qntm_alpha.png
new file mode 100644
index 0000000..dd6fe20
--- /dev/null
+++ b/core/res/res/drawable-ldpi/ic_find_next_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_find_previous_qntm_alpha.png b/core/res/res/drawable-ldpi/ic_find_previous_qntm_alpha.png
new file mode 100644
index 0000000..d4598ba
--- /dev/null
+++ b/core/res/res/drawable-ldpi/ic_find_previous_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_copy_qntm_am_alpha.png b/core/res/res/drawable-ldpi/ic_menu_copy_qntm_am_alpha.png
new file mode 100644
index 0000000..565280b
--- /dev/null
+++ b/core/res/res/drawable-ldpi/ic_menu_copy_qntm_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_cut_qntm_alpha.png b/core/res/res/drawable-ldpi/ic_menu_cut_qntm_alpha.png
new file mode 100644
index 0000000..dbedece
--- /dev/null
+++ b/core/res/res/drawable-ldpi/ic_menu_cut_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_find_qntm_alpha.png b/core/res/res/drawable-ldpi/ic_menu_find_qntm_alpha.png
new file mode 100644
index 0000000..c828577
--- /dev/null
+++ b/core/res/res/drawable-ldpi/ic_menu_find_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_moreoverflow_qntm_alpha.png b/core/res/res/drawable-ldpi/ic_menu_moreoverflow_qntm_alpha.png
new file mode 100644
index 0000000..d47f81e
--- /dev/null
+++ b/core/res/res/drawable-ldpi/ic_menu_moreoverflow_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_paste_qntm_am_alpha.png b/core/res/res/drawable-ldpi/ic_menu_paste_qntm_am_alpha.png
new file mode 100644
index 0000000..430141b
--- /dev/null
+++ b/core/res/res/drawable-ldpi/ic_menu_paste_qntm_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_search_qntm_alpha.png b/core/res/res/drawable-ldpi/ic_menu_search_qntm_alpha.png
new file mode 100644
index 0000000..ec759fb
--- /dev/null
+++ b/core/res/res/drawable-ldpi/ic_menu_search_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_selectall_qntm_alpha.png b/core/res/res/drawable-ldpi/ic_menu_selectall_qntm_alpha.png
new file mode 100644
index 0000000..7b520bc
--- /dev/null
+++ b/core/res/res/drawable-ldpi/ic_menu_selectall_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_share_qntm_alpha.png b/core/res/res/drawable-ldpi/ic_menu_share_qntm_alpha.png
new file mode 100644
index 0000000..db1e146
--- /dev/null
+++ b/core/res/res/drawable-ldpi/ic_menu_share_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/list_divider_qntm_alpha.9.png b/core/res/res/drawable-ldpi/list_divider_qntm_alpha.9.png
new file mode 100644
index 0000000..77845df
--- /dev/null
+++ b/core/res/res/drawable-ldpi/list_divider_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/list_section_divider_qntm_alpha.9.png b/core/res/res/drawable-ldpi/list_section_divider_qntm_alpha.9.png
new file mode 100644
index 0000000..f1a0362
--- /dev/null
+++ b/core/res/res/drawable-ldpi/list_section_divider_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/progress_primary_qntm_alpha.9.png b/core/res/res/drawable-ldpi/progress_primary_qntm_alpha.9.png
new file mode 100644
index 0000000..eb0933b
--- /dev/null
+++ b/core/res/res/drawable-ldpi/progress_primary_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/progress_qntm_alpha.9.png b/core/res/res/drawable-ldpi/progress_qntm_alpha.9.png
new file mode 100644
index 0000000..a58128f
--- /dev/null
+++ b/core/res/res/drawable-ldpi/progress_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/scrollbar_handle_qntm_alpha.9.png b/core/res/res/drawable-ldpi/scrollbar_handle_qntm_alpha.9.png
new file mode 100644
index 0000000..3e301ef
--- /dev/null
+++ b/core/res/res/drawable-ldpi/scrollbar_handle_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/scrubber_control_off_pressed_qntm_alpha.png b/core/res/res/drawable-ldpi/scrubber_control_off_pressed_qntm_alpha.png
new file mode 100644
index 0000000..df88c4e
--- /dev/null
+++ b/core/res/res/drawable-ldpi/scrubber_control_off_pressed_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/scrubber_control_off_qntm_alpha.png b/core/res/res/drawable-ldpi/scrubber_control_off_qntm_alpha.png
new file mode 100644
index 0000000..bf6ce6c
--- /dev/null
+++ b/core/res/res/drawable-ldpi/scrubber_control_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/scrubber_control_on_pressed_qntm_alpha.png b/core/res/res/drawable-ldpi/scrubber_control_on_pressed_qntm_alpha.png
new file mode 100644
index 0000000..458abaf
--- /dev/null
+++ b/core/res/res/drawable-ldpi/scrubber_control_on_pressed_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/scrubber_control_on_qntm_alpha.png b/core/res/res/drawable-ldpi/scrubber_control_on_qntm_alpha.png
new file mode 100644
index 0000000..85a06b9
--- /dev/null
+++ b/core/res/res/drawable-ldpi/scrubber_control_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/scrubber_primary_qntm_alpha.9.png b/core/res/res/drawable-ldpi/scrubber_primary_qntm_alpha.9.png
new file mode 100644
index 0000000..6f99790
--- /dev/null
+++ b/core/res/res/drawable-ldpi/scrubber_primary_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/spinner_qntm_am_alpha.9.png b/core/res/res/drawable-ldpi/spinner_qntm_am_alpha.9.png
new file mode 100644
index 0000000..368a9b0
--- /dev/null
+++ b/core/res/res/drawable-ldpi/spinner_qntm_am_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/switch_off_qntm_alpha.9.png b/core/res/res/drawable-ldpi/switch_off_qntm_alpha.9.png
new file mode 100644
index 0000000..9cd2df3
--- /dev/null
+++ b/core/res/res/drawable-ldpi/switch_off_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/switch_on_qntm_alpha.9.png b/core/res/res/drawable-ldpi/switch_on_qntm_alpha.9.png
new file mode 100644
index 0000000..f9b287a
--- /dev/null
+++ b/core/res/res/drawable-ldpi/switch_on_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/switch_track_qntm_alpha.9.png b/core/res/res/drawable-ldpi/switch_track_qntm_alpha.9.png
new file mode 100644
index 0000000..a58128f
--- /dev/null
+++ b/core/res/res/drawable-ldpi/switch_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/tab_indicator_normal_qntm_alpha.9.png b/core/res/res/drawable-ldpi/tab_indicator_normal_qntm_alpha.9.png
new file mode 100644
index 0000000..2244362
--- /dev/null
+++ b/core/res/res/drawable-ldpi/tab_indicator_normal_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/tab_indicator_selected_qntm_alpha.9.png b/core/res/res/drawable-ldpi/tab_indicator_selected_qntm_alpha.9.png
new file mode 100644
index 0000000..22ea80e
--- /dev/null
+++ b/core/res/res/drawable-ldpi/tab_indicator_selected_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/text_cursor_qntm_alpha.9.png b/core/res/res/drawable-ldpi/text_cursor_qntm_alpha.9.png
new file mode 100644
index 0000000..4aaa79f
--- /dev/null
+++ b/core/res/res/drawable-ldpi/text_cursor_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/textfield_activated_qntm_alpha.9.png b/core/res/res/drawable-ldpi/textfield_activated_qntm_alpha.9.png
new file mode 100644
index 0000000..d12ec06
--- /dev/null
+++ b/core/res/res/drawable-ldpi/textfield_activated_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/textfield_default_qntm_alpha.9.png b/core/res/res/drawable-ldpi/textfield_default_qntm_alpha.9.png
new file mode 100644
index 0000000..6f0c57f
--- /dev/null
+++ b/core/res/res/drawable-ldpi/textfield_default_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_solid_shadow_qntm.9.png b/core/res/res/drawable-mdpi/ab_solid_shadow_qntm.9.png
new file mode 100644
index 0000000..c00c545
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_solid_shadow_qntm.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_transparent_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_transparent_qntm_alpha.9.png
new file mode 100644
index 0000000..2e42386
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_off_qntm_alpha.png
new file mode 100644
index 0000000..2ab6b7f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_on_qntm_alpha.png
new file mode 100644
index 0000000..2211d83
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_qntm_alpha.9.png b/core/res/res/drawable-mdpi/btn_qntm_alpha.9.png
new file mode 100644
index 0000000..fc51595
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_pressed_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_off_pressed_qntm_alpha.png
new file mode 100644
index 0000000..713fee8
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_off_pressed_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_off_qntm_alpha.png
new file mode 100644
index 0000000..dcb90d0
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_pressed_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_on_pressed_qntm_alpha.png
new file mode 100644
index 0000000..3c304bf
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_on_pressed_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_on_qntm_alpha.png
new file mode 100644
index 0000000..04a8edb
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_star_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_star_qntm_alpha.png
new file mode 100644
index 0000000..7ce950d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_star_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/expander_close_qntm_alpha.9.png b/core/res/res/drawable-mdpi/expander_close_qntm_alpha.9.png
new file mode 100644
index 0000000..6070397
--- /dev/null
+++ b/core/res/res/drawable-mdpi/expander_close_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/expander_open_qntm_alpha.9.png b/core/res/res/drawable-mdpi/expander_open_qntm_alpha.9.png
new file mode 100644
index 0000000..29a3a1a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/expander_open_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/fastscroll_thumb_qntm_alpha.png b/core/res/res/drawable-mdpi/fastscroll_thumb_qntm_alpha.png
new file mode 100644
index 0000000..4984f9c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/fastscroll_thumb_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/fastscroll_track_qntm_alpha.9.png b/core/res/res/drawable-mdpi/fastscroll_track_qntm_alpha.9.png
new file mode 100644
index 0000000..4041808
--- /dev/null
+++ b/core/res/res/drawable-mdpi/fastscroll_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_ab_back_qntm_am_alpha.png b/core/res/res/drawable-mdpi/ic_ab_back_qntm_am_alpha.png
new file mode 100644
index 0000000..e196bbe
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_ab_back_qntm_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_cab_done_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_cab_done_qntm_alpha.png
new file mode 100644
index 0000000..541184a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_cab_done_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_dialog_alert_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_dialog_alert_qntm_alpha.png
new file mode 100644
index 0000000..8a882f90
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_dialog_alert_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_find_next_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_find_next_qntm_alpha.png
new file mode 100644
index 0000000..1cfdb3f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_find_next_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_find_previous_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_find_previous_qntm_alpha.png
new file mode 100644
index 0000000..0d3c009
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_find_previous_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_copy_qntm_am_alpha.png b/core/res/res/drawable-mdpi/ic_menu_copy_qntm_am_alpha.png
new file mode 100644
index 0000000..3fae32d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_menu_copy_qntm_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_cut_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_menu_cut_qntm_alpha.png
new file mode 100644
index 0000000..61ff631
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_menu_cut_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_find_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_menu_find_qntm_alpha.png
new file mode 100644
index 0000000..6be897d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_menu_find_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_moreoverflow_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_qntm_alpha.png
new file mode 100644
index 0000000..8415096
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_menu_moreoverflow_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_paste_qntm_am_alpha.png b/core/res/res/drawable-mdpi/ic_menu_paste_qntm_am_alpha.png
new file mode 100644
index 0000000..112c268
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_menu_paste_qntm_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_search_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_menu_search_qntm_alpha.png
new file mode 100644
index 0000000..c5de768
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_menu_search_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_selectall_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_menu_selectall_qntm_alpha.png
new file mode 100644
index 0000000..6414956
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_menu_selectall_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_share_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_menu_share_qntm_alpha.png
new file mode 100644
index 0000000..e0d5ac4
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_menu_share_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_divider_qntm_alpha.9.png b/core/res/res/drawable-mdpi/list_divider_qntm_alpha.9.png
new file mode 100644
index 0000000..77845df
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_divider_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_section_divider_qntm_alpha.9.png b/core/res/res/drawable-mdpi/list_section_divider_qntm_alpha.9.png
new file mode 100644
index 0000000..11ae4f4
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_section_divider_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_primary_qntm_alpha.9.png b/core/res/res/drawable-mdpi/progress_primary_qntm_alpha.9.png
new file mode 100644
index 0000000..07cbed8
--- /dev/null
+++ b/core/res/res/drawable-mdpi/progress_primary_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_qntm_alpha.9.png b/core/res/res/drawable-mdpi/progress_qntm_alpha.9.png
new file mode 100644
index 0000000..8991421
--- /dev/null
+++ b/core/res/res/drawable-mdpi/progress_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrollbar_handle_qntm_alpha.9.png b/core/res/res/drawable-mdpi/scrollbar_handle_qntm_alpha.9.png
new file mode 100644
index 0000000..1834b2e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/scrollbar_handle_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_off_pressed_qntm_alpha.png b/core/res/res/drawable-mdpi/scrubber_control_off_pressed_qntm_alpha.png
new file mode 100644
index 0000000..1f4b46a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/scrubber_control_off_pressed_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_off_qntm_alpha.png b/core/res/res/drawable-mdpi/scrubber_control_off_qntm_alpha.png
new file mode 100644
index 0000000..1833704
--- /dev/null
+++ b/core/res/res/drawable-mdpi/scrubber_control_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_on_pressed_qntm_alpha.png b/core/res/res/drawable-mdpi/scrubber_control_on_pressed_qntm_alpha.png
new file mode 100644
index 0000000..3c304bf
--- /dev/null
+++ b/core/res/res/drawable-mdpi/scrubber_control_on_pressed_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_on_qntm_alpha.png b/core/res/res/drawable-mdpi/scrubber_control_on_qntm_alpha.png
new file mode 100644
index 0000000..e64d3f2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/scrubber_control_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_primary_qntm_alpha.9.png b/core/res/res/drawable-mdpi/scrubber_primary_qntm_alpha.9.png
new file mode 100644
index 0000000..a4ab0a1
--- /dev/null
+++ b/core/res/res/drawable-mdpi/scrubber_primary_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_qntm_am_alpha.9.png b/core/res/res/drawable-mdpi/spinner_qntm_am_alpha.9.png
new file mode 100644
index 0000000..5e245bc
--- /dev/null
+++ b/core/res/res/drawable-mdpi/spinner_qntm_am_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_off_qntm_alpha.9.png b/core/res/res/drawable-mdpi/switch_off_qntm_alpha.9.png
new file mode 100644
index 0000000..ffd6c39
--- /dev/null
+++ b/core/res/res/drawable-mdpi/switch_off_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_on_qntm_alpha.9.png b/core/res/res/drawable-mdpi/switch_on_qntm_alpha.9.png
new file mode 100644
index 0000000..15faff0
--- /dev/null
+++ b/core/res/res/drawable-mdpi/switch_on_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_track_qntm_alpha.9.png b/core/res/res/drawable-mdpi/switch_track_qntm_alpha.9.png
new file mode 100644
index 0000000..8991421
--- /dev/null
+++ b/core/res/res/drawable-mdpi/switch_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_indicator_normal_qntm_alpha.9.png b/core/res/res/drawable-mdpi/tab_indicator_normal_qntm_alpha.9.png
new file mode 100644
index 0000000..fd668ee
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_indicator_normal_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_indicator_selected_qntm_alpha.9.png b/core/res/res/drawable-mdpi/tab_indicator_selected_qntm_alpha.9.png
new file mode 100644
index 0000000..ace579f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_indicator_selected_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_cursor_qntm_alpha.9.png b/core/res/res/drawable-mdpi/text_cursor_qntm_alpha.9.png
new file mode 100644
index 0000000..e5760be
--- /dev/null
+++ b/core/res/res/drawable-mdpi/text_cursor_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_activated_qntm_alpha.9.png b/core/res/res/drawable-mdpi/textfield_activated_qntm_alpha.9.png
new file mode 100644
index 0000000..7a72295
--- /dev/null
+++ b/core/res/res/drawable-mdpi/textfield_activated_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_default_qntm_alpha.9.png b/core/res/res/drawable-mdpi/textfield_default_qntm_alpha.9.png
new file mode 100644
index 0000000..483931f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/textfield_default_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_solid_shadow_qntm.9.png b/core/res/res/drawable-xhdpi/ab_solid_shadow_qntm.9.png
new file mode 100644
index 0000000..1443b7f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_solid_shadow_qntm.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_transparent_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_transparent_qntm_alpha.9.png
new file mode 100644
index 0000000..c37ba9e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_off_qntm_alpha.png
new file mode 100644
index 0000000..5d820ae
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_on_qntm_alpha.png
new file mode 100644
index 0000000..019c92e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/btn_qntm_alpha.9.png
new file mode 100644
index 0000000..30d732a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_off_pressed_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_off_pressed_qntm_alpha.png
new file mode 100644
index 0000000..2fd964e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_off_pressed_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_off_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_off_qntm_alpha.png
new file mode 100644
index 0000000..8873cd6
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_on_pressed_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_on_pressed_qntm_alpha.png
new file mode 100644
index 0000000..a7ed0f8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_on_pressed_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_on_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_on_qntm_alpha.png
new file mode 100644
index 0000000..be4aaf3
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_star_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_star_qntm_alpha.png
new file mode 100644
index 0000000..a85bc06
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_star_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/expander_close_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/expander_close_qntm_alpha.9.png
new file mode 100644
index 0000000..43dccf3
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/expander_close_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/expander_open_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/expander_open_qntm_alpha.9.png
new file mode 100644
index 0000000..181be1a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/expander_open_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/fastscroll_thumb_qntm_alpha.png b/core/res/res/drawable-xhdpi/fastscroll_thumb_qntm_alpha.png
new file mode 100644
index 0000000..9534f78
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/fastscroll_thumb_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/fastscroll_track_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/fastscroll_track_qntm_alpha.9.png
new file mode 100644
index 0000000..02f0174
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/fastscroll_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_ab_back_qntm_am_alpha.png b/core/res/res/drawable-xhdpi/ic_ab_back_qntm_am_alpha.png
new file mode 100644
index 0000000..4385b2b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_ab_back_qntm_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_cab_done_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_cab_done_qntm_alpha.png
new file mode 100644
index 0000000..3d6d734
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_cab_done_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_dialog_alert_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_dialog_alert_qntm_alpha.png
new file mode 100644
index 0000000..2229bf3
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_dialog_alert_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_find_next_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_find_next_qntm_alpha.png
new file mode 100644
index 0000000..9038282
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_find_next_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_find_previous_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_find_previous_qntm_alpha.png
new file mode 100644
index 0000000..579347f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_find_previous_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_copy_qntm_am_alpha.png b/core/res/res/drawable-xhdpi/ic_menu_copy_qntm_am_alpha.png
new file mode 100644
index 0000000..b690d7c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_copy_qntm_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_cut_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_menu_cut_qntm_alpha.png
new file mode 100644
index 0000000..10c2067
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_cut_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_find_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_menu_find_qntm_alpha.png
new file mode 100644
index 0000000..dd5460f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_find_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_qntm_alpha.png
new file mode 100644
index 0000000..f91b718
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_moreoverflow_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_paste_qntm_am_alpha.png b/core/res/res/drawable-xhdpi/ic_menu_paste_qntm_am_alpha.png
new file mode 100644
index 0000000..4024627
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_paste_qntm_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_search_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_menu_search_qntm_alpha.png
new file mode 100644
index 0000000..4602b35
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_search_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_selectall_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_menu_selectall_qntm_alpha.png
new file mode 100644
index 0000000..f7c0261
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_selectall_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_share_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_menu_share_qntm_alpha.png
new file mode 100644
index 0000000..7accf52
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_menu_share_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_divider_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/list_divider_qntm_alpha.9.png
new file mode 100644
index 0000000..77845df
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/list_divider_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/list_section_divider_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/list_section_divider_qntm_alpha.9.png
new file mode 100644
index 0000000..e053b39
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/list_section_divider_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progress_primary_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/progress_primary_qntm_alpha.9.png
new file mode 100644
index 0000000..5c7e5cd
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/progress_primary_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progress_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/progress_qntm_alpha.9.png
new file mode 100644
index 0000000..4970f56
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/progress_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrollbar_handle_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/scrollbar_handle_qntm_alpha.9.png
new file mode 100644
index 0000000..3c816c7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/scrollbar_handle_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_off_pressed_qntm_alpha.png b/core/res/res/drawable-xhdpi/scrubber_control_off_pressed_qntm_alpha.png
new file mode 100644
index 0000000..754b321
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/scrubber_control_off_pressed_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_off_qntm_alpha.png b/core/res/res/drawable-xhdpi/scrubber_control_off_qntm_alpha.png
new file mode 100644
index 0000000..ad72f06
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/scrubber_control_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_on_pressed_qntm_alpha.png b/core/res/res/drawable-xhdpi/scrubber_control_on_pressed_qntm_alpha.png
new file mode 100644
index 0000000..a7ed0f8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/scrubber_control_on_pressed_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_on_qntm_alpha.png b/core/res/res/drawable-xhdpi/scrubber_control_on_qntm_alpha.png
new file mode 100644
index 0000000..7aceed1
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/scrubber_control_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_primary_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/scrubber_primary_qntm_alpha.9.png
new file mode 100644
index 0000000..2b4734d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/scrubber_primary_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_qntm_am_alpha.9.png b/core/res/res/drawable-xhdpi/spinner_qntm_am_alpha.9.png
new file mode 100644
index 0000000..79a260b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/spinner_qntm_am_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_off_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/switch_off_qntm_alpha.9.png
new file mode 100644
index 0000000..309b528
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/switch_off_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_on_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/switch_on_qntm_alpha.9.png
new file mode 100644
index 0000000..139795e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/switch_on_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_track_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/switch_track_qntm_alpha.9.png
new file mode 100644
index 0000000..4970f56
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/switch_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_indicator_normal_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/tab_indicator_normal_qntm_alpha.9.png
new file mode 100644
index 0000000..a677f9a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/tab_indicator_normal_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_indicator_selected_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/tab_indicator_selected_qntm_alpha.9.png
new file mode 100644
index 0000000..7de791d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/tab_indicator_selected_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_cursor_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/text_cursor_qntm_alpha.9.png
new file mode 100644
index 0000000..3939214
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/text_cursor_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_activated_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/textfield_activated_qntm_alpha.9.png
new file mode 100644
index 0000000..16c376a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/textfield_activated_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_default_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/textfield_default_qntm_alpha.9.png
new file mode 100644
index 0000000..e3bd904
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/textfield_default_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_solid_shadow_qntm.9.png b/core/res/res/drawable-xxhdpi/ab_solid_shadow_qntm.9.png
new file mode 100644
index 0000000..e89c9fe
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_solid_shadow_qntm.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_transparent_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_transparent_qntm_alpha.9.png
new file mode 100644
index 0000000..f220168
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_off_qntm_alpha.png
new file mode 100644
index 0000000..2a17861
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_on_qntm_alpha.png
new file mode 100644
index 0000000..61067ac
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/btn_qntm_alpha.9.png
new file mode 100644
index 0000000..7d29d18
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_pressed_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_off_pressed_qntm_alpha.png
new file mode 100644
index 0000000..fdbbbce
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_pressed_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_off_qntm_alpha.png
new file mode 100644
index 0000000..0ec2ee6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_pressed_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_on_pressed_qntm_alpha.png
new file mode 100644
index 0000000..b46ee1c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_pressed_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_on_qntm_alpha.png
new file mode 100644
index 0000000..8737156
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_star_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_star_qntm_alpha.png
new file mode 100644
index 0000000..7488ff9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_star_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/expander_close_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/expander_close_qntm_alpha.9.png
new file mode 100644
index 0000000..e78fff6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/expander_close_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/expander_open_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/expander_open_qntm_alpha.9.png
new file mode 100644
index 0000000..a3d09657
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/expander_open_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_thumb_qntm_alpha.png b/core/res/res/drawable-xxhdpi/fastscroll_thumb_qntm_alpha.png
new file mode 100644
index 0000000..55a73e7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/fastscroll_thumb_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/fastscroll_track_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/fastscroll_track_qntm_alpha.9.png
new file mode 100644
index 0000000..be64a94
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/fastscroll_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_ab_back_qntm_am_alpha.png b/core/res/res/drawable-xxhdpi/ic_ab_back_qntm_am_alpha.png
new file mode 100644
index 0000000..ca15853
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_ab_back_qntm_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_cab_done_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_cab_done_qntm_alpha.png
new file mode 100644
index 0000000..1f9c734
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_cab_done_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_dialog_alert_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_dialog_alert_qntm_alpha.png
new file mode 100644
index 0000000..10e0756
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_dialog_alert_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_find_next_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_find_next_qntm_alpha.png
new file mode 100644
index 0000000..e3a7e9e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_find_next_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_find_previous_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_find_previous_qntm_alpha.png
new file mode 100644
index 0000000..f9cf16c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_find_previous_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_copy_qntm_am_alpha.png b/core/res/res/drawable-xxhdpi/ic_menu_copy_qntm_am_alpha.png
new file mode 100644
index 0000000..7c3a58b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_copy_qntm_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_cut_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_menu_cut_qntm_alpha.png
new file mode 100644
index 0000000..2200642
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_cut_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_find_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_menu_find_qntm_alpha.png
new file mode 100644
index 0000000..d35b337
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_find_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_qntm_alpha.png
new file mode 100644
index 0000000..ff1759b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_moreoverflow_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_paste_qntm_am_alpha.png b/core/res/res/drawable-xxhdpi/ic_menu_paste_qntm_am_alpha.png
new file mode 100644
index 0000000..28c0ae0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_paste_qntm_am_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_search_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_menu_search_qntm_alpha.png
new file mode 100644
index 0000000..cb295a3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_search_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_selectall_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_menu_selectall_qntm_alpha.png
new file mode 100644
index 0000000..6430d45
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_selectall_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_share_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_menu_share_qntm_alpha.png
new file mode 100644
index 0000000..66f7d16
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_menu_share_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_divider_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/list_divider_qntm_alpha.9.png
new file mode 100644
index 0000000..0fafd1a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/list_divider_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/list_section_divider_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/list_section_divider_qntm_alpha.9.png
new file mode 100644
index 0000000..491fab9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/list_section_divider_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progress_primary_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/progress_primary_qntm_alpha.9.png
new file mode 100644
index 0000000..2d4eb3f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/progress_primary_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/progress_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/progress_qntm_alpha.9.png
new file mode 100644
index 0000000..74a259b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/progress_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrollbar_handle_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/scrollbar_handle_qntm_alpha.9.png
new file mode 100644
index 0000000..c1c0622
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrollbar_handle_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_off_pressed_qntm_alpha.png b/core/res/res/drawable-xxhdpi/scrubber_control_off_pressed_qntm_alpha.png
new file mode 100644
index 0000000..0319bd8
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_off_pressed_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_off_qntm_alpha.png b/core/res/res/drawable-xxhdpi/scrubber_control_off_qntm_alpha.png
new file mode 100644
index 0000000..c11b0ae
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_on_pressed_qntm_alpha.png b/core/res/res/drawable-xxhdpi/scrubber_control_on_pressed_qntm_alpha.png
new file mode 100644
index 0000000..b46ee1c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_on_pressed_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_on_qntm_alpha.png b/core/res/res/drawable-xxhdpi/scrubber_control_on_qntm_alpha.png
new file mode 100644
index 0000000..cde797e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_primary_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/scrubber_primary_qntm_alpha.9.png
new file mode 100644
index 0000000..6a82af5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_primary_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_qntm_am_alpha.9.png b/core/res/res/drawable-xxhdpi/spinner_qntm_am_alpha.9.png
new file mode 100644
index 0000000..b8c78b5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/spinner_qntm_am_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_off_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/switch_off_qntm_alpha.9.png
new file mode 100644
index 0000000..9e234af
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/switch_off_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_on_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/switch_on_qntm_alpha.9.png
new file mode 100644
index 0000000..b371eab
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/switch_on_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_track_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/switch_track_qntm_alpha.9.png
new file mode 100644
index 0000000..74a259b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/switch_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/tab_indicator_normal_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/tab_indicator_normal_qntm_alpha.9.png
new file mode 100644
index 0000000..0a14025
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/tab_indicator_normal_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/tab_indicator_selected_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/tab_indicator_selected_qntm_alpha.9.png
new file mode 100644
index 0000000..20e291a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/tab_indicator_selected_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_cursor_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/text_cursor_qntm_alpha.9.png
new file mode 100644
index 0000000..432c385
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/text_cursor_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_activated_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/textfield_activated_qntm_alpha.9.png
new file mode 100644
index 0000000..a22f352
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_activated_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_default_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/textfield_default_qntm_alpha.9.png
new file mode 100644
index 0000000..b0504e0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_default_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable/ab_transparent_quantum_dark.xml b/core/res/res/drawable/ab_transparent_quantum_dark.xml
new file mode 100644
index 0000000..9ac2fc0
--- /dev/null
+++ b/core/res/res/drawable/ab_transparent_quantum_dark.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ab_transparent_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ab_transparent_quantum_light.xml b/core/res/res/drawable/ab_transparent_quantum_light.xml
new file mode 100644
index 0000000..bc49848
--- /dev/null
+++ b/core/res/res/drawable/ab_transparent_quantum_light.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ab_transparent_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_light" />
diff --git a/core/res/res/drawable/activated_background_quantum_dark.xml b/core/res/res/drawable/activated_background_quantum_dark.xml
new file mode 100644
index 0000000..a9e3fea
--- /dev/null
+++ b/core/res/res/drawable/activated_background_quantum_dark.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_activated="true" android:drawable="@color/control_activated_foreground_quantum_dark" />
+    <item android:drawable="@color/transparent" />
+</selector>
diff --git a/core/res/res/drawable/activated_background_quantum_light.xml b/core/res/res/drawable/activated_background_quantum_light.xml
new file mode 100644
index 0000000..5d10ea2
--- /dev/null
+++ b/core/res/res/drawable/activated_background_quantum_light.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_activated="true" android:drawable="@color/control_activated_foreground_quantum_light" />
+    <item android:drawable="@color/transparent" />
+</selector>
diff --git a/core/res/res/drawable/background_cache_hint_selector_quantum_dark.xml b/core/res/res/drawable/background_cache_hint_selector_quantum_dark.xml
index 7d64abc..ab66501 100644
--- a/core/res/res/drawable/background_cache_hint_selector_quantum_dark.xml
+++ b/core/res/res/drawable/background_cache_hint_selector_quantum_dark.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<!-- Copyright (C) 2014 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.
diff --git a/core/res/res/drawable/background_cache_hint_selector_quantum_light.xml b/core/res/res/drawable/background_cache_hint_selector_quantum_light.xml
index 3fc3483..fb940a9 100644
--- a/core/res/res/drawable/background_cache_hint_selector_quantum_light.xml
+++ b/core/res/res/drawable/background_cache_hint_selector_quantum_light.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<!-- Copyright (C) 2014 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.
diff --git a/core/res/res/drawable/btn_borderless_quantum_dark.xml b/core/res/res/drawable/btn_borderless_quantum_dark.xml
new file mode 100644
index 0000000..e1bff4f
--- /dev/null
+++ b/core/res/res/drawable/btn_borderless_quantum_dark.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<reveal xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@color/transparent" />
+    <item>
+        <nine-patch android:src="@drawable/btn_qntm_alpha"
+            android:tint="@color/btn_default_pressed_quantum_dark" />
+    </item>
+</reveal>
diff --git a/core/res/res/drawable/btn_borderless_quantum_light.xml b/core/res/res/drawable/btn_borderless_quantum_light.xml
new file mode 100644
index 0000000..e7a95b1
--- /dev/null
+++ b/core/res/res/drawable/btn_borderless_quantum_light.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<reveal xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@color/transparent" />
+    <item>
+        <nine-patch android:src="@drawable/btn_qntm_alpha"
+            android:tint="@color/btn_default_pressed_quantum_light" />
+    </item>
+</reveal>
diff --git a/core/res/res/drawable/btn_check_quantum_dark.xml b/core/res/res/drawable/btn_check_quantum_dark.xml
new file mode 100644
index 0000000..a35bec4
--- /dev/null
+++ b/core/res/res/drawable/btn_check_quantum_dark.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true" android:state_pressed="true">
+        <bitmap android:src="@drawable/btn_check_on_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item android:state_checked="true">
+        <bitmap android:src="@drawable/btn_check_on_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item android:state_pressed="true">
+        <bitmap android:src="@drawable/btn_check_off_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item>
+        <bitmap android:src="@drawable/btn_check_off_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_dark" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/btn_check_quantum_light.xml b/core/res/res/drawable/btn_check_quantum_light.xml
new file mode 100644
index 0000000..8588fce
--- /dev/null
+++ b/core/res/res/drawable/btn_check_quantum_light.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true" android:state_pressed="true">
+        <bitmap android:src="@drawable/btn_check_on_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item android:state_checked="true">
+        <bitmap android:src="@drawable/btn_check_on_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item android:state_pressed="true">
+        <bitmap android:src="@drawable/btn_check_off_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item>
+        <bitmap android:src="@drawable/btn_check_off_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_light" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/btn_color_quantum_dark.xml b/core/res/res/drawable/btn_color_quantum_dark.xml
new file mode 100644
index 0000000..5e44a78
--- /dev/null
+++ b/core/res/res/drawable/btn_color_quantum_dark.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<reveal xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+        <selector>
+            <item android:state_enabled="false">
+                <nine-patch android:src="@drawable/btn_qntm_alpha"
+                    android:tint="@color/btn_default_normal_quantum_light" />
+            </item>
+            <item>
+                <nine-patch android:src="@drawable/btn_qntm_alpha"
+                    android:tint="@color/theme_color_500" />
+            </item>
+        </selector>
+    </item>
+    <item>
+        <nine-patch android:src="@drawable/btn_qntm_alpha"
+            android:tint="@color/theme_color_300" />
+    </item>
+</reveal>
diff --git a/core/res/res/drawable/btn_color_quantum_light.xml b/core/res/res/drawable/btn_color_quantum_light.xml
new file mode 100644
index 0000000..d6be958
--- /dev/null
+++ b/core/res/res/drawable/btn_color_quantum_light.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<reveal xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+        <selector>
+            <item android:state_enabled="false">
+                <nine-patch android:src="@drawable/btn_qntm_alpha"
+                    android:tint="@color/btn_default_normal_quantum_dark" />
+            </item>
+            <item>
+                <nine-patch android:src="@drawable/btn_qntm_alpha"
+                    android:tint="@color/theme_color_500" />
+            </item>
+        </selector>
+    </item>
+    <item>
+        <nine-patch android:src="@drawable/btn_qntm_alpha"
+            android:tint="@color/theme_color_700" />
+    </item>
+</reveal>
diff --git a/core/res/res/drawable/btn_default_quantum_dark.xml b/core/res/res/drawable/btn_default_quantum_dark.xml
index 84b1090..7f0cca8 100644
--- a/core/res/res/drawable/btn_default_quantum_dark.xml
+++ b/core/res/res/drawable/btn_default_quantum_dark.xml
@@ -16,20 +16,11 @@
 
 <reveal xmlns:android="http://schemas.android.com/apk/res/android">
     <item>
-        <selector>
-            <item android:state_window_focused="false" android:state_enabled="true"
-                android:drawable="@drawable/btn_default_normal_holo_dark" />
-            <item android:state_window_focused="false" android:state_enabled="false"
-                android:drawable="@drawable/btn_default_disabled_holo_dark" />
-            <item android:state_focused="true" android:state_enabled="true"
-                android:drawable="@drawable/btn_default_focused_holo_dark" />
-            <item android:state_enabled="true"
-                android:drawable="@drawable/btn_default_normal_holo_dark" />
-            <item android:state_focused="true"
-                android:drawable="@drawable/btn_default_disabled_focused_holo_dark" />
-            <item
-                android:drawable="@drawable/btn_default_disabled_holo_dark" />
-        </selector>
+        <nine-patch android:src="@drawable/btn_qntm_alpha"
+            android:tint="@color/btn_default_normal_quantum_dark" />
     </item>
-    <item android:drawable="@drawable/btn_default_pressed_holo_dark" />
+    <item>
+        <nine-patch android:src="@drawable/btn_qntm_alpha"
+            android:tint="@color/btn_default_pressed_quantum_dark" />
+    </item>
 </reveal>
diff --git a/core/res/res/drawable/btn_default_quantum_light.xml b/core/res/res/drawable/btn_default_quantum_light.xml
index b559198..e391a80 100644
--- a/core/res/res/drawable/btn_default_quantum_light.xml
+++ b/core/res/res/drawable/btn_default_quantum_light.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
+<!-- Copyright (C) 2014 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.
@@ -16,20 +16,11 @@
 
 <reveal xmlns:android="http://schemas.android.com/apk/res/android">
     <item>
-        <selector>
-            <item android:state_window_focused="false" android:state_enabled="true"
-                android:drawable="@drawable/btn_default_normal_holo_light" />
-            <item android:state_window_focused="false" android:state_enabled="false"
-                android:drawable="@drawable/btn_default_disabled_holo_light" />
-            <item android:state_focused="true" android:state_enabled="true"
-                android:drawable="@drawable/btn_default_focused_holo_light" />
-            <item android:state_enabled="true"
-                android:drawable="@drawable/btn_default_normal_holo_light" />
-            <item android:state_focused="true"
-                android:drawable="@drawable/btn_default_disabled_focused_holo_light" />
-            <item
-                android:drawable="@drawable/btn_default_disabled_holo_light" />
-        </selector>
+        <nine-patch android:src="@drawable/btn_qntm_alpha"
+            android:tint="@color/btn_default_normal_quantum_light" />
     </item>
-    <item android:drawable="@drawable/btn_default_pressed_holo_light" />
+    <item>
+        <nine-patch android:src="@drawable/btn_qntm_alpha"
+            android:tint="@color/btn_default_pressed_quantum_light" />
+    </item>
 </reveal>
diff --git a/core/res/res/drawable/btn_radio_quantum_dark.xml b/core/res/res/drawable/btn_radio_quantum_dark.xml
new file mode 100644
index 0000000..54f4f9a
--- /dev/null
+++ b/core/res/res/drawable/btn_radio_quantum_dark.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true" android:state_enabled="true" android:state_pressed="true">
+        <bitmap android:src="@drawable/btn_radio_on_pressed_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item android:state_checked="true">
+        <bitmap android:src="@drawable/btn_radio_on_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item android:state_enabled="true" android:state_pressed="true">
+        <bitmap android:src="@drawable/btn_radio_off_pressed_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item>
+        <bitmap android:src="@drawable/btn_radio_off_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_dark" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/btn_radio_quantum_light.xml b/core/res/res/drawable/btn_radio_quantum_light.xml
new file mode 100644
index 0000000..c1ace70
--- /dev/null
+++ b/core/res/res/drawable/btn_radio_quantum_light.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true" android:state_enabled="true" android:state_pressed="true">
+        <bitmap android:src="@drawable/btn_radio_on_pressed_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item android:state_checked="true">
+        <bitmap android:src="@drawable/btn_radio_on_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item android:state_enabled="true" android:state_pressed="true">
+        <bitmap android:src="@drawable/btn_radio_off_pressed_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item>
+        <bitmap android:src="@drawable/btn_radio_off_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_light" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/btn_star_quantum_dark.xml b/core/res/res/drawable/btn_star_quantum_dark.xml
new file mode 100644
index 0000000..7b26a3c
--- /dev/null
+++ b/core/res/res/drawable/btn_star_quantum_dark.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true">
+        <bitmap android:src="@drawable/btn_star_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item android:state_pressed="true">
+        <bitmap android:src="@drawable/btn_star_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item>
+        <bitmap android:src="@drawable/btn_star_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_dark" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/btn_star_quantum_light.xml b/core/res/res/drawable/btn_star_quantum_light.xml
new file mode 100644
index 0000000..df2cc91
--- /dev/null
+++ b/core/res/res/drawable/btn_star_quantum_light.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true">
+        <bitmap android:src="@drawable/btn_star_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item android:state_pressed="true">
+        <bitmap android:src="@drawable/btn_star_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item>
+        <bitmap android:src="@drawable/btn_star_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_light" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/edit_text_quantum_dark.xml b/core/res/res/drawable/edit_text_quantum_dark.xml
new file mode 100644
index 0000000..ea3fc52
--- /dev/null
+++ b/core/res/res/drawable/edit_text_quantum_dark.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_window_focused="false" android:state_enabled="true">
+        <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_dark" />
+    </item>
+    <item android:state_window_focused="false" android:state_enabled="false">
+        <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_dark" />
+    </item>
+    <item android:state_enabled="true" android:state_focused="true">
+        <nine-patch android:src="@drawable/textfield_activated_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item android:state_enabled="true" android:state_activated="true">
+        <nine-patch android:src="@drawable/textfield_activated_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item android:state_enabled="true">
+        <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_dark" />
+    </item>
+    <item>
+        <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_dark" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/edit_text_quantum_light.xml b/core/res/res/drawable/edit_text_quantum_light.xml
new file mode 100644
index 0000000..dd7fe53
--- /dev/null
+++ b/core/res/res/drawable/edit_text_quantum_light.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_window_focused="false" android:state_enabled="true">
+        <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_light" />
+    </item>
+    <item android:state_window_focused="false" android:state_enabled="false">
+        <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_light" />
+    </item>
+    <item android:state_enabled="true" android:state_focused="true">
+        <nine-patch android:src="@drawable/textfield_activated_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item android:state_enabled="true" android:state_activated="true">
+        <nine-patch android:src="@drawable/textfield_activated_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item android:state_enabled="true">
+        <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_light" />
+    </item>
+    <item>
+        <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_light" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/expander_group_quantum_dark.xml b/core/res/res/drawable/expander_group_quantum_dark.xml
new file mode 100644
index 0000000..7250e01
--- /dev/null
+++ b/core/res/res/drawable/expander_group_quantum_dark.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_expanded="true">
+        <nine-patch android:src="@drawable/expander_close_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_dark" />
+    </item>
+    <item>
+        <nine-patch android:src="@drawable/expander_open_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_dark" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/expander_group_quantum_light.xml b/core/res/res/drawable/expander_group_quantum_light.xml
new file mode 100644
index 0000000..62af983
--- /dev/null
+++ b/core/res/res/drawable/expander_group_quantum_light.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_expanded="true">
+        <nine-patch android:src="@drawable/expander_close_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_light" />
+    </item>
+    <item>
+        <nine-patch android:src="@drawable/expander_open_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_light" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/fastscroll_thumb_quantum_dark.xml b/core/res/res/drawable/fastscroll_thumb_quantum_dark.xml
new file mode 100644
index 0000000..53c7fdd
--- /dev/null
+++ b/core/res/res/drawable/fastscroll_thumb_quantum_dark.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true">
+        <bitmap android:src="@drawable/fastscroll_thumb_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item>
+        <bitmap android:src="@drawable/fastscroll_thumb_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_dark" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/fastscroll_thumb_quantum_light.xml b/core/res/res/drawable/fastscroll_thumb_quantum_light.xml
new file mode 100644
index 0000000..3bc87e9
--- /dev/null
+++ b/core/res/res/drawable/fastscroll_thumb_quantum_light.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true">
+        <bitmap android:src="@drawable/fastscroll_thumb_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item>
+        <bitmap android:src="@drawable/fastscroll_thumb_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_light" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/fastscroll_track_quantum_dark.xml b/core/res/res/drawable/fastscroll_track_quantum_dark.xml
new file mode 100644
index 0000000..0ae57d2
--- /dev/null
+++ b/core/res/res/drawable/fastscroll_track_quantum_dark.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/fastscroll_track_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_light" />
diff --git a/core/res/res/drawable/fastscroll_track_quantum_light.xml b/core/res/res/drawable/fastscroll_track_quantum_light.xml
new file mode 100644
index 0000000..627c079
--- /dev/null
+++ b/core/res/res/drawable/fastscroll_track_quantum_light.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/fastscroll_track_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ic_ab_back_quantum_dark.xml b/core/res/res/drawable/ic_ab_back_quantum_dark.xml
new file mode 100644
index 0000000..628d53e
--- /dev/null
+++ b/core/res/res/drawable/ic_ab_back_quantum_dark.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_ab_back_qntm_am_alpha"
+    android:autoMirrored="true"
+    android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ic_ab_back_quantum_light.xml b/core/res/res/drawable/ic_ab_back_quantum_light.xml
new file mode 100644
index 0000000..01f5362
--- /dev/null
+++ b/core/res/res/drawable/ic_ab_back_quantum_light.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_ab_back_qntm_am_alpha"
+    android:autoMirrored="true"
+    android:tint="@color/control_normal_foreground_quantum_light" />
diff --git a/core/res/res/drawable/ic_cab_done_quantum_dark.xml b/core/res/res/drawable/ic_cab_done_quantum_dark.xml
new file mode 100644
index 0000000..472996e
--- /dev/null
+++ b/core/res/res/drawable/ic_cab_done_quantum_dark.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_cab_done_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ic_cab_done_quantum_light.xml b/core/res/res/drawable/ic_cab_done_quantum_light.xml
new file mode 100644
index 0000000..d70a3f1
--- /dev/null
+++ b/core/res/res/drawable/ic_cab_done_quantum_light.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_cab_done_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_light" />
diff --git a/core/res/res/drawable/ic_dialog_alert_quantum_dark.xml b/core/res/res/drawable/ic_dialog_alert_quantum_dark.xml
new file mode 100644
index 0000000..8b8cb0c
--- /dev/null
+++ b/core/res/res/drawable/ic_dialog_alert_quantum_dark.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_dialog_alert_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ic_dialog_alert_quantum_light.xml b/core/res/res/drawable/ic_dialog_alert_quantum_light.xml
new file mode 100644
index 0000000..8b8cb0c
--- /dev/null
+++ b/core/res/res/drawable/ic_dialog_alert_quantum_light.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_dialog_alert_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ic_find_next_quantum_dark.xml b/core/res/res/drawable/ic_find_next_quantum_dark.xml
new file mode 100644
index 0000000..929bea3
--- /dev/null
+++ b/core/res/res/drawable/ic_find_next_quantum_dark.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_find_next_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ic_find_next_quantum_light.xml b/core/res/res/drawable/ic_find_next_quantum_light.xml
new file mode 100644
index 0000000..9c20327
--- /dev/null
+++ b/core/res/res/drawable/ic_find_next_quantum_light.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_find_next_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_light" />
diff --git a/core/res/res/drawable/ic_find_previous_quantum_dark.xml b/core/res/res/drawable/ic_find_previous_quantum_dark.xml
new file mode 100644
index 0000000..e944223
--- /dev/null
+++ b/core/res/res/drawable/ic_find_previous_quantum_dark.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_find_previous_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ic_find_previous_quantum_light.xml b/core/res/res/drawable/ic_find_previous_quantum_light.xml
new file mode 100644
index 0000000..b037094
--- /dev/null
+++ b/core/res/res/drawable/ic_find_previous_quantum_light.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_find_previous_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_light" />
diff --git a/core/res/res/drawable/ic_menu_copy_quantum_dark.xml b/core/res/res/drawable/ic_menu_copy_quantum_dark.xml
new file mode 100644
index 0000000..285b752
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_copy_quantum_dark.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_menu_copy_qntm_am_alpha"
+    android:tint="@color/control_normal_foreground_quantum_dark"
+    android:autoMirrored="true" />
diff --git a/core/res/res/drawable/ic_menu_copy_quantum_light.xml b/core/res/res/drawable/ic_menu_copy_quantum_light.xml
new file mode 100644
index 0000000..a40b219
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_copy_quantum_light.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_menu_copy_qntm_am_alpha"
+    android:tint="@color/control_normal_foreground_quantum_light"
+    android:autoMirrored="true" />
diff --git a/core/res/res/drawable/ic_menu_cut_quantum_dark.xml b/core/res/res/drawable/ic_menu_cut_quantum_dark.xml
new file mode 100644
index 0000000..563400b
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_cut_quantum_dark.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_menu_cut_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ic_menu_cut_quantum_light.xml b/core/res/res/drawable/ic_menu_cut_quantum_light.xml
new file mode 100644
index 0000000..36c9442
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_cut_quantum_light.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_menu_cut_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_light" />
diff --git a/core/res/res/drawable/ic_menu_find_quantum_dark.xml b/core/res/res/drawable/ic_menu_find_quantum_dark.xml
new file mode 100644
index 0000000..8803463
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_find_quantum_dark.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_menu_find_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ic_menu_find_quantum_light.xml b/core/res/res/drawable/ic_menu_find_quantum_light.xml
new file mode 100644
index 0000000..9b3bd73
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_find_quantum_light.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_menu_find_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_light" />
diff --git a/core/res/res/drawable/ic_menu_moreoverflow_quantum_dark.xml b/core/res/res/drawable/ic_menu_moreoverflow_quantum_dark.xml
new file mode 100644
index 0000000..9f39a68
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_moreoverflow_quantum_dark.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_menu_moreoverflow_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ic_menu_moreoverflow_quantum_light.xml b/core/res/res/drawable/ic_menu_moreoverflow_quantum_light.xml
new file mode 100644
index 0000000..e15eaec
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_moreoverflow_quantum_light.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_menu_moreoverflow_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_light" />
diff --git a/core/res/res/drawable/ic_menu_paste_quantum_dark.xml b/core/res/res/drawable/ic_menu_paste_quantum_dark.xml
new file mode 100644
index 0000000..7033404
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_paste_quantum_dark.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_menu_paste_qntm_am_alpha"
+    android:tint="@color/control_normal_foreground_quantum_dark"
+    android:autoMirrored="true" />
diff --git a/core/res/res/drawable/ic_menu_paste_quantum_light.xml b/core/res/res/drawable/ic_menu_paste_quantum_light.xml
new file mode 100644
index 0000000..155ec34
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_paste_quantum_light.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_menu_paste_qntm_am_alpha"
+    android:tint="@color/control_normal_foreground_quantum_light"
+    android:autoMirrored="true" />
diff --git a/core/res/res/drawable/ic_menu_search_quantum_dark.xml b/core/res/res/drawable/ic_menu_search_quantum_dark.xml
new file mode 100644
index 0000000..1c6efcd
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_search_quantum_dark.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_menu_search_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ic_menu_search_quantum_light.xml b/core/res/res/drawable/ic_menu_search_quantum_light.xml
new file mode 100644
index 0000000..ba6efb6
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_search_quantum_light.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_menu_search_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_light" />
diff --git a/core/res/res/drawable/ic_menu_selectall_quantum_dark.xml b/core/res/res/drawable/ic_menu_selectall_quantum_dark.xml
new file mode 100644
index 0000000..c1d3e69
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_selectall_quantum_dark.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_menu_selectall_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ic_menu_selectall_quantum_light.xml b/core/res/res/drawable/ic_menu_selectall_quantum_light.xml
new file mode 100644
index 0000000..4de8962
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_selectall_quantum_light.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_menu_selectall_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_light" />
diff --git a/core/res/res/drawable/ic_menu_share_quantum_dark.xml b/core/res/res/drawable/ic_menu_share_quantum_dark.xml
new file mode 100644
index 0000000..a7c5afc
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_share_quantum_dark.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_menu_share_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ic_menu_share_quantum_light.xml b/core/res/res/drawable/ic_menu_share_quantum_light.xml
new file mode 100644
index 0000000..9257c25
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_share_quantum_light.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_menu_share_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_light" />
diff --git a/core/res/res/drawable/item_background_borderless_quantum_dark.xml b/core/res/res/drawable/item_background_borderless_quantum_dark.xml
new file mode 100644
index 0000000..1caee4e
--- /dev/null
+++ b/core/res/res/drawable/item_background_borderless_quantum_dark.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="@color/lighter_gray" />
diff --git a/core/res/res/drawable/item_background_borderless_quantum_light.xml b/core/res/res/drawable/item_background_borderless_quantum_light.xml
new file mode 100644
index 0000000..ecf7dfb
--- /dev/null
+++ b/core/res/res/drawable/item_background_borderless_quantum_light.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="@color/darker_gray" />
diff --git a/core/res/res/drawable/list_divider_quantum_dark.xml b/core/res/res/drawable/list_divider_quantum_dark.xml
new file mode 100644
index 0000000..9d05b2f
--- /dev/null
+++ b/core/res/res/drawable/list_divider_quantum_dark.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/list_divider_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/list_divider_quantum_light.xml b/core/res/res/drawable/list_divider_quantum_light.xml
new file mode 100644
index 0000000..d312e2d
--- /dev/null
+++ b/core/res/res/drawable/list_divider_quantum_light.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/list_divider_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_light" />
diff --git a/core/res/res/drawable/list_section_divider_quantum_dark.xml b/core/res/res/drawable/list_section_divider_quantum_dark.xml
new file mode 100644
index 0000000..6344c7e
--- /dev/null
+++ b/core/res/res/drawable/list_section_divider_quantum_dark.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/list_section_divider_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/list_section_divider_quantum_light.xml b/core/res/res/drawable/list_section_divider_quantum_light.xml
new file mode 100644
index 0000000..98ede38
--- /dev/null
+++ b/core/res/res/drawable/list_section_divider_quantum_light.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/list_section_divider_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_light" />
diff --git a/core/res/res/drawable/list_selector_quantum_dark.xml b/core/res/res/drawable/list_selector_quantum_dark.xml
deleted file mode 100644
index fea55a8..0000000
--- a/core/res/res/drawable/list_selector_quantum_dark.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 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.
--->
-
-<reveal xmlns:android="http://schemas.android.com/apk/res/android">
-    <selector>
-        <item android:state_window_focused="false" android:drawable="@color/transparent" />
-        <item android:state_focused="true" android:state_enabled="false"
-            android:drawable="@drawable/list_selector_disabled_holo_dark" />
-        <item android:state_focused="true" android:drawable="@drawable/list_focused_holo" />
-    </selector>
-    <selector>
-        <item android:state_window_focused="false" android:drawable="@color/transparent" />
-        <item android:state_focused="true" android:state_enabled="false"
-            android:state_pressed="true" android:drawable="@drawable/list_selector_disabled_holo_dark" />
-        <item android:state_focused="true" android:state_pressed="true"
-            android:drawable="@drawable/list_selector_background_transition_holo_dark" />
-        <item android:state_focused="false" android:state_pressed="true"
-            android:drawable="@drawable/list_selector_background_transition_holo_dark" />
-    </selector>
-</reveal>
diff --git a/core/res/res/drawable/list_selector_quantum_light.xml b/core/res/res/drawable/list_selector_quantum_light.xml
deleted file mode 100644
index 1e32eac..0000000
--- a/core/res/res/drawable/list_selector_quantum_light.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 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.
--->
-
-<reveal xmlns:android="http://schemas.android.com/apk/res/android">
-    <selector>
-        <item android:state_window_focused="false" android:drawable="@color/transparent" />
-        <item android:state_focused="true" android:state_enabled="false"
-            android:drawable="@drawable/list_selector_disabled_holo_light" />
-        <item android:state_focused="true" android:drawable="@drawable/list_focused_holo" />
-    </selector>
-    <selector>
-        <item android:state_window_focused="false" android:drawable="@color/transparent" />
-        <item android:state_focused="true" android:state_enabled="false"
-            android:state_pressed="true" android:drawable="@drawable/list_selector_disabled_holo_light" />
-        <item android:state_focused="true" android:state_pressed="true"
-            android:drawable="@drawable/list_selector_background_transition_holo_light" />
-        <item android:state_focused="false" android:state_pressed="true"
-            android:drawable="@drawable/list_selector_background_transition_holo_light" />
-    </selector>
-</reveal>
diff --git a/core/res/res/drawable/notification_quantum_background.xml b/core/res/res/drawable/notification_quantum_background.xml
new file mode 100644
index 0000000..f33e2e3
--- /dev/null
+++ b/core/res/res/drawable/notification_quantum_background.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 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
+  -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="#ffffffff" />
+    <corners android:radius="2dp" />
+</shape>
\ No newline at end of file
diff --git a/core/res/res/drawable/notification_quantum_bg.xml b/core/res/res/drawable/notification_quantum_bg.xml
new file mode 100644
index 0000000..608115e
--- /dev/null
+++ b/core/res/res/drawable/notification_quantum_bg.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true"  android:drawable="@drawable/notification_quantum_press" />
+    <item android:state_pressed="false" android:drawable="@drawable/notification_quantum_background" />
+</selector>
\ No newline at end of file
diff --git a/core/res/res/drawable/notification_quantum_press.xml b/core/res/res/drawable/notification_quantum_press.xml
new file mode 100644
index 0000000..4999f55
--- /dev/null
+++ b/core/res/res/drawable/notification_quantum_press.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 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
+  -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="#ffcccccc" />
+    <corners android:radius="2dp" />
+</shape>
\ No newline at end of file
diff --git a/core/res/res/drawable/progress_horizontal_quantum_dark.xml b/core/res/res/drawable/progress_horizontal_quantum_dark.xml
new file mode 100644
index 0000000..fb4b67e
--- /dev/null
+++ b/core/res/res/drawable/progress_horizontal_quantum_dark.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@id/background">
+        <nine-patch android:src="@drawable/progress_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_dark" />
+    </item>
+    <item android:id="@id/secondaryProgress">
+        <scale android:scaleWidth="100%">
+            <nine-patch android:src="@drawable/progress_qntm_alpha"
+                android:tint="@color/control_activated_foreground_quantum_dark" />
+        </scale>
+    </item>
+    <item android:id="@id/progress">
+        <scale android:scaleWidth="100%">
+            <nine-patch android:src="@drawable/progress_primary_qntm_alpha"
+                android:tint="@color/control_activated_foreground_quantum_dark" />
+        </scale>
+    </item>
+</layer-list>
diff --git a/core/res/res/drawable/progress_horizontal_quantum_light.xml b/core/res/res/drawable/progress_horizontal_quantum_light.xml
new file mode 100644
index 0000000..1ceb2e2
--- /dev/null
+++ b/core/res/res/drawable/progress_horizontal_quantum_light.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@id/background">
+        <nine-patch android:src="@drawable/progress_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_light" />
+    </item>
+    <item android:id="@id/secondaryProgress">
+        <scale android:scaleWidth="100%">
+            <nine-patch android:src="@drawable/progress_qntm_alpha"
+                android:tint="@color/control_activated_foreground_quantum_light" />
+        </scale>
+    </item>
+    <item android:id="@id/progress">
+        <scale android:scaleWidth="100%">
+            <nine-patch android:src="@drawable/progress_primary_qntm_alpha"
+                android:tint="@color/control_activated_foreground_quantum_light" />
+        </scale>
+    </item>
+</layer-list>
diff --git a/core/res/res/drawable/scrollbar_handle_quantum_dark.xml b/core/res/res/drawable/scrollbar_handle_quantum_dark.xml
new file mode 100644
index 0000000..2d4e37d
--- /dev/null
+++ b/core/res/res/drawable/scrollbar_handle_quantum_dark.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/scrollbar_handle_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/scrollbar_handle_quantum_light.xml b/core/res/res/drawable/scrollbar_handle_quantum_light.xml
new file mode 100644
index 0000000..d4d4b8d
--- /dev/null
+++ b/core/res/res/drawable/scrollbar_handle_quantum_light.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/scrollbar_handle_qntm_alpha"
+    android:tint="@color/control_normal_foreground_quantum_light" />
diff --git a/core/res/res/drawable/scrubber_control_selector_quantum_dark.xml b/core/res/res/drawable/scrubber_control_selector_quantum_dark.xml
new file mode 100644
index 0000000..521bcca
--- /dev/null
+++ b/core/res/res/drawable/scrubber_control_selector_quantum_dark.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="true" android:state_pressed="true">
+        <bitmap android:src="@drawable/scrubber_control_on_pressed_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item>
+        <bitmap android:src="@drawable/scrubber_control_on_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_dark" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/scrubber_control_selector_quantum_light.xml b/core/res/res/drawable/scrubber_control_selector_quantum_light.xml
new file mode 100644
index 0000000..8d009b7
--- /dev/null
+++ b/core/res/res/drawable/scrubber_control_selector_quantum_light.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="true" android:state_pressed="true">
+        <bitmap android:src="@drawable/scrubber_control_on_pressed_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item>
+        <bitmap android:src="@drawable/scrubber_control_on_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_light" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/scrubber_progress_horizontal_quantum_dark.xml b/core/res/res/drawable/scrubber_progress_horizontal_quantum_dark.xml
new file mode 100644
index 0000000..fa0d631
--- /dev/null
+++ b/core/res/res/drawable/scrubber_progress_horizontal_quantum_dark.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true">
+        <bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item>
+        <bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_dark" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/scrubber_progress_horizontal_quantum_light.xml b/core/res/res/drawable/scrubber_progress_horizontal_quantum_light.xml
new file mode 100644
index 0000000..053f542
--- /dev/null
+++ b/core/res/res/drawable/scrubber_progress_horizontal_quantum_light.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true">
+        <bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item>
+        <bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_light" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/spinner_background_quantum_dark.xml b/core/res/res/drawable/spinner_background_quantum_dark.xml
new file mode 100644
index 0000000..d1e7407
--- /dev/null
+++ b/core/res/res/drawable/spinner_background_quantum_dark.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:autoMirrored="true">
+    <item android:state_checked="true">
+        <nine-patch android:src="@drawable/spinner_qntm_am_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item android:state_pressed="true">
+        <nine-patch android:src="@drawable/spinner_qntm_am_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item>
+        <nine-patch android:src="@drawable/spinner_qntm_am_alpha"
+            android:tint="@color/control_normal_foreground_quantum_dark" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/spinner_background_quantum_light.xml b/core/res/res/drawable/spinner_background_quantum_light.xml
new file mode 100644
index 0000000..b01628d
--- /dev/null
+++ b/core/res/res/drawable/spinner_background_quantum_light.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:autoMirrored="true">
+    <item android:state_checked="true">
+        <nine-patch android:src="@drawable/spinner_qntm_am_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item android:state_pressed="true">
+        <nine-patch android:src="@drawable/spinner_qntm_am_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item>
+        <nine-patch android:src="@drawable/spinner_qntm_am_alpha"
+            android:tint="@color/control_normal_foreground_quantum_light" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/switch_inner_quantum_dark.xml b/core/res/res/drawable/switch_inner_quantum_dark.xml
new file mode 100644
index 0000000..927a55e
--- /dev/null
+++ b/core/res/res/drawable/switch_inner_quantum_dark.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true" android:state_pressed="true">
+        <nine-patch android:src="@drawable/switch_on_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item android:state_checked="true">
+        <nine-patch android:src="@drawable/switch_on_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item android:state_pressed="true">
+        <nine-patch android:src="@drawable/switch_off_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item>
+        <nine-patch android:src="@drawable/switch_off_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_dark" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/switch_inner_quantum_light.xml b/core/res/res/drawable/switch_inner_quantum_light.xml
new file mode 100644
index 0000000..b5aa47b
--- /dev/null
+++ b/core/res/res/drawable/switch_inner_quantum_light.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true" android:state_pressed="true">
+        <nine-patch android:src="@drawable/switch_on_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item android:state_checked="true">
+        <nine-patch android:src="@drawable/switch_on_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item android:state_pressed="true">
+        <nine-patch android:src="@drawable/switch_off_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item>
+        <nine-patch android:src="@drawable/switch_off_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_light" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/switch_track_quantum_dark.xml b/core/res/res/drawable/switch_track_quantum_dark.xml
new file mode 100644
index 0000000..c018bd2
--- /dev/null
+++ b/core/res/res/drawable/switch_track_quantum_dark.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true">
+        <nine-patch android:src="@drawable/switch_track_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item>
+        <nine-patch android:src="@drawable/switch_track_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_dark" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/switch_track_quantum_light.xml b/core/res/res/drawable/switch_track_quantum_light.xml
new file mode 100644
index 0000000..ab87a57
--- /dev/null
+++ b/core/res/res/drawable/switch_track_quantum_light.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true">
+        <nine-patch android:src="@drawable/switch_track_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item>
+        <nine-patch android:src="@drawable/switch_track_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_light" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/tab_indicator_quantum_dark.xml b/core/res/res/drawable/tab_indicator_quantum_dark.xml
new file mode 100644
index 0000000..9b57c33
--- /dev/null
+++ b/core/res/res/drawable/tab_indicator_quantum_dark.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_selected="true" android:state_pressed="true">
+        <nine-patch android:src="@drawable/tab_indicator_selected_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item android:state_selected="true" android:state_focused="true">
+        <nine-patch android:src="@drawable/tab_indicator_selected_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item android:state_selected="true">
+        <nine-patch android:src="@drawable/tab_indicator_selected_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_dark" />
+    </item>
+
+    <item android:state_pressed="true">
+        <nine-patch android:src="@drawable/tab_indicator_normal_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item android:state_focused="true">
+        <nine-patch android:src="@drawable/tab_indicator_normal_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_dark" />
+    </item>
+    <item>
+        <nine-patch android:src="@drawable/tab_indicator_normal_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_dark" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/tab_indicator_quantum_light.xml b/core/res/res/drawable/tab_indicator_quantum_light.xml
new file mode 100644
index 0000000..371322a
--- /dev/null
+++ b/core/res/res/drawable/tab_indicator_quantum_light.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_selected="true" android:state_pressed="true">
+        <nine-patch android:src="@drawable/tab_indicator_selected_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item android:state_selected="true" android:state_focused="true">
+        <nine-patch android:src="@drawable/tab_indicator_selected_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item android:state_selected="true">
+        <nine-patch android:src="@drawable/tab_indicator_selected_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_light" />
+    </item>
+
+    <item android:state_pressed="true">
+        <nine-patch android:src="@drawable/tab_indicator_normal_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item android:state_focused="true">
+        <nine-patch android:src="@drawable/tab_indicator_normal_qntm_alpha"
+            android:tint="@color/control_activated_foreground_quantum_light" />
+    </item>
+    <item>
+        <nine-patch android:src="@drawable/tab_indicator_normal_qntm_alpha"
+            android:tint="@color/control_normal_foreground_quantum_light" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/text_cursor_quantum_dark.xml b/core/res/res/drawable/text_cursor_quantum_dark.xml
new file mode 100644
index 0000000..bd0d66f
--- /dev/null
+++ b/core/res/res/drawable/text_cursor_quantum_dark.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/text_cursor_qntm_alpha"
+    android:tint="@color/control_activated_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/text_cursor_quantum_light.xml b/core/res/res/drawable/text_cursor_quantum_light.xml
new file mode 100644
index 0000000..0ec7f01
--- /dev/null
+++ b/core/res/res/drawable/text_cursor_quantum_light.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/text_cursor_qntm_alpha"
+    android:tint="@color/control_activated_foreground_quantum_light" />
diff --git a/core/res/res/layout-xlarge/screen_action_bar.xml b/core/res/res/layout-xlarge/screen_action_bar.xml
index e495e53..d2fe9fa 100644
--- a/core/res/res/layout-xlarge/screen_action_bar.xml
+++ b/core/res/res/layout-xlarge/screen_action_bar.xml
@@ -34,6 +34,7 @@
         android:layout_height="wrap_content"
         android:layout_alignParentTop="true"
         style="?android:attr/actionBarStyle"
+        android:sharedElementName="android:action_bar"
         android:gravity="top">
         <com.android.internal.widget.ActionBarView
             android:id="@+id/action_bar"
diff --git a/core/res/res/layout/notification_quantum_action.xml b/core/res/res/layout/notification_quantum_action.xml
new file mode 100644
index 0000000..775182f
--- /dev/null
+++ b/core/res/res/layout/notification_quantum_action.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 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
+  -->
+
+<Button xmlns:android="http://schemas.android.com/apk/res/android"
+    style="?android:attr/borderlessButtonStyle" 
+    android:id="@+id/action0"
+    android:layout_width="0dp"
+    android:layout_height="48dp"
+    android:layout_weight="1"
+    android:gravity="start|center_vertical"
+    android:drawablePadding="8dp"
+    android:paddingStart="8dp"
+    android:textColor="#555555"
+    android:textSize="14dp"
+    android:singleLine="true"
+    android:ellipsize="end"
+    />
diff --git a/core/res/res/layout/notification_quantum_action_list.xml b/core/res/res/layout/notification_quantum_action_list.xml
new file mode 100644
index 0000000..a8aef97
--- /dev/null
+++ b/core/res/res/layout/notification_quantum_action_list.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/actions"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:visibility="gone"
+    android:layout_marginBottom="8dp"
+    android:showDividers="middle"
+    android:divider="?android:attr/listDivider"
+    android:dividerPadding="12dp"
+    >
+    <!-- actions will be added here -->
+</LinearLayout>
diff --git a/core/res/res/layout/notification_quantum_action_tombstone.xml b/core/res/res/layout/notification_quantum_action_tombstone.xml
new file mode 100644
index 0000000..9104991
--- /dev/null
+++ b/core/res/res/layout/notification_quantum_action_tombstone.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 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
+  -->
+
+<Button xmlns:android="http://schemas.android.com/apk/res/android"
+    style="?android:attr/borderlessButtonStyle" 
+    android:id="@+id/action0"
+    android:layout_width="0dp"
+    android:layout_height="48dp"
+    android:layout_weight="1"
+    android:gravity="start|center_vertical"
+    android:drawablePadding="8dp"
+    android:paddingStart="8dp"
+    android:textColor="#555555"
+    android:textSize="14dp"
+    android:singleLine="true"
+    android:ellipsize="end"
+    android:alpha="0.5"
+    android:enabled="false"
+    />
diff --git a/core/res/res/layout/notification_template_quantum_base.xml b/core/res/res/layout/notification_template_quantum_base.xml
new file mode 100644
index 0000000..3e97b2a
--- /dev/null
+++ b/core/res/res/layout/notification_template_quantum_base.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 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"
+    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+    android:background="@android:drawable/notification_quantum_bg"
+    android:id="@+id/status_bar_latest_event_content"
+    android:layout_width="match_parent"
+    android:layout_height="64dp"
+    internal:layout_minHeight="64dp"
+    internal:layout_maxHeight="64dp"
+    >
+    <ImageView android:id="@+id/icon"
+        android:layout_width="@dimen/notification_large_icon_width"
+        android:layout_height="@dimen/notification_large_icon_height"
+        android:scaleType="center"
+        />
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+
+        android:layout_gravity="fill_vertical"
+        android:layout_marginStart="@dimen/notification_large_icon_width"
+        android:minHeight="@dimen/notification_large_icon_height"
+        android:orientation="vertical"
+        android:paddingEnd="8dp"
+        android:paddingTop="2dp"
+        android:paddingBottom="2dp"
+        android:gravity="top"
+        >
+        <LinearLayout
+            android:id="@+id/line1"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="6dp"
+            android:layout_marginStart="8dp"
+            android:orientation="horizontal"
+            >
+            <TextView android:id="@+id/title"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Title"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:singleLine="true"
+                android:ellipsize="marquee"
+                android:fadingEdge="horizontal"
+                android:layout_weight="1"
+                />
+            <ViewStub android:id="@+id/time"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="0"
+                android:visibility="gone"
+                android:layout="@layout/notification_template_part_time"
+                />
+            <ViewStub android:id="@+id/chronometer"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="0"
+                android:visibility="gone"
+                android:layout="@layout/notification_template_part_chronometer"
+                />
+        </LinearLayout>
+        <TextView android:id="@+id/text2"
+            android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Line2"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="-2dp"
+            android:layout_marginBottom="-2dp"
+            android:layout_marginStart="8dp"
+            android:singleLine="true"
+            android:fadingEdge="horizontal"
+            android:ellipsize="marquee"
+            android:visibility="gone"
+            />
+        <ProgressBar
+            android:id="@android:id/progress"
+            android:layout_width="match_parent"
+            android:layout_height="12dp"
+            android:layout_marginStart="8dp"
+            android:visibility="gone"
+            style="?android:attr/progressBarStyleHorizontal"
+            />
+        <LinearLayout
+            android:id="@+id/line3"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:gravity="center_vertical"
+            android:layout_marginStart="8dp"
+            >
+            <TextView android:id="@+id/text"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:layout_gravity="center"
+                android:singleLine="true"
+                android:ellipsize="marquee"
+                android:fadingEdge="horizontal"
+                />
+            <TextView android:id="@+id/info"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Info"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:layout_weight="0"
+                android:singleLine="true"
+                android:gravity="center"
+                android:paddingStart="8dp"
+                />
+            <ImageView android:id="@+id/right_icon"
+                android:layout_width="16dp"
+                android:layout_height="16dp"
+                android:layout_gravity="center"
+                android:layout_weight="0"
+                android:layout_marginStart="8dp"
+                android:scaleType="centerInside"
+                android:visibility="gone"
+                android:drawableAlpha="153"
+                />
+        </LinearLayout>
+    </LinearLayout>
+</FrameLayout>
diff --git a/core/res/res/layout/notification_template_quantum_big_base.xml b/core/res/res/layout/notification_template_quantum_big_base.xml
new file mode 100644
index 0000000..d860045
--- /dev/null
+++ b/core/res/res/layout/notification_template_quantum_big_base.xml
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 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"
+    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+    android:background="@android:drawable/notification_quantum_bg"
+    android:id="@+id/status_bar_latest_event_content"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    internal:layout_minHeight="65dp"
+    internal:layout_maxHeight="unbounded"
+    >
+    <ImageView android:id="@+id/icon"
+        android:layout_width="@dimen/notification_large_icon_width"
+        android:layout_height="@dimen/notification_large_icon_height"
+        android:scaleType="center"
+        />
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="fill_vertical"
+        android:minHeight="@dimen/notification_large_icon_height"
+        android:orientation="vertical"
+        android:gravity="top"
+        >
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="@dimen/notification_large_icon_width"
+            android:minHeight="@dimen/notification_large_icon_height"
+            android:paddingTop="2dp"
+            android:orientation="vertical"
+            >
+            <LinearLayout
+                android:id="@+id/line1"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingTop="6dp"
+                android:layout_marginEnd="8dp"
+                android:layout_marginStart="8dp"
+                android:orientation="horizontal"
+                >
+                <TextView android:id="@+id/title"
+                    android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Title"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:fadingEdge="horizontal"
+                    android:layout_weight="1"
+                    />
+                <ViewStub android:id="@+id/time"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="0"
+                    android:visibility="gone"
+                    android:layout="@layout/notification_template_part_time"
+                    />
+                <ViewStub android:id="@+id/chronometer"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="0"
+                    android:visibility="gone"
+                    android:layout="@layout/notification_template_part_chronometer"
+                    />
+            </LinearLayout>
+            <TextView android:id="@+id/text2"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Line2"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="-2dp"
+                android:layout_marginBottom="-2dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:fadingEdge="horizontal"
+                android:ellipsize="marquee"
+                android:visibility="gone"
+                />
+            <TextView android:id="@+id/big_text"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="false"
+                android:visibility="gone"
+                />
+            <LinearLayout
+                android:id="@+id/line3"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:orientation="horizontal"
+                android:gravity="center_vertical"
+                >
+                <TextView android:id="@+id/text"
+                    android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:layout_gravity="center"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:fadingEdge="horizontal"
+                    />
+                <TextView android:id="@+id/info"
+                    android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Info"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:layout_weight="0"
+                    android:singleLine="true"
+                    android:gravity="center"
+                    android:paddingStart="8dp"
+                    />
+                <ImageView android:id="@+id/right_icon"
+                    android:layout_width="16dp"
+                    android:layout_height="16dp"
+                    android:layout_gravity="center"
+                    android:layout_weight="0"
+                    android:layout_marginStart="8dp"
+                    android:scaleType="centerInside"
+                    android:visibility="gone"
+                    android:drawableAlpha="153"
+                    />
+            </LinearLayout>
+            <ProgressBar
+                android:id="@android:id/progress"
+                android:layout_width="match_parent"
+                android:layout_height="12dp"
+                android:layout_marginBottom="8dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:visibility="gone"
+                style="?android:attr/progressBarStyleHorizontal"
+                />
+        </LinearLayout>
+        <ImageView
+            android:layout_width="match_parent"
+            android:layout_height="1dp"
+            android:id="@+id/action_divider"
+            android:visibility="gone"
+            android:background="?android:attr/dividerHorizontal" />
+        <include
+            layout="@layout/notification_quantum_action_list"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="@dimen/notification_large_icon_width"
+            />
+    </LinearLayout>
+</FrameLayout>
diff --git a/core/res/res/layout/notification_template_quantum_big_picture.xml b/core/res/res/layout/notification_template_quantum_big_picture.xml
new file mode 100644
index 0000000..e49c3bd
--- /dev/null
+++ b/core/res/res/layout/notification_template_quantum_big_picture.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 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"
+    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+    android:background="@android:drawable/notification_quantum_bg"
+    android:id="@+id/status_bar_latest_event_content"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    internal:layout_minHeight="65dp"
+    internal:layout_maxHeight="unbounded"
+    >
+    <ImageView
+        android:id="@+id/big_picture"
+        android:layout_width="match_parent"
+        android:layout_height="192dp"
+        android:layout_marginTop="64dp"
+        android:layout_gravity="bottom"
+        android:scaleType="centerCrop"
+        />
+    <ImageView
+        android:layout_width="match_parent"
+        android:layout_height="6dp"
+        android:layout_marginTop="64dp"
+        android:scaleType="fitXY"
+        android:src="@drawable/title_bar_shadow"
+        />
+    <include layout="@layout/notification_template_quantum_base"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        />
+  <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="208dp"
+        android:paddingStart="64dp"
+        android:layout_gravity="bottom"
+        android:background="#CCEEEEEE"
+        >
+        <include
+            layout="@layout/notification_quantum_action_list"
+            android:id="@+id/actions"
+            android:layout_gravity="bottom"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            />
+    </FrameLayout>
+</FrameLayout>
diff --git a/core/res/res/layout/notification_template_quantum_big_text.xml b/core/res/res/layout/notification_template_quantum_big_text.xml
new file mode 100644
index 0000000..585be80
--- /dev/null
+++ b/core/res/res/layout/notification_template_quantum_big_text.xml
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 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"
+    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+    android:background="@android:drawable/notification_quantum_bg"
+    android:id="@+id/status_bar_latest_event_content"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    internal:layout_minHeight="65dp"
+    internal:layout_maxHeight="unbounded"
+    >
+    <ImageView android:id="@+id/icon"
+        android:layout_width="@dimen/notification_large_icon_width"
+        android:layout_height="@dimen/notification_large_icon_height"
+        android:scaleType="center"
+        />
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="fill_vertical"
+        android:layout_marginStart="@dimen/notification_large_icon_width"
+        android:orientation="vertical"
+        android:paddingTop="0dp"
+        android:paddingBottom="2dp"
+        android:gravity="top"
+        >
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:minHeight="@dimen/notification_large_icon_height"
+            android:orientation="vertical"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
+            android:layout_weight="1"
+            >
+            <LinearLayout
+                android:id="@+id/line1"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingTop="8dp"
+                android:orientation="horizontal"
+                android:layout_gravity="top"
+                android:layout_weight="0"
+                >
+                <TextView android:id="@+id/title"
+                    android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Title"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:fadingEdge="horizontal"
+                    android:layout_weight="1"
+                    />
+                <ViewStub android:id="@+id/time"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="0"
+                    android:visibility="gone"
+                    android:layout="@layout/notification_template_part_time"
+                    />
+                <ViewStub android:id="@+id/chronometer"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="0"
+                    android:visibility="gone"
+                    android:layout="@layout/notification_template_part_chronometer"
+                    />
+            </LinearLayout>
+            <TextView android:id="@+id/text2"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Line2"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="-2dp"
+                android:layout_marginBottom="-2dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:fadingEdge="horizontal"
+                android:ellipsize="marquee"
+                android:layout_weight="0"
+                android:visibility="gone"
+                />
+            <ProgressBar
+                android:id="@android:id/progress"
+                android:layout_width="match_parent"
+                android:layout_height="12dp"
+                android:layout_marginBottom="8dp"
+                android:layout_marginEnd="8dp"
+                android:visibility="gone"
+                android:layout_weight="0"
+                style="?android:attr/progressBarStyleHorizontal"
+                />
+            <TextView android:id="@+id/big_text"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginBottom="10dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="false"
+                android:visibility="gone"
+                android:maxLines="8"
+                android:ellipsize="end"
+                android:layout_weight="1"
+                />
+        </LinearLayout>
+        <ImageView
+            android:layout_width="match_parent"
+            android:layout_height="1dip"
+            android:id="@+id/action_divider"
+            android:visibility="gone"
+            android:background="?android:attr/dividerHorizontal" />
+        <include
+            layout="@layout/notification_quantum_action_list"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:visibility="gone"
+            android:layout_weight="1"
+            />
+        <ImageView
+            android:layout_width="match_parent"
+            android:layout_height="1dp"
+            android:id="@+id/overflow_divider"
+            android:layout_marginBottom="8dp"
+            android:visibility="visible"
+            android:background="?android:attr/dividerHorizontal" />
+        <LinearLayout
+            android:id="@+id/line3"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="8dp"
+            android:layout_marginBottom="8dp"
+            android:layout_marginEnd="8dp"
+            android:orientation="horizontal"
+            android:layout_weight="0"
+            android:gravity="center_vertical"
+            >
+            <TextView android:id="@+id/text"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:layout_gravity="center"
+                android:singleLine="true"
+                android:ellipsize="marquee"
+                android:fadingEdge="horizontal"
+                />
+            <TextView android:id="@+id/info"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Info"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:layout_weight="0"
+                android:singleLine="true"
+                android:gravity="center"
+                android:paddingStart="8dp"
+                />
+            <ImageView android:id="@+id/right_icon"
+                android:layout_width="16dp"
+                android:layout_height="16dp"
+                android:layout_gravity="center"
+                android:layout_weight="0"
+                android:layout_marginStart="8dp"
+                android:scaleType="centerInside"
+                android:visibility="gone"
+                android:drawableAlpha="153"
+                />
+        </LinearLayout>
+    </LinearLayout>
+</FrameLayout>
diff --git a/core/res/res/layout/notification_template_quantum_inbox.xml b/core/res/res/layout/notification_template_quantum_inbox.xml
new file mode 100644
index 0000000..31ed508
--- /dev/null
+++ b/core/res/res/layout/notification_template_quantum_inbox.xml
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 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"
+    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+    android:id="@+id/status_bar_latest_event_content"
+    android:background="@android:drawable/notification_quantum_bg"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    internal:layout_minHeight="65dp"
+    internal:layout_maxHeight="unbounded"
+    >
+    <ImageView android:id="@+id/icon"
+        android:layout_width="@dimen/notification_large_icon_width"
+        android:layout_height="@dimen/notification_large_icon_height"
+        android:scaleType="center"
+        />
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="fill_vertical"
+        android:layout_marginStart="@dimen/notification_large_icon_width"
+        android:minHeight="@dimen/notification_large_icon_height"
+        android:orientation="vertical"
+        android:paddingTop="0dp"
+        android:paddingBottom="2dp"
+        android:gravity="top"
+        >
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:minHeight="@dimen/notification_large_icon_height"
+            android:paddingTop="2dp"
+            android:orientation="vertical"
+            >
+            <LinearLayout
+                android:id="@+id/line1"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:paddingTop="6dp"
+                android:orientation="horizontal"
+                android:layout_weight="0"
+                >
+                <TextView android:id="@+id/title"
+                    android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Title"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:fadingEdge="horizontal"
+                    android:layout_weight="1"
+                    />
+                <ViewStub android:id="@+id/time"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="0"
+                    android:visibility="gone"
+                    android:layout="@layout/notification_template_part_time"
+                    />
+                <ViewStub android:id="@+id/chronometer"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="0"
+                    android:visibility="gone"
+                    android:layout="@layout/notification_template_part_chronometer"
+                    />
+            </LinearLayout>
+            <TextView android:id="@+id/text2"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Line2"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="-2dp"
+                android:layout_marginBottom="-2dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:fadingEdge="horizontal"
+                android:ellipsize="marquee"
+                android:visibility="gone"
+                android:layout_weight="0"
+                />
+            <ProgressBar
+                android:id="@android:id/progress"
+                android:layout_width="match_parent"
+                android:layout_height="12dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:visibility="gone"
+                android:layout_weight="0"
+                style="?android:attr/progressBarStyleHorizontal"
+                />
+            <TextView android:id="@+id/inbox_text0"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text1"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text2"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text3"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text4"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text5"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_text6"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                />
+            <TextView android:id="@+id/inbox_more"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:ellipsize="end"
+                android:visibility="gone"
+                android:layout_weight="1"
+                android:text="@android:string/ellipsis"
+                />
+            <FrameLayout
+                android:id="@+id/inbox_end_pad"
+                android:layout_width="match_parent"
+                android:layout_height="8dip"
+                android:visibility="gone"
+                android:layout_weight="0"
+            />
+        </LinearLayout>
+        <ImageView
+            android:layout_width="match_parent"
+            android:layout_height="1dip"
+            android:id="@+id/action_divider"
+            android:visibility="gone"
+            android:background="?android:attr/dividerHorizontal" />
+        <include
+            layout="@layout/notification_quantum_action_list"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="0"
+            />
+        <ImageView
+            android:layout_width="match_parent"
+            android:layout_height="1dip"
+            android:id="@+id/overflow_divider"
+            android:visibility="visible"
+            android:background="?android:attr/dividerHorizontal" />
+        <LinearLayout
+            android:id="@+id/line3"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="8dp"
+            android:layout_marginStart="8dp"
+            android:layout_marginBottom="8dp"
+            android:layout_marginEnd="8dp"
+            android:orientation="horizontal"
+            android:layout_weight="0"
+            android:gravity="center_vertical"
+            >
+            <TextView android:id="@+id/text"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:layout_gravity="center"
+                android:singleLine="true"
+                android:ellipsize="marquee"
+                android:fadingEdge="horizontal"
+                />
+            <TextView android:id="@+id/info"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Info"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:layout_weight="0"
+                android:singleLine="true"
+                android:gravity="center"
+                android:paddingStart="8dp"
+                />
+            <ImageView android:id="@+id/right_icon"
+                android:layout_width="16dp"
+                android:layout_height="16dp"
+                android:layout_gravity="center"
+                android:layout_weight="0"
+                android:layout_marginStart="8dp"
+                android:scaleType="centerInside"
+                android:visibility="gone"
+                android:drawableAlpha="153"
+                />
+        </LinearLayout>
+    </LinearLayout>
+</FrameLayout>
diff --git a/core/res/res/layout/number_picker_with_selector_wheel_micro.xml b/core/res/res/layout/number_picker_with_selector_wheel_micro.xml
new file mode 100644
index 0000000..a1c09214
--- /dev/null
+++ b/core/res/res/layout/number_picker_with_selector_wheel_micro.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <view class="android.widget.NumberPicker$CustomEditText"
+        android:textAppearance="?android:attr/textAppearanceLarge"
+        android:id="@+id/numberpicker_input"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center"
+        android:singleLine="true"
+        android:background="@null" />
+
+</merge>
diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml
index b1889a2..3265736 100644
--- a/core/res/res/layout/screen_action_bar.xml
+++ b/core/res/res/layout/screen_action_bar.xml
@@ -23,7 +23,8 @@
     android:id="@+id/action_bar_overlay_layout"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:splitMotionEvents="false">
+    android:splitMotionEvents="false"
+    android:theme="?attr/actionBarTheme">
     <FrameLayout android:id="@android:id/content"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent" />
@@ -33,6 +34,7 @@
         android:layout_height="wrap_content"
         android:layout_alignParentTop="true"
         style="?android:attr/actionBarStyle"
+        android:sharedElementName="android:action_bar"
         android:gravity="top">
         <com.android.internal.widget.ActionBarView
             android:id="@+id/action_bar"
diff --git a/core/res/res/layout/screen_custom_title.xml b/core/res/res/layout/screen_custom_title.xml
index e3364d1..d02cc8b 100644
--- a/core/res/res/layout/screen_custom_title.xml
+++ b/core/res/res/layout/screen_custom_title.xml
@@ -31,6 +31,7 @@
     <FrameLayout android:id="@android:id/title_container" 
         android:layout_width="match_parent" 
         android:layout_height="?android:attr/windowTitleSize"
+        android:sharedElementName="android:title"
         style="?android:attr/windowTitleBackgroundStyle">
     </FrameLayout>
     <FrameLayout android:id="@android:id/content"
diff --git a/core/res/res/layout/screen_swipe_dismiss.xml b/core/res/res/layout/screen_swipe_dismiss.xml
new file mode 100644
index 0000000..90e970fe
--- /dev/null
+++ b/core/res/res/layout/screen_swipe_dismiss.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!--
+This is a layout for a window whose resident activity is finished when swiped away.
+-->
+
+<com.android.internal.widget.SwipeDismissLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/content"
+    android:fitsSystemWindows="true"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    />
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 4f38a82..c92ecb3 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -46,7 +46,7 @@
     <string name="badPin" msgid="9015277645546710014">"የተየበከው የድሮ ፒን ትክክል አይደለም።"</string>
     <string name="badPuk" msgid="5487257647081132201">"የተየብከው PUK ትክክል  አይደለም።"</string>
     <string name="mismatchPin" msgid="609379054496863419">"ያስገባሃቸው ፒኖች አይዛመዱም"</string>
-    <string name="invalidPin" msgid="3850018445187475377">"ከ4 እስከ 8 ቁጥሮች የያዘ PIN ተይብ"</string>
+    <string name="invalidPin" msgid="3850018445187475377">"ከ4 እስከ 8 ቁጥሮች የያዘ ፒን  ተይብ"</string>
     <string name="invalidPuk" msgid="8761456210898036513">"8 ወይም ከዛ በላይ የሆኑ ቁጥሮችንPUK ተይብ።"</string>
     <string name="needPuk" msgid="919668385956251611">"SIM ካርድዎ PUK-የተቆለፈ ነው።የPUK ኮዱን በመተየብ ይክፈቱት።"</string>
     <string name="needPuk2" msgid="4526033371987193070">" SIM ለመክፈት PUK2 ተይብ።"</string>
@@ -832,7 +832,7 @@
     <string name="keyguard_password_entry_touch_hint" msgid="7858547464982981384"><font size="17">"የይለፍ ቃል ለመተየብ ንካ"</font></string>
     <string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"ለመክፈት የይለፍ ቃል ተይብ"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"ለመክፈት ፒን ተይብ"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"ትክክል ያልሆነ PIN ኮድ።"</string>
+    <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"ትክክል ያልሆነ ፒን  ኮድ።"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"ለመክፈት፣ምናሌ ተጫን ከዛ 0"</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"የአደጋ ጊዜቁጥር"</string>
     <string name="lockscreen_carrier_default" msgid="8963839242565653192">"ከአገልግሎት መስጫ ክልል ውጪ"</string>
@@ -994,8 +994,8 @@
     <string name="searchview_description_submit" msgid="2688450133297983542">"ጥያቄ አስረክብ"</string>
     <string name="searchview_description_voice" msgid="2453203695674994440">"የድምፅ ፍለጋ"</string>
     <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"በመንካት አስስ ይንቃ?"</string>
-    <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g>  ማሰስን በንኪ ማንቃት ይፈልጋል። አስስ በንኪ በሚበራበት ጊዜ፣ ከጡባዊ ተኮው ጋር ለመግባባት ምን በጣትህ ስር ወይም ምልክቶችን ማከናወን እንዳለብህ ማብራሪያ ልታይ ወይም ልትሰማ ትችላለህ።"</string>
-    <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g>  ማሰስን በንኪ ማንቃት ይፈልጋል። አስስ በንኪ በሚበራበት ጊዜ፣ ከስልኩ ጋር ለመግባባት ምን በጣትህ ስር ወይም ምልክቶችን ማከናወን እንዳለብህ ማብራሪያ ልታይ ወይም ልትሰማ ትችላለህ።"</string>
+    <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g>  ማሰስን በንኪ ማንቃት ይፈልጋል። አስስ በንኪ በሚበራበት ጊዜ፣ ከጡባዊ ተኮው ጋር ለመግባባት ምን በጣትዎ ስር ወይም ምልክቶችን ማከናወን እንዳለብዎ ማብራሪያ ሊመለከቱ ወይም ሊሰሙ ይችላሉ።"</string>
+    <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g>  ማሰስን በንኪ ማንቃት ይፈልጋል። አስስ በንኪ በሚበራበት ጊዜ፣ ከስልኩ ጋር ለመግባባት ምን በጣትዎ ስር ወይም ምልክቶችን ማከናወን እንዳለብዎ ማብራሪያ ሊመለከቱ ወይም ሊሰሙ ይችላሉ።"</string>
     <string name="oneMonthDurationPast" msgid="7396384508953779925">"ከ1 ወር በፊት"</string>
     <string name="beforeOneMonthDurationPast" msgid="909134546836499826">"ከ1 ወር በፊት"</string>
   <plurals name="num_seconds_ago">
@@ -1241,7 +1241,7 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"ጊዜ አዘጋጅ"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"ውሂብ አዘጋጅ"</string>
     <string name="date_time_set" msgid="5777075614321087758">"አዘጋጅ"</string>
-    <string name="date_time_done" msgid="2507683751759308828">"ተጠናቋል"</string>
+    <string name="date_time_done" msgid="2507683751759308828">"ተከናውኗል"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"አዲስ፦ "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"በ<xliff:g id="APP_NAME">%1$s</xliff:g> የቀረበ።"</string>
     <string name="no_permissions" msgid="7283357728219338112">"ምንም ፍቃዶች አይጠየቁም"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 50c7187..cde9bdf 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -683,8 +683,8 @@
     <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Permet que l\'aplicació modifiqui les marques de sòcols per a l\'encaminament"</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"accedeix a les notificacions"</string>
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permet que l\'aplicació recuperi, examini i esborri les notificacions, incloses les que han publicat altres aplicacions."</string>
-    <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"vincula a un servei de processament de notificacions"</string>
-    <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permet que el titular vinculi la interfície de nivell superior d\'un servei de processament de notificacions. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
+    <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"vincula a un servei oient de notificacions"</string>
+    <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permet que el titular vinculi la interfície de nivell superior d\'un servei oient de notificacions. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invoca l\'aplicació de configuració proporcionada per l\'operador"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permet que el titular invoqui l\'aplicació de configuració proporcionada per l\'operador. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"conèixer les observacions sobre les condicions de la xarxa"</string>
@@ -1346,7 +1346,7 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Accessibilitat"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fons de pantalla"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Canvia el fons de pantalla"</string>
-    <string name="notification_listener_binding_label" msgid="2014162835481906429">"Processador de notificacions"</string>
+    <string name="notification_listener_binding_label" msgid="2014162835481906429">"Oient de notificacions"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ha activat VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toca per gestionar la xarxa."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 69ca648..010f812 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -563,8 +563,8 @@
     <string name="permdesc_modifyPhoneState" msgid="1029877529007686732">"Umožňuje aplikaci ovládat telefonní funkce zařízení. Aplikace s tímto oprávněním smí bez upozornění přepínat sítě, zapínat a vypínat bezdrátový modul telefonu a podobně."</string>
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"čtení stavu a identity telefonu"</string>
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Umožňuje aplikaci získat přístup k telefonním funkcím zařízení. Toto oprávnění umožňuje aplikaci zjistit telefonní číslo telefonu, identifikační čísla zařízení, zda zrovna probíhá hovor, a vzdálené číslo, ke kterému je hovor připojen."</string>
-    <string name="permlab_readPrecisePhoneState" msgid="5476483020282007597">"čtení přesných stavů telefonů"</string>
-    <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"Umožňuje aplikaci používat přesné stavy telefonů. Toto oprávnění aplikaci umožňuje zjistit skutečný stav volání, zda je volání aktivní nebo na pozadí, zda volání selhalo, přesný stav datového připojení a zda datové připojení selhalo."</string>
+    <string name="permlab_readPrecisePhoneState" msgid="5476483020282007597">"čtení přesného stavu telefonování"</string>
+    <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"Umožňuje aplikaci zjišťovat přesný stav telefonování a mobilních dat. Toto oprávnění aplikaci umožňuje zjistit skutečný stav volání, zda je volání aktivní nebo na pozadí, zda volání selhalo, přesný stav datového připojení a zda datové připojení selhalo."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"bránění přechodu tabletu do režimu spánku"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"bránění přechodu telefonu do režimu spánku"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"Umožňuje aplikaci zabránit přechodu tabletu do režimu spánku."</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 6b12c26..545b317 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -563,7 +563,7 @@
     <string name="permdesc_modifyPhoneState" msgid="1029877529007686732">"Permite que la aplicación controle las funciones de teléfono del dispositivo. Una aplicación con este permiso puede cambiar redes, encender y apagar la radio del teléfono y tareas similares sin siquiera notificártelo."</string>
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"leer la identidad y el estado del dispositivo"</string>
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite que la aplicación acceda a las funciones de teléfono del dispositivo. La aplicación puede utilizar este permiso para descubrir identificadores de dispositivos y números de teléfono, para saber si una llamada está activa y para conocer el número remoto con el que se ha establecido conexión mediante una llamada."</string>
-    <string name="permlab_readPrecisePhoneState" msgid="5476483020282007597">"Leer estados precisos del teléfono"</string>
+    <string name="permlab_readPrecisePhoneState" msgid="5476483020282007597">"leer estados precisos del teléfono"</string>
     <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"Permite que la aplicación acceda a los estados precisos del teléfono y determine el estado real de la llamada, si hay una llamada activa o en segundo plano, si se produjeron fallos en la llamada, el estado preciso de la conexión de datos y si hubo fallos relacionados con la conexión de datos."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"evitar que el tablet entre en estado de inactividad"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"evitar que el dispositivo entre en estado de inactividad"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 1fed273..1f2a6cc 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -423,7 +423,7 @@
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"‏اجازه می‎دهد برنامه از هر رمزگشای رسانه نصب شده‌ای استفاده کند تا برای پخش رمزگشایی شود."</string>
     <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"مدیریت اطلاعات کاربری مورد اعتماد"</string>
     <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"‏به برنامه امکان می‌دهد گواهینامه‌های CA را به عنوان اطلاعات کاربری مورد اعتماد نصب یا حذف نصب کند."</string>
-    <string name="permlab_bindIdleService" msgid="816311765497613780">"اجرای برنامه در هنگام بی‌حرکت بودن دستگاه"</string>
+    <string name="permlab_bindIdleService" msgid="816311765497613780">"اجرای برنامه در هنگام بدون فعالیت بودن دستگاه"</string>
     <string name="permdesc_bindIdleService" msgid="1767538493214100612">"‏این مجوز به سیستم Android امکان می‌دهد تا وقتی دستگاه استفاده نمی‌شود برنامه را در پس‌زمینه اجرا کند."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"خواندن/نوشتن منابع متعلق به تشخیص"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"‏به برنامه اجازه می‌دهد هر منبعی را که متعلق به گروه تشخیص است بخواند و در آن بنویسد؛ به‌عنوان مثال، فایل‌های /dev. این امر به‌صورت بالقوه می‌تواند بر پایدار بودن و امنیت سیستم تأثیر بگذارد. این تنها باید برای تشخیص‎‌های مختص سخت‌افزار توسط تولیدکننده یا اپراتور استفاده شود."</string>
@@ -564,7 +564,7 @@
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"خواندن وضعیت تلفن و شناسه"</string>
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"به برنامه اجازه می‌دهد به ویژگی‌های تلفن دستگاه شما دسترسی پیدا کند. این مجوز به برنامه اجازه می‌دهد شماره تلفن و شناسه‌های دستگاه، فعال بودن یک تماس و شماره راه دوری که با یک تماس متصل شده است را مشخص کند."</string>
     <string name="permlab_readPrecisePhoneState" msgid="5476483020282007597">"خواندن وضعیت‌های دقیق تلفن"</string>
-    <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"به برنامه امکان می‌دهد به وضعیت‌های دقیق تلفن دسترسی داشته باشد. این مجوز به برنامه امکان می‌دهد وضعیت واقعی تماس اینکه آیا تماس فعال است یا در پس‌زمینه قرار دارد، تماس‌های ناموفق، وضعیت دقیق اتصال داده و اتصال‌های ناموفق داده را تعیین کند."</string>
+    <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"به برنامه امکان می‌دهد به وضعیت‌های دقیق تلفن دسترسی داشته باشد. این مجوز به برنامه امکان می‌دهد وضعیت واقعی تماس، اینکه آیا تماس فعال است یا در پس‌زمینه قرار دارد، تماس‌های ناموفق، وضعیت دقیق اتصال داده و اتصال‌های ناموفق داده را تعیین کند."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ممانعت از به خواب رفتن رایانهٔ لوحی"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ممانعت از به خواب رفتن تلفن"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"‏به برنامه اجازه می‎دهد تا از غیرفعال شدن رایانهٔ لوحی جلوگیری کند."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 4504bad..b048bbc 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -635,7 +635,7 @@
     <string name="permlab_bluetooth" msgid="6127769336339276828">"uparivanje s Bluetooth uređajima"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Aplikaciji omogućuje pregled konfiguracije Bluetootha na tabletnom računalu te uspostavljanje i prihvaćanje veza s uparenim uređajima."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Aplikaciji omogućuje pregled konfiguracije Bluetootha na telefonu te uspostavljanje i prihvaćanje veza s uparenim uređajima."</string>
-    <string name="permlab_nfc" msgid="4423351274757876953">"upravljaj beskontaktnom (NFC) komunikacijom"</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"upravljanje beskontaktnom komunikacijom (NFC)"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"Aplikaciji omogućuje komunikaciju s oznakama, karticama i čitačima komunikacije kratkog dometa (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="3598496301486439258">"onemogućavanje zaključavanja zaslona"</string>
     <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Aplikaciji omogućuje onemogućavanje zaključavanja tipkovnice i svih pripadajućih sigurnosnih zaporki. Na primjer, telefon onemogućuje zaključavanje tipkovnice kod primanja dolaznog telefonskog poziva, nakon kojeg se zaključavanje tipkovnice ponovo omogućuje."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 92ab180..1547900 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -564,7 +564,7 @@
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"telefonállapot és azonosító olvasása"</string>
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Lehetővé teszi az alkalmazás számára, hogy hozzáférjen az eszköz telefonálási funkcióihoz. Az engedéllyel rendelkező alkalmazás meghatározhatja a telefonszámot és eszközazonosítókat, hogy egy hívás aktív-e, valamint híváskor a másik fél telefonszámát."</string>
     <string name="permlab_readPrecisePhoneState" msgid="5476483020282007597">"pontos telefonállapot megállapítása"</string>
-    <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"Engedélyezi, hogy az alkalmazás hozzáférjen a pontos telefonállapothoz. Az ilyen engedéllyel rendelkező alkalmazás képes meghatározni a valós hívási állapotot: hogy egy hívás aktív-e vagy a háttérben van, a hívás meghiúsult-e, illetve a pontos adatkapcsoltot és az adatkapcsolati műveletek meghiúsulását."</string>
+    <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"Engedélyezi, hogy az alkalmazás hozzáférjen a pontos telefonállapothoz. Az ilyen engedéllyel rendelkező alkalmazás képes meghatározni a valós hívási állapotot, azt, hogy egy hívás aktív-e vagy a háttérben van, a hívás meghiúsult-e, illetve képes meghatározni az adatkapcsolat pontos állapotát és az adatkapcsolati műveletek meghiúsulását."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"táblagép alvás üzemmódjának megakadályozása"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"telefon alvó üzemmódjának megakadályozása"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"Lehetővé teszi az alkalmazás számára, hogy megakadályozza, hogy a táblagép alvó üzemmódra váltson."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 096c4ed..d3e1cdd 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -605,7 +605,7 @@
     <string name="permlab_accessNetworkState" msgid="4951027964348974773">"הצג חיבורי רשת"</string>
     <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"מאפשר לאפליקציה להציג מידע לגבי חיבורי רשת, למשל, אילו רשתות קיימות ומחוברות."</string>
     <string name="permlab_createNetworkSockets" msgid="8018758136404323658">"גישת רשת מלאה"</string>
-    <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"‏מאפשר לאפליקציה ליצור Sockets ולהשתמש בפרוטוקולי רשת מותאמים אישית. הדפדפן ואפליקציות  אחרות מספקות אמצעים לשליחת נתונים לאינטרנט, כך שאישור זה אינו נחוץ לשליחת נתונים לאינטרנט."</string>
+    <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"‏מאפשר לאפליקציה ליצור Sockets ולהשתמש בפרוטוקולי רשת מותאמים אישית. הדפדפן, כמו אפליקציות  אחרות, מספק אמצעים לשליחת נתונים לאינטרנט, כך שאישור זה אינו נחוץ לשליחת נתונים לאינטרנט."</string>
     <string name="permlab_writeApnSettings" msgid="505660159675751896">"שנה/עכב הגדרות רשת ותנועה"</string>
     <string name="permdesc_writeApnSettings" msgid="5333798886412714193">"‏מאפשר לאפליקציה לשנות את הגדרות הרשת ולעכב ולבדוק את כל תנועת הרשת, לדוגמה, לשנות את ה-proxy והיציאה של כל רשת APN. אפליקציות זדוניות עלולות לעקוב אחר חבילות רשת, לבצע הפניה מחדש שלהן או לשנות אותן, ללא ידיעתך."</string>
     <string name="permlab_changeNetworkState" msgid="958884291454327309">"שנה את קישוריות הרשת"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index e08dd93..a8cb3d2 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -564,7 +564,7 @@
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"skaityti telefono būseną ir tapatybę"</string>
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Leidžiama programai pasiekti telefono funkcijas įrenginyje. Šis leidimas suteikia teisę programai nustatyti telefono numerį ir įrenginio ID, tai, ar skambutis aktyvus, ir skambučiu prijungtą nuotolinį numerį."</string>
     <string name="permlab_readPrecisePhoneState" msgid="5476483020282007597">"skaityti tikslias telefono būsenas"</string>
-    <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"Programai leidžiama pasiekti tikslias telefono būsenas. Šiuo leidimu programai leidžiama nustatyti tikrą skambučio būseną, ar skambutis yra aktyvus, ar vyksta fone, ar paskambinti nepavyksta, tikslią duomenų ryšio būseną ir ar nepavyksta užmegzto duomenų ryšio."</string>
+    <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"Programai leidžiama pasiekti tikslias telefono būsenas. Šiuo leidimu programai leidžiama nustatyti tikrą skambučio būseną, ar skambutis yra aktyvus, ar vyksta fone, ar paskambinti nepavyksta, tikslią duomenų ryšio būseną ir ar nepavyksta užmegzti duomenų ryšio."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"neleisti planšetiniam kompiuteriui užmigti"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"neleisti telefonui snausti"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"Leidžiama programai neleisti planšetiniam kompiuteriui užmigti."</string>
diff --git a/core/res/res/values-mcc440-mnc20/config.xml b/core/res/res/values-mcc440-mnc20/config.xml
index ba709fa..62001d9 100644
--- a/core/res/res/values-mcc440-mnc20/config.xml
+++ b/core/res/res/values-mcc440-mnc20/config.xml
@@ -23,6 +23,6 @@
 
     <!-- Configure mobile network MTU. Carrier specific value is set here.
     -->
-    <integer name="config_mobile_mtu">1340</integer>
+    <integer name="config_mobile_mtu">1422</integer>
 
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 2e584e5..6eae123 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -564,7 +564,7 @@
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"lese telefonstatus og -identitet"</string>
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Lar appen bruke enhetens telefonfunksjoner. Med denne tillatelsen kan appen finne telefonnummer og enhets-ID-er, registrere om en samtale pågår, og se det eksterne nummeret det opprettes en forbindelse med via oppringing."</string>
     <string name="permlab_readPrecisePhoneState" msgid="5476483020282007597">"lese nøyaktige telefontilstander"</string>
-    <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"Gir appen tillatelse til å bruke nøyaktige telefontilstander. Denne tillatelsen gjør at appen kan fastslå den faktiske anropstatusen, om et anrop er aktivt eller i bakgrunnen, anropsfeil, nøyaktig status for datatilkobling og datatilkoblingsfeil."</string>
+    <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"Gir appen tilgang til nøyaktige telefontilstander. Denne tillatelsen gjør at appen kan fastslå den faktiske anropstatusen, om et anrop er aktivt eller i bakgrunnen, anropsfeil, nøyaktig status for datatilkobling og datatilkoblingsfeil."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"hindre nettbrettet fra å gå over til sovemodus"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"forhindre telefonen fra å sove"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"Lar appen hindre nettbrettet fra å gå over i sovemodus."</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index e0433a6..7610c06 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -423,7 +423,7 @@
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Permite aplicaţiei să utilizeze orice decodor media instalat pentru a decodifica redarea."</string>
     <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"gestionarea acreditărilor de încredere"</string>
     <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Permite aplicației să instaleze și să dezinstaleze certificate CA ca acreditări de încredere."</string>
-    <string name="permlab_bindIdleService" msgid="816311765497613780">"rulați aplicația în timp ce dispozitivul este inactiv"</string>
+    <string name="permlab_bindIdleService" msgid="816311765497613780">"rulează aplicația în timp ce dispozitivul este inactiv"</string>
     <string name="permdesc_bindIdleService" msgid="1767538493214100612">"Cu această permisiune, sistemul Android poate rula aplicația în fundal în timp ce dispozitivul nu este utilizat."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"citire/scriere în resursele deţinute de diag"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Permite aplicaţiei să citească şi să scrie în orice resursă deţinută de grupul diag, de ex., fişierele din /dev. Această permisiune ar putea să afecteze stabilitatea şi securitatea sistemului. Permisiunea trebuie utilizată NUMAI de producător sau de operator pentru diagnostice specifice pentru hardware."</string>
@@ -564,7 +564,7 @@
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"citeşte starea şi identitatea telefonului"</string>
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permite aplicaţiei să acceseze funcţiile de telefon ale dispozitivului. Cu această permisiune aplicaţia stabileşte numărul de telefon şi ID-urile de dispozitiv, dacă un apel este activ, precum şi numărul de la distanţă conectat printr-un apel."</string>
     <string name="permlab_readPrecisePhoneState" msgid="5476483020282007597">"accesați stările exacte ale telefonului"</string>
-    <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"Permite aplicației să acceseze stările exacte ale telefonului. Cu această permisiune, aplicația poate să determine starea reală a apelului, dacă apelul este activ sau în fundal, dacă apelul nu reușește, starea exactă și întreruperile conexiunii de date."</string>
+    <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"Permite aplicației să acceseze stările exacte ale telefonului. Cu această permisiune, aplicația poate să determine starea reală a apelului, dacă apelul este activ sau în fundal, dacă apelul eșuează, starea exactă și întreruperile conexiunii de date."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"împiedicarea computerului tablet PC să intre în repaus"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"împiedicare intrare telefon în repaus"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"Permite aplicaţiei să împiedice intrarea tabletei în stare de repaus."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 6d8aca7..2ffc435 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -423,8 +423,8 @@
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Приложение сможет использовать любой установленный дешифратор."</string>
     <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"Управление учетными данными"</string>
     <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Приложение сможет устанавливать сертификаты ЦС в качестве надежных учетных данных, а также удалять их."</string>
-    <string name="permlab_bindIdleService" msgid="816311765497613780">"запуск приложений в свящем режиме"</string>
-    <string name="permdesc_bindIdleService" msgid="1767538493214100612">"Система Android сможет запускать приложение в фоновом режиме, когда устройство не будет использоваться."</string>
+    <string name="permlab_bindIdleService" msgid="816311765497613780">"выполнение приложения в спящем режиме"</string>
+    <string name="permdesc_bindIdleService" msgid="1767538493214100612">"Система Android сможет выполнять приложение в фоновом режиме, когда устройство не используется."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"Чтение/запись данных в системы диагностики"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Приложение сможет считывать и записывать данные системы диагностики (например, файлы в каталоге /dev). Это может повлиять на стабильность и безопасность системы. Это разрешение должно использоваться ТОЛЬКО производителем или оператором для диагностики аппаратного обеспечения."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"Включение/отключение компонентов приложения"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 1d5772b..d3934a9 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -190,7 +190,7 @@
     <string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Prístup k zariadeniam a sieťam prostredníctvom rozhrania Bluetooth."</string>
     <string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Nastavenia zvuku"</string>
     <string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Zmena nastavení zvuku."</string>
-    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Má vplyv na batériu"</string>
+    <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Vplyv na batériu"</string>
     <string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Používanie funkcií, ktoré môžu rýchlo vyčerpať batériu."</string>
     <string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalendár"</string>
     <string name="permgroupdesc_calendar" msgid="5777534316982184416">"Priamy prístup ku kalendáru a udalostiam."</string>
@@ -232,7 +232,7 @@
     <string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Funkcie len pre vývojárov aplikácií."</string>
     <string name="permgrouplab_display" msgid="4279909676036402636">"Používateľské rozhranie iných aplikácií"</string>
     <string name="permgroupdesc_display" msgid="6051002031933013714">"Vplyv na používateľské rozhranie ďalších aplikácií."</string>
-    <string name="permgrouplab_storage" msgid="1971118770546336966">"Ukladací priestor"</string>
+    <string name="permgrouplab_storage" msgid="1971118770546336966">"Úložisko"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Prístup do ukl. priestoru USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Prístup na kartu SD."</string>
     <string name="permgrouplab_accessibilityFeatures" msgid="7919025602283593907">"Funkcie zjednodušenia ovládania"</string>
@@ -566,7 +566,7 @@
     <string name="permlab_readPrecisePhoneState" msgid="5476483020282007597">"čítanie presných stavov telefónu"</string>
     <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"Umožňuje aplikácii pristupovať k presným stavom telefónu. Toto povolenie umožňuje aplikácii zistiť skutočný stav hovoru, či je hovor aktívny alebo na pozadí, zlyhania hovorov, presný stav dátového pripojenia a zlyhania dátového pripojenia."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"zabránenie prechodu tabletu do režimu spánku"</string>
-    <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"zabránenie prechodu telefónu do režimu spánku"</string>
+    <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"deaktivácia režimu spánku"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"Umožňuje aplikácii zabrániť prechodu tabletu do režimu spánku."</string>
     <string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"Umožňuje aplikácii zabrániť prechodu telefónu do režimu spánku."</string>
     <string name="permlab_transmitIr" msgid="7545858504238530105">"infračervený prenos"</string>
@@ -637,7 +637,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Umožňuje aplikácii zobraziť informácie o konfigurácii Bluetooth na telefóne. Taktiež jej umožňuje nadväzovať a akceptovať spojenia so spárovanými zariadeniami."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"ovládať technológiu Near Field Communication"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"Umožňuje aplikácii komunikovať so značkami, kartami a čítačkami s podporou technológie Near Field Communication (NFC)."</string>
-    <string name="permlab_disableKeyguard" msgid="3598496301486439258">"zakázať uzamknutie obrazovky"</string>
+    <string name="permlab_disableKeyguard" msgid="3598496301486439258">"deaktivácia zámky obrazovky"</string>
     <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Umožňuje aplikácii zakázať uzamknutie klávesnice a akékoľvek súvisiace zabezpečenie heslom. Príkladom je zakázanie uzamknutia klávesnice pri prichádzajúcom telefonickom hovore a jeho opätovné povolenie po skončení hovoru."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"čítanie nastavení synchronizácie"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Umožňuje aplikácii čítať nastavenia synchronizácie v účte. Môže napríklad určiť, či je s účtom synchronizovaná aplikácia Ľudia."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 5e8c45b..783b0a4 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -424,7 +424,7 @@
     <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"upravljanje preverjenih poverilnic"</string>
     <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Aplikaciji dovoli nameščanje in odstranjevanje potrdil overitelja potrdil kot preverjenih poverilnic."</string>
     <string name="permlab_bindIdleService" msgid="816311765497613780">"izvajanje aplikacije ob nedejavnosti"</string>
-    <string name="permdesc_bindIdleService" msgid="1767538493214100612">"To dovoljenje sistemu Android omogoča, da izvaja aplikacijo v ozadju, ko se naprava ne uporablja."</string>
+    <string name="permdesc_bindIdleService" msgid="1767538493214100612">"To dovoljenje sistemu Android omogoča, da izvaja aplikacijo v ozadju, ko naprava ni v uporabi."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"branje/pisanje v sredstva, ki so v lasti skupine za diagnostiko"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Programu omogoča branje in pisanje na poljuben vir, ki je v lasti skupine za diagnostiko; na primer datoteke v mapi /dev. To lahko vpliva na stabilnost in varnost sistema. To naj uporablja SAMO izdelovalec ali operater za diagnostiko, specifično za strojno opremo."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"omogočanje ali onemogočanje komponent programa"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 7cbe055..d6f7457 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1461,7 +1461,7 @@
     <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Gränsen för data via Wi-Fi har överskridits"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> över angiven gräns."</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"Bakgrundsdata är begränsade"</string>
-    <string name="data_usage_restricted_body" msgid="6741521330997452990">"Tryck för att radera begränsning"</string>
+    <string name="data_usage_restricted_body" msgid="6741521330997452990">"Tryck för att ta bort begränsning"</string>
     <string name="ssl_certificate" msgid="6510040486049237639">"Säkerhetscertifikat"</string>
     <string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Certifikatet är giltigt."</string>
     <string name="issued_to" msgid="454239480274921032">"Utfärdad till:"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 87afca6..7f17c76 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -423,8 +423,8 @@
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Huruhusu programu kutumia vyombo vyovyote vya habari vilivyosakinishwa ili kusimbua kwa ajili ya kucheza tena."</string>
     <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"dhibiti vitambulisho vinavyoaminika"</string>
     <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Huruhusu programu kusakinisha na kusanidua vyeti vya CA kama vitambulisho vinavyoaminika."</string>
-    <string name="permlab_bindIdleService" msgid="816311765497613780">"endesha programu wakati haifanyi kitu"</string>
-    <string name="permdesc_bindIdleService" msgid="1767538493214100612">"Ruhusa hii huwezesha mfumo wa Android kuendesha programu chini chini wakati kifaa hakitumiki."</string>
+    <string name="permlab_bindIdleService" msgid="816311765497613780">"endesha programu wakati kifaa hakifanyi kitu"</string>
+    <string name="permdesc_bindIdleService" msgid="1767538493214100612">"Ruhusa hii huwezesha mfumo wa Android kuendesha programu chini kwa chini wakati kifaa hakitumiki."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"soma/andika kwa vyanzo vinavyomilikiwa na diag"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Inaruhusu programu kusoma na kuandika kwa chanzo chochote kinachomilikiwa na kikundi cha diag; kwa mfano, faili katika /dev. Hii inaweza kuathiri udhabiti na usalama wa mfumo. Hii inapaswa kutumiwa TU kwa utambuzi mahsusi wa maunzi na mtengenezaji au opareta."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"wezesha au lemeza vijenzi vya programu"</string>
@@ -564,7 +564,7 @@
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"kusoma hali na kitambulisho cha simu"</string>
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Inaruhusu programu kufikia vipengele vya simu vya kifaa. Idhini hii inaruhusu programu kutambua nambari ya simu na kifaa, kama simu ni amilifu, na nambari ya mbali iliyounganishwa kwa simu."</string>
     <string name="permlab_readPrecisePhoneState" msgid="5476483020282007597">"Soma hali sahihi ya simu"</string>
-    <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"Huruhusu programu kufikia hali sahihi ya simu. Ruhusa hii huwezesha programu kufahamu hali sahihi ya simu, iwapo simu inatumika au katika hali ya chini chini, simu inaposhindikana, hali sahihi ya muunganisho wa data na muunganisho wa data unaposhindikana."</string>
+    <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"Huruhusu programu kufikia hali sahihi ya simu. Ruhusa hii huwezesha programu kufahamu hali sahihi ya simu, iwapo simu inatumika au iko katika hali ya chini kwa chini, simu inaposhindikana, hali sahihi ya muunganisho wa data na muunganisho wa data unaposhindikana."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"zuia kompyuta ndogo dhidi ya kulala"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"kuzuia simu isilale"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"Inaruhusu programu kuzuia kompyuta kibao  kwenda kulala."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 08308c7..f59b2d1 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1363,7 +1363,7 @@
     <string name="car_mode_disable_notification_message" msgid="8035230537563503262">"แตะเพื่อออกจากโหมดรถยนต์"</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"การปล่อยสัญญาณหรือฮอตสปอตทำงานอยู่"</string>
     <string name="tethered_notification_message" msgid="6857031760103062982">"แตะเพื่อตั้งค่า"</string>
-    <string name="back_button_label" msgid="2300470004503343439">"ย้อนกลับ"</string>
+    <string name="back_button_label" msgid="2300470004503343439">"กลับ"</string>
     <string name="next_button_label" msgid="1080555104677992408">"ถัดไป"</string>
     <string name="skip_button_label" msgid="1275362299471631819">"ข้าม"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"การใช้งานข้อมูลมือถือในระดับสูง"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index d5ea7e2..4b5e48a 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -424,7 +424,7 @@
     <string name="permlab_manageCaCertificates" msgid="1678391896786882014">"quản lý thông tin xác thực đáng tin cậy"</string>
     <string name="permdesc_manageCaCertificates" msgid="4015644047196937014">"Cho phép ứng dụng cài đặt và gỡ cài đặt chứng chỉ CA dưới dạng thông tin xác thực đáng tin cậy."</string>
     <string name="permlab_bindIdleService" msgid="816311765497613780">"chạy ứng dụng trong thời gian rảnh"</string>
-    <string name="permdesc_bindIdleService" msgid="1767538493214100612">"Sự cho phép này cho phép hệ thống Android chạy ứng dụng trong nền khi thiết bị không được sử dụng."</string>
+    <string name="permdesc_bindIdleService" msgid="1767538493214100612">"Quyền này cho phép hệ thống Android chạy ứng dụng trong nền khi thiết bị không được sử dụng."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"đọc/ghi vào tài nguyên do chẩn đoán sở hữu"</string>
     <string name="permdesc_diagnostic" msgid="6608295692002452283">"Cho phép ứng dụng đọc và ghi vào bất kỳ tài nguyên nào do nhóm chẩn đoán sở hữu; ví dụ: các tệp trong /dev. Quyền này có thể ảnh hưởng đến sự ổn định và tính bảo mật của hệ thống. CHỈ nên sử dụng quyền này cho các chẩn đoán phần cứng cụ thể của nhà sản xuất hoặc nhà cung cấp."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"bật hoặc tắt cấu phần ứng dụng"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 9d3879b..ebf11c4 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -76,7 +76,7 @@
     <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"默认显示本机号码,在下一次通话中也显示"</string>
     <string name="serviceNotProvisioned" msgid="8614830180508686666">"未提供服务。"</string>
     <string name="CLIRPermanent" msgid="3377371145926835671">"您无法更改来电显示设置。"</string>
-    <string name="RestrictedChangedTitle" msgid="5592189398956187498">"访问受限情况已发生变化"</string>
+    <string name="RestrictedChangedTitle" msgid="5592189398956187498">"网络可用情况发生变化"</string>
     <string name="RestrictedOnData" msgid="8653794784690065540">"数据服务已禁用。"</string>
     <string name="RestrictedOnEmergency" msgid="6581163779072833665">"紧急服务已禁用。"</string>
     <string name="RestrictedOnNormal" msgid="4953867011389750673">"已禁用语音服务。"</string>
@@ -564,7 +564,7 @@
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"读取手机状态和身份"</string>
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"允许该应用访问设备的电话功能。此权限可让该应用确定本机号码和设备 ID、是否正处于通话状态以及拨打的号码。"</string>
     <string name="permlab_readPrecisePhoneState" msgid="5476483020282007597">"读取确切的手机状态"</string>
-    <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"允许应用获取确切的手机状态。此权限可让应用确定实际通话状态、通话是在界面上进行还是在后台进行、通话未接通次数、确切的数据网络连接状态,以及数据网络连接失败次数。"</string>
+    <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"允许应用获取确切的手机状态。此权限可让应用确定实际通话状态、通话是在界面上进行还是在后台进行、通话未接通情况、确切的数据网络连接状态,以及数据网络连接失败情况。"</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"阻止平板电脑进入休眠状态"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"防止手机休眠"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"允许应用阻止平板电脑进入休眠状态。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index d079ac5..544fd5b 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -563,8 +563,8 @@
     <string name="permdesc_modifyPhoneState" msgid="1029877529007686732">"允許應用程式控制裝置的電話功能。擁有這項權限的應用程式可在未通知您的情況下,任意切換網路、開啟或關閉手機無線電等。"</string>
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"讀取手機狀態和識別碼"</string>
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"允許應用程式使用裝置的電話功能。這項權限可讓應用程式判讀手機號碼和裝置 ID、是否正在通話中,以及所撥打的對方號碼。"</string>
-    <string name="permlab_readPrecisePhoneState" msgid="5476483020282007597">"讀取精確手機狀態"</string>
-    <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"允許應用程式存取精確的手機狀態。這項權限可讓應用程式判別實際通話狀態、通話程序正在進行中或是在背景運作、通話失敗次數、精確數據連線狀態和數據連線失敗次數。"</string>
+    <string name="permlab_readPrecisePhoneState" msgid="5476483020282007597">"讀取手機精確狀態"</string>
+    <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"允許應用程式存取手機的精確狀態。這項權限可讓應用程式判別實際通話狀態,包括通話正在進行中或是在背景運作、通話失敗次數、精確數據連線狀態和數據連線失敗次數。"</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"防止平板電腦進入休眠狀態"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"防止手機進入待命狀態"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"允許應用程式防止平板電腦進入休眠狀態。"</string>
@@ -1138,7 +1138,7 @@
     <string name="chooseUsbActivity" msgid="6894748416073583509">"選取要以 USB 裝置存取的應用程式"</string>
     <string name="noApplications" msgid="2991814273936504689">"沒有應用程式可執行這項操作。"</string>
     <string name="aerr_title" msgid="1905800560317137752"></string>
-    <string name="aerr_application" msgid="932628488013092776">"很抱歉,<xliff:g id="APPLICATION">%1$s</xliff:g> 已停止。"</string>
+    <string name="aerr_application" msgid="932628488013092776">"很抱歉,<xliff:g id="APPLICATION">%1$s</xliff:g>已停止運作。"</string>
     <string name="aerr_process" msgid="4507058997035697579">"很抱歉,處理程序 <xliff:g id="PROCESS">%1$s</xliff:g> 已停止。"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
     <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> 沒有回應。\n\n您要結束嗎?"</string>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index d1fa082..f01f10e 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -77,8 +77,6 @@
        <item>@drawable/btn_default_disabled_focused_holo_dark</item>
        <item>@drawable/btn_default_holo_dark</item>
        <item>@drawable/btn_default_holo_light</item>
-       <item>@drawable/btn_default_quantum_dark</item>
-       <item>@drawable/btn_default_quantum_light</item>
        <item>@drawable/btn_star_off_normal_holo_light</item>
        <item>@drawable/btn_star_on_normal_holo_light</item>
        <item>@drawable/btn_star_on_disabled_holo_light</item>
@@ -136,8 +134,6 @@
        <item>@drawable/expander_group_holo_light</item>
        <item>@drawable/list_selector_holo_dark</item>
        <item>@drawable/list_selector_holo_light</item>
-       <item>@drawable/list_selector_quantum_light</item>
-       <item>@drawable/list_selector_quantum_dark</item>
        <item>@drawable/list_section_divider_holo_light</item>
        <item>@drawable/list_section_divider_holo_dark</item>
        <item>@drawable/menu_hardkey_panel_holo_dark</item>
@@ -263,8 +259,6 @@
        <item>@drawable/ab_solid_shadow_holo</item>
        <item>@drawable/item_background_holo_dark</item>
        <item>@drawable/item_background_holo_light</item>
-       <item>@drawable/item_background_quantum_light</item>
-       <item>@drawable/item_background_quantum_dark</item>
        <item>@drawable/fastscroll_thumb_holo</item>
        <item>@drawable/fastscroll_thumb_pressed_holo</item>
        <item>@drawable/fastscroll_thumb_default_holo</item>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index c5524d7..f85b193 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -447,6 +447,10 @@
              to {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION}. -->
         <attr name="windowTranslucentNavigation" format="boolean" />
 
+        <!-- Flag to indicate that a window can be swiped away to be dismissed.
+             Corresponds to {@link android.view.Window.FEATURE_SWIPE_TO_DISMISS} -->
+        <attr name="windowSwipeToDismiss" format="boolean" />
+
         <!-- Flag indicating whether this window requests that content changes be performed
              as scene changes with transitions. Corresponds to
              {@link android.view.Window#FEATURE_CONTENT_TRANSITIONS}. -->
@@ -673,6 +677,8 @@
         <!-- Action bar styles   -->
         <!-- =================== -->
         <eat-comment />
+        <!-- Theme override for the Action Bar -->
+        <attr name="actionBarTheme" format="reference" />
         <!-- Default style for tabs within an action bar -->
         <attr name="actionBarTabStyle" format="reference" />
         <attr name="actionBarTabBarStyle" format="reference" />
@@ -1590,6 +1596,8 @@
         <enum name="KEYCODE_BRIGHTNESS_DOWN" value="220" />
         <enum name="KEYCODE_BRIGHTNESS_UP" value="221" />
         <enum name="KEYCODE_MEDIA_AUDIO_TRACK" value="222" />
+        <enum name="KEYCODE_MEDIA_SLEEP" value="223" />
+        <enum name="KEYCODE_MEDIA_WAKEUP" value="224" />
     </attr>
 
     <!-- ***************************************************************** -->
@@ -1627,6 +1635,7 @@
         <attr name="windowCloseOnTouchOutside" />
         <attr name="windowTranslucentStatus" />
         <attr name="windowTranslucentNavigation" />
+        <attr name="windowSwipeToDismiss" />
         <attr name="windowContentTransitions" />
         <attr name="windowContentTransitionManager" />
 
@@ -2357,8 +2366,8 @@
         <!-- Sets whether or not this ViewGroup should be treated as a single entity
              when doing an Activity transition. Typically, the elements inside a
              ViewGroup are each transitioned from the scene individually. The default
-             for a ViewGroup is false unless it has a background.
-             See {@link android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)}
+             for a ViewGroup is false unless it has a background. See
+             {@link android.app.ActivityOptions#makeSceneTransitionAnimation(android.view.View, String)}
              for more information. -->
         <attr name="transitionGroup" format="boolean" />
     </declare-styleable>
@@ -4094,19 +4103,6 @@
              RTL (right-to-left).  See
              {@link android.graphics.drawable.Drawable#setAutoMirrored}. -->
         <attr name="autoMirrored" format="boolean" />
-        <!-- If set, specifies the color to apply to the drawable as a color filter. By
-             default, no color filter is applied. -->
-        <attr name="colorFilterColor" format="color" />
-        <!-- When a color filter color is set, specifies its Porter-Duff blending mode.
-             The default value is multiply. -->
-        <attr name="colorFilterMode">
-            <!-- [Sa * Da, Sc * Dc] -->
-            <enum name="multiply" value="14" />
-            <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -->
-            <enum name="screen" value="15" />
-            <!-- [Da, Sc * Da + (1 - Sa) * Dc] -->
-            <enum name="src_atop" value="9" />
-        </attr>
     </declare-styleable>
 
     <!-- Drawable used to render several states. Each state is represented by
@@ -4391,8 +4387,21 @@
         <!-- Indicates if the drawable needs to be mirrored when its layout direction is
              RTL (right-to-left). -->
         <attr name="autoMirrored" />
-        <attr name="colorFilterColor" />
-        <attr name="colorFilterMode" />
+        <!-- If set, specifies the color to apply to the drawable as a tint. By default,
+             no tint is applied. May be a color state list. -->
+        <attr name="tint" />
+        <!-- When a tint color is set, specifies its Porter-Duff blending mode. The
+             default value is src_in, which treats the drawable as an alpha mask. -->
+        <attr name="tintMode">
+            <!-- [Sa * Da, Sc * Da] -->
+            <enum name="src_in" value="0" />
+            <!-- [Da, Sc * Da + (1 - Sa) * Dc] -->
+            <enum name="src_atop" value="1" />
+            <!-- [Sa * Da, Sc * Dc] -->
+            <enum name="multiply" value="2" />
+            <!-- [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] -->
+            <enum name="screen" value="3" />
+        </attr>
     </declare-styleable>
 
     <!-- Drawable used to draw 9-patches. -->
@@ -4406,8 +4415,12 @@
         <!-- Indicates if the drawable needs to be mirrored when its layout direction is
              RTL (right-to-left). -->
         <attr name="autoMirrored" />
-        <attr name="colorFilterColor" />
-        <attr name="colorFilterMode" />
+        <!-- If set, specifies the color to apply to the drawable as a tint. By default,
+             no tint is applied. May be a color state list. -->
+        <attr name="tint" />
+        <!-- When a tint color is set, specifies its Porter-Duff blending mode. The
+             default value is src_in, which treats the drawable as an alpha mask. -->
+        <attr name="tintMode" />
     </declare-styleable>
 
     <!-- Drawable used to draw a single color. -->
@@ -4756,14 +4769,6 @@
         <attr name="fromScene" format="reference" />
         <!-- The destination scene in this scene change. -->
         <attr name="toScene" format="reference" />
-        <!-- The name of the originating scene in this scene change.
-             Apps should treat this name as an API in the same sense
-             that an Intent action or extra key is. -->
-        <attr name="fromSceneName" format="string" />
-        <!-- The name of the destination scene in this scene change.
-             Apps should treat this name as an API in the same sense
-             that an Intent action or extra key is. -->
-        <attr name="toSceneName" format="string" />
     </declare-styleable>
 
     <!-- ========================== -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 4647413..2efbca2 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -259,6 +259,17 @@
          applications can request this feature. Default value is false. -->
     <attr name="requiredForAllUsers" format="boolean" />
 
+    <!-- Flag to specifiy for which types of profile this application needs to be present.
+         Only pre-installed applications can request this feature. Default is none. -->
+    <attr name="requiredForProfile">
+        <!-- This application needs to be present for restricted profiles -->
+        <flag name="restricted" value="0x0001" />
+        <!-- This application needs to be present for managed profiles -->
+        <flag name="managed" value="0x0002" />
+        <!-- This application needs to be present for all types of profiles -->
+        <flag name="all" value="0xFFFF" />
+    </attr>
+
     <!-- Flag indicating whether the application can be debugged, even when
          running on a device that is running in user mode. -->
     <attr name="debuggable" format="boolean" />
@@ -901,6 +912,7 @@
         <attr name="hasCode" format="boolean" />
         <attr name="persistent" />
         <attr name="requiredForAllUsers" />
+        <attr name="requiredForProfile" />
         <!-- Specify whether the components in this application are enabled or not (that is, can be
              instantiated by the system).
              If "false", it overrides any component specific values (a value of "true" will not
diff --git a/core/res/res/values/colors_quantum.xml b/core/res/res/values/colors_quantum.xml
index b623263..c8083f4 100644
--- a/core/res/res/values/colors_quantum.xml
+++ b/core/res/res/values/colors_quantum.xml
@@ -15,34 +15,150 @@
 -->
 
 <resources>
-    <color name="background_quantum_dark">#ff000000</color>
-    <color name="background_quantum_light">#fff3f3f3</color>
+    <color name="background_quantum_dark">@color/black</color>
+    <color name="background_quantum_light">@color/quantum_grey_50</color>
+    <color name="secondary_background_quantum_dark">@color/quantum_grey_700</color>
+    <color name="secondary_background_quantum_light">@color/quantum_grey_100</color>
 
     <color name="bright_foreground_quantum_dark">@color/background_quantum_light</color>
     <color name="bright_foreground_quantum_light">@color/background_quantum_dark</color>
-    <color name="bright_foreground_disabled_quantum_dark">#ff4c4c4c</color>
-    <color name="bright_foreground_disabled_quantum_light">#ffb2b2b2</color>
+    <!-- TODO: This is 50% alpha black -->
+    <color name="bright_foreground_disabled_quantum_dark">#80000000</color>
+    <!-- TODO: This is 50% alpha grey_50 -->
+    <color name="bright_foreground_disabled_quantum_light">#80fafafa</color>
     <color name="bright_foreground_inverse_quantum_dark">@color/bright_foreground_quantum_light</color>
     <color name="bright_foreground_inverse_quantum_light">@color/bright_foreground_quantum_dark</color>
 
-    <color name="dim_foreground_quantum_dark">#bebebe</color>
-    <color name="dim_foreground_quantum_light">#323232</color>
+    <color name="dim_foreground_quantum_dark">#ffbebebe</color>
+    <color name="dim_foreground_quantum_light">#ff323232</color>
     <color name="dim_foreground_disabled_quantum_dark">#80bebebe</color>
     <color name="dim_foreground_disabled_quantum_light">#80323232</color>
 
-    <color name="hint_foreground_quantum_dark">#808080</color>
-    <color name="hint_foreground_quantum_light">#808080</color>
-    <color name="highlighted_text_quantum_dark">#6633b5e5</color>
-    <color name="highlighted_text_quantum_light">#6633b5e5</color>
+    <!-- TODO: These should be theme attributes. -->
+    <color name="control_normal_foreground_quantum_light">@color/secondary_text_quantum_light</color>
+    <color name="control_activated_foreground_quantum_light">@color/quantum_teal_700</color>
 
-    <color name="timepicker_default_background_quantum_dark">#ff303030</color>
-    <color name="timepicker_default_background_quantum_light">@color/white</color>
-    <color name="timepicker_default_text_color_quantum_dark">@color/white</color>
-    <color name="timepicker_default_text_color_quantum_light">#8c8c8c</color>
-    <color name="timepicker_default_disabled_color_quantum_dark">#7f08c8c8</color>
-    <color name="timepicker_default_disabled_color_quantum_light">#7f000000</color>
-    <color name="timepicker_default_ampm_selected_background_color_quantum_dark">@color/holo_blue_light</color>
-    <color name="timepicker_default_ampm_selected_background_color_quantum_light">@color/holo_blue_light</color>
+    <!-- TODO: These should be theme attributes. -->
+    <color name="control_normal_foreground_quantum_dark">@color/secondary_text_quantum_dark</color>
+    <color name="control_activated_foreground_quantum_dark">@color/quantum_lime_A200</color>
+
+    <!-- TODO: These should be theme attributes. -->
+    <color name="btn_default_normal_quantum_light">@color/quantum_grey_300</color>
+    <color name="btn_default_pressed_quantum_light">@color/quantum_grey_500</color>
+
+    <!-- TODO: These should be theme attributes. -->
+    <color name="btn_default_normal_quantum_dark">@color/quantum_grey_700</color>
+    <color name="btn_default_pressed_quantum_dark">@color/quantum_grey_500</color>
+
+    <color name="hint_foreground_quantum_dark">@color/bright_foreground_disabled_quantum_dark</color>
+    <color name="hint_foreground_quantum_light">@color/bright_foreground_disabled_quantum_light</color>
+    <!-- TODO: This is 40% alpha lime_A200 -->
+    <color name="highlighted_text_quantum_dark">#66eeff41</color>
+    <!-- TODO: This is 40% alpha teal_700 -->
+    <color name="highlighted_text_quantum_light">#660097a7</color>
+
+    <!-- TODO: These should all be pushed into a TimePicker widget style. -->
+    <color name="timepicker_default_background_quantum_dark">@color/background_quantum_dark</color>
+    <color name="timepicker_default_background_quantum_light">@color/background_quantum_light</color>
+    <color name="timepicker_default_text_color_quantum_dark">@color/bright_foreground_quantum_dark</color>
+    <color name="timepicker_default_text_color_quantum_light">@color/bright_foreground_quantum_light</color>
+    <color name="timepicker_default_disabled_color_quantum_dark">@color/bright_foreground_disabled_quantum_dark</color>
+    <color name="timepicker_default_disabled_color_quantum_light">@color/bright_foreground_disabled_quantum_light</color>
+    <color name="timepicker_default_ampm_selected_background_color_quantum_dark">@color/control_activated_foreground_quantum_dark</color>
+    <color name="timepicker_default_ampm_selected_background_color_quantum_light">@color/control_activated_foreground_quantum_light</color>
     <color name="timepicker_default_ampm_unselected_background_color_quantum_dark">@color/transparent</color>
     <color name="timepicker_default_ampm_unselected_background_color_quantum_light">@color/white</color>
+
+    <!-- Primary & accent colors -->
+
+    <color name="quantum_red_100">#fff4c7c3</color>
+    <color name="quantum_red_300">#ffe67c73</color>
+    <color name="quantum_red_500">#ffdb4437</color>
+    <color name="quantum_red_700">#ffc53929</color>
+    <color name="quantum_red_A200">#ffff5252</color>
+    <color name="quantum_red_A400">#ffff1744</color>
+
+    <color name="quantum_blue_100">#ffc6dafc</color>
+    <color name="quantum_blue_300">#ff7baaf7</color>
+    <color name="quantum_blue_500">#ff4285f4</color>
+    <color name="quantum_blue_700">#ff3367d6</color>
+    <color name="quantum_blue_A200">#ff448aff</color>
+    <color name="quantum_blue_A400">#ff2979ff</color>
+
+    <color name="quantum_teal_100">#ffb2ebf2</color>
+    <color name="quantum_teal_300">#ff4dd0e1</color>
+    <color name="quantum_teal_500">#ff00bcd4</color>
+    <color name="quantum_teal_700">#ff0097a7</color>
+    <color name="quantum_teal_A200">#ff18ffff</color>
+    <color name="quantum_teal_A400">#ff00e5ff</color>
+
+    <color name="quantum_green_100">#ffb7e1cd</color>
+    <color name="quantum_green_300">#ff57bb8a</color>
+    <color name="quantum_green_500">#ff0f9d58</color>
+    <color name="quantum_green_700">#ff0b8043</color>
+    <color name="quantum_green_A200">#ff69f0ae</color>
+    <color name="quantum_green_A400">#ff00e676</color>
+
+    <color name="quantum_lime_100">#fff0f4c3</color>
+    <color name="quantum_lime_300">#ffdce775</color>
+    <color name="quantum_lime_500">#ffcddc39</color>
+    <color name="quantum_lime_700">#ffafb42b</color>
+    <color name="quantum_lime_A200">#ffeeff41</color>
+    <color name="quantum_lime_A400">#ffc6ff00</color>
+
+    <color name="quantum_yellow_100">#fffce8b2</color>
+    <color name="quantum_yellow_300">#fff7cb4d</color>
+    <color name="quantum_yellow_500">#fff4b400</color>
+    <color name="quantum_yellow_700">#fff09300</color>
+    <color name="quantum_yellow_A200">#ffffcd40</color>
+    <color name="quantum_yellow_A400">#ffffbc00</color>
+
+    <color name="quantum_orange_100">#ffffe0b2</color>
+    <color name="quantum_orange_300">#ffffb74d</color>
+    <color name="quantum_orange_500">#ffff9800</color>
+    <color name="quantum_orange_700">#fff57c00</color>
+    <color name="quantum_orange_A200">#ffffab40</color>
+    <color name="quantum_orange_A400">#ffff9100</color>
+
+    <color name="quantum_deep_orange_100">#fff4c7c3</color>
+    <color name="quantum_deep_orange_300">#ffe67c73</color>
+    <color name="quantum_deep_orange_500">#ffff5722</color>
+    <color name="quantum_deep_orange_700">#ffc53929</color>
+    <color name="quantum_deep_orange_A200">#ffff5252</color>
+    <color name="quantum_deep_orange_A400">#ffff1744</color>
+
+    <!-- Neutral colors -->
+
+    <color name="quantum_grey_50">#fffafafa</color>
+    <color name="quantum_grey_100">#fff5f5f5</color>
+    <color name="quantum_grey_300">#ffeeeeee</color>
+    <color name="quantum_grey_500">#ffa3a3a3</color>
+    <color name="quantum_grey_700">#ff717171</color>
+
+    <color name="quantum_blue_grey_50">#ffeceff1</color>
+    <color name="quantum_blue_grey_100">#ffcfd8dc</color>
+    <color name="quantum_blue_grey_300">#ff90a4ae</color>
+    <color name="quantum_blue_grey_500">#ff607d8b</color>
+    <color name="quantum_blue_grey_700">#ff455a64</color>
+
+    <color name="quantum_brown_100">#ffd7ccc8</color>
+    <color name="quantum_brown_300">#ffa1887f</color>
+    <color name="quantum_brown_500">#ff795548</color>
+    <color name="quantum_brown_700">#ff5d4037</color>
+
+    <!-- Text & foreground colors -->
+
+    <color name="primary_text_quantum_light">#ff000000</color>
+    <color name="secondary_text_quantum_light">#de000000</color>
+    <color name="tertiary_text_quantum_light">#8a000000</color>
+
+    <color name="primary_text_quantum_dark">#ffffffff</color>
+    <color name="secondary_text_quantum_dark">#deffffff</color>
+    <color name="tertiary_text_quantum_dark">#8affffff</color>
+
+    <!-- "Theme" colors to be replaced by attrs when available -->
+    <color name="theme_color_100">@color/quantum_teal_100</color>
+    <color name="theme_color_300">@color/quantum_teal_300</color>
+    <color name="theme_color_500">@color/quantum_teal_500</color>
+    <color name="theme_color_700">@color/quantum_teal_700</color>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 519e2ae..cfd4a63 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -370,6 +370,17 @@
     <!-- If this is true, key chords can be used to take a screenshot on the device. -->
     <bool name="config_enableScreenshotChord">true</bool>
 
+    <!-- Auto-rotation behavior -->
+
+    <!-- If true, enables auto-rotation features using the accelerometer.
+         Otherwise, auto-rotation is disabled.  Applications may still request
+         to use specific orientations but the sensor is ignored and sensor-based
+         orientations are not available.  Furthermore, all auto-rotation related
+         settings are omitted from the system UI.  In certain situations we may
+         still use the accelerometer to determine the orientation, such as when
+         docked if the dock is configured to enable the accelerometer. -->
+    <bool name="config_supportAutoRotation">true</bool>
+
     <!-- If true, the screen can be rotated via the accelerometer in all 4
          rotations as the default behavior. -->
     <bool name="config_allowAllRotations">false</bool>
@@ -382,57 +393,12 @@
          true here reverses that logic. -->
     <bool name="config_reverseDefaultRotation">false</bool>
 
+    <!-- Lid switch behavior -->
+
     <!-- The number of degrees to rotate the display when the keyboard is open.
          A value of -1 means no change in orientation by default. -->
     <integer name="config_lidOpenRotation">-1</integer>
 
-    <!-- The number of degrees to rotate the display when the device is in a desk dock.
-         A value of -1 means no change in orientation by default. -->
-    <integer name="config_deskDockRotation">-1</integer>
-
-    <!-- The number of degrees to rotate the display when the device is in a car dock.
-         A value of -1 means no change in orientation by default. -->
-    <integer name="config_carDockRotation">-1</integer>
-
-    <!-- The number of degrees to rotate the display when the device has HDMI connected
-         but is not in a dock.  A value of -1 means no change in orientation by default.
-         Use -1 except on older devices whose Hardware Composer HAL does not
-         provide full support for multiple displays.  -->
-    <integer name="config_undockedHdmiRotation">-1</integer>
-
-    <!-- Control the default UI mode type to use when there is no other type override
-         happening.  One of the following values (See Configuration.java):
-             1  UI_MODE_TYPE_NORMAL
-             4  UI_MODE_TYPE_TELEVISION
-             5  UI_MODE_TYPE_APPLIANCE
-         Any other values will have surprising consequences. -->
-    <integer name="config_defaultUiModeType">1</integer>
-
-    <!-- Control whether being in the desk dock (and powered) always
-         keeps the screen on.  By default it stays on when plugged in to
-         AC.  0 will not keep it on; or together 1 to stay on when plugged
-         in to AC and 2 to stay on when plugged in to USB.  (So 3 for both.) -->
-    <integer name="config_deskDockKeepsScreenOn">1</integer>
-
-    <!-- Control whether being in the car dock (and powered) always
-         keeps the screen on.  By default it stays on when plugged in to
-         AC.  0 will not keep it on; or together 1 to stay on when plugged
-         in to AC and 2 to stay on when plugged in to USB.  (So 3 for both.) -->
-    <integer name="config_carDockKeepsScreenOn">1</integer>
-
-    <!-- Control whether being in the desk dock should enable accelerometer
-         based screen orientation.  This defaults to true because it is
-         common for desk docks to be sold in a variety of form factors
-         with different orientations.  Since we cannot always tell these docks
-         apart and the docks cannot report their true orientation on their own,
-         we rely on gravity to determine the effective orientation. -->
-    <bool name="config_deskDockEnablesAccelerometer">true</bool>
-
-    <!-- Control whether being in the car dock should enable accelerometer based
-         screen orientation.  This defaults to true because putting a device in
-         a car dock make the accelerometer more a physical input (like a lid). -->
-    <bool name="config_carDockEnablesAccelerometer">true</bool>
-
     <!-- Indicate whether the lid state impacts the accessibility of
          the physical keyboard.  0 means it doesn't, 1 means it is accessible
          when the lid is open, 2 means it is accessible when the lid is
@@ -450,6 +416,60 @@
          The default is false. -->
     <bool name="config_lidControlsSleep">false</bool>
 
+    <!-- Desk dock behavior -->
+
+    <!-- The number of degrees to rotate the display when the device is in a desk dock.
+         A value of -1 means no change in orientation by default. -->
+    <integer name="config_deskDockRotation">-1</integer>
+
+    <!-- Control whether being in the desk dock (and powered) always
+         keeps the screen on.  By default it stays on when plugged in to
+         AC.  0 will not keep it on; or together 1 to stay on when plugged
+         in to AC and 2 to stay on when plugged in to USB.  (So 3 for both.) -->
+    <integer name="config_deskDockKeepsScreenOn">1</integer>
+
+    <!-- Control whether being in the desk dock should enable accelerometer
+         based screen orientation.  This defaults to true because it is
+         common for desk docks to be sold in a variety of form factors
+         with different orientations.  Since we cannot always tell these docks
+         apart and the docks cannot report their true orientation on their own,
+         we rely on gravity to determine the effective orientation. -->
+    <bool name="config_deskDockEnablesAccelerometer">true</bool>
+
+    <!-- Car dock behavior -->
+
+    <!-- The number of degrees to rotate the display when the device is in a car dock.
+         A value of -1 means no change in orientation by default. -->
+    <integer name="config_carDockRotation">-1</integer>
+
+    <!-- Control whether being in the car dock (and powered) always
+         keeps the screen on.  By default it stays on when plugged in to
+         AC.  0 will not keep it on; or together 1 to stay on when plugged
+         in to AC and 2 to stay on when plugged in to USB.  (So 3 for both.) -->
+    <integer name="config_carDockKeepsScreenOn">1</integer>
+
+    <!-- Control whether being in the car dock should enable accelerometer based
+         screen orientation.  This defaults to true because putting a device in
+         a car dock make the accelerometer more a physical input (like a lid). -->
+
+    <bool name="config_carDockEnablesAccelerometer">true</bool>
+
+    <!-- HDMI behavior -->
+
+    <!-- The number of degrees to rotate the display when the device has HDMI connected
+         but is not in a dock.  A value of -1 means no change in orientation by default.
+         Use -1 except on older devices whose Hardware Composer HAL does not
+         provide full support for multiple displays.  -->
+    <integer name="config_undockedHdmiRotation">-1</integer>
+
+    <!-- Control the default UI mode type to use when there is no other type override
+         happening.  One of the following values (See Configuration.java):
+             1  UI_MODE_TYPE_NORMAL
+             4  UI_MODE_TYPE_TELEVISION
+             5  UI_MODE_TYPE_APPLIANCE
+         Any other values will have surprising consequences. -->
+    <integer name="config_defaultUiModeType">1</integer>
+
     <!-- Indicate whether to allow the device to suspend when the screen is off
          due to the proximity sensor.  This resource should only be set to true
          if the sensor HAL correctly handles the proximity sensor as a wake-up source.
@@ -1083,8 +1103,16 @@
     <!-- Name of the wimax state tracker clas -->
     <string name="config_wimaxStateTrackerClassname" translatable="false"></string>
 
-    <!-- Is the dreams feature supported? -->
+    <!-- Specifies whether the dreams feature should be supported.
+         When true, the system will allow the user to configure dreams (screensavers)
+         to launch when a user activity timeout occurs or the system is told to nap.
+         When false, the dreams feature will be disabled (this does not affect dozing).
+
+         Consider setting this resource to false or disabling dreams by default when a
+         doze component is specified below since dreaming will supercede dozing and
+         will prevent the system from entering a low power state until the dream ends. -->
     <bool name="config_dreamsSupported">true</bool>
+
     <!-- If supported, are dreams enabled? (by default) -->
     <bool name="config_dreamsEnabledByDefault">true</bool>
     <!-- If supported and enabled, are dreams activated when docked? (by default) -->
@@ -1181,6 +1209,8 @@
 
     <!--  Maximum number of supported users -->
     <integer name="config_multiuserMaximumUsers">1</integer>
+    <!-- Whether UI for multi user should be shown -->
+    <bool name="config_enableMultiUserUI">false</bool>
 
     <!-- Minimum span needed to begin a touch scaling gesture.
          If the span is equal to or greater than this size, a scaling gesture
diff --git a/core/res/res/values/dimens_quantum.xml b/core/res/res/values/dimens_quantum.xml
new file mode 100644
index 0000000..3913752
--- /dev/null
+++ b/core/res/res/values/dimens_quantum.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+
+    <!-- Default height of an action bar. -->
+    <dimen name="action_bar_default_height_quantum">56dp</dimen>
+    <!-- Vertical padding around action bar icons. -->
+    <dimen name="action_bar_icon_vertical_padding_quantum">16dp</dimen>
+    <!-- Text size for action bar titles -->
+    <dimen name="action_bar_title_text_size_quantum">20sp</dimen>
+    <!-- Text size for action bar subtitles -->
+    <dimen name="action_bar_subtitle_text_size_quantum">16sp</dimen>
+    <!-- Top margin for action bar subtitles -->
+    <dimen name="action_bar_subtitle_top_margin_quantum">-3dp</dimen>
+    <!-- Bottom margin for action bar subtitles -->
+    <dimen name="action_bar_subtitle_bottom_margin_quantum">5dp</dimen>
+
+    <dimen name="text_size_display_4_quantum">112sp</dimen>
+    <dimen name="text_size_display_3_quantum">56sp</dimen>
+    <dimen name="text_size_display_2_quantum">45sp</dimen>
+    <dimen name="text_size_display_1_quantum">34sp</dimen>
+    <dimen name="text_size_headline_quantum">24sp</dimen>
+    <dimen name="text_size_title_quantum">20sp</dimen>
+    <dimen name="text_size_subhead_quantum">16sp</dimen>
+    <dimen name="text_size_body_2_quantum">14sp</dimen>
+    <dimen name="text_size_body_1_quantum">14sp</dimen>
+    <dimen name="text_size_caption_quantum">12sp</dimen>
+    <dimen name="text_size_menu_quantum">14sp</dimen>
+    <dimen name="text_size_button_quantum">14sp</dimen>
+
+</resources>
diff --git a/core/res/res/values/donottranslate_quantum.xml b/core/res/res/values/donottranslate_quantum.xml
new file mode 100644
index 0000000..83cc4e5
--- /dev/null
+++ b/core/res/res/values/donottranslate_quantum.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+
+    <string name="font_family_display_4_quantum">sans-serif-light</string>
+    <string name="font_family_display_3_quantum">sans-serif</string>
+    <string name="font_family_display_2_quantum">sans-serif</string>
+    <string name="font_family_display_1_quantum">sans-serif</string>
+    <string name="font_family_headline_quantum">sans-serif</string>
+    <string name="font_family_title_quantum">sans-serif-medium</string>
+    <string name="font_family_subhead_quantum">sans-serif</string>
+    <string name="font_family_body_2_quantum">sans-serif-medium</string>
+    <string name="font_family_body_1_quantum">sans-serif</string>
+    <string name="font_family_caption_quantum">sans-serif</string>
+    <string name="font_family_menu_quantum">sans-serif-medium</string>
+    <string name="font_family_button_quantum">sans-serif</string>
+
+</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 794d6a5..3ab3e5d 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2097,18 +2097,15 @@
   <public type="attr" name="windowContentTransitions" />
   <public type="attr" name="windowContentTransitionManager" />
   <public type="attr" name="translationZ" />
-  <public type="attr" name="colorFilterColor" />
-  <public type="attr" name="colorFilterMode" />
-  <public type="attr" name="isolatedZVolume" />
+  <public type="attr" name="tintMode" />
   <public type="attr" name="controlX1" />
   <public type="attr" name="controlY1" />
   <public type="attr" name="controlX2" />
   <public type="attr" name="controlY2" />
-  <public type="attr" name="fromSceneName" />
-  <public type="attr" name="toSceneName" />
   <public type="attr" name="sharedElementName" />
   <public type="attr" name="transitionGroup" />
   <public type="attr" name="castsShadow" />
+  <public type="attr" name="requiredForProfile"/>
 
   <public type="id" name="shared_element_name" />
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 91bef50..afb7085 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -625,9 +625,9 @@
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_processOutgoingCalls">reroute outgoing calls</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permdesc_processOutgoingCalls">Allows the app to process
-      outgoing calls and change the number to be dialed. This permission allows
-      the app to monitor, redirect, or prevent outgoing calls.</string>
+    <string name="permdesc_processOutgoingCalls">Allows the app to see the
+        number being dialed during an outgoing call with the option to redirect
+        the call to a different number or abort the call altogether.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_receiveSms">receive text messages (SMS)</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 1a6eacd..be875ff 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -225,6 +225,14 @@
         <item name="windowExitAnimation">@anim/fast_fade_out</item>
     </style>
 
+    <!-- Window animations for swipe-dismissable windows. {@hide} -->
+    <style name="Animation.SwipeDismiss">
+        <item name="taskOpenEnterAnimation">@anim/swipe_window_enter</item>
+        <item name="taskOpenExitAnimation">@anim/swipe_window_exit</item>
+        <item name="taskCloseEnterAnimation">@anim/swipe_window_enter</item>
+        <item name="taskCloseExitAnimation">@anim/swipe_window_exit</item>
+    </style>
+
     <!-- Status Bar Styles -->
     <style name="TextAppearance.StatusBar">
         <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
@@ -263,6 +271,33 @@
         <item name="android:textColor">#CCCCCC</item>
     </style>
 
+    <style name="TextAppearance.StatusBar.Quantum">
+    </style>
+    <style name="TextAppearance.StatusBar.Quantum.EventContent">
+        <item name="android:textColor">#888888</item>
+        <item name="android:textSize">@dimen/notification_text_size</item>
+    </style>
+    <style name="TextAppearance.StatusBar.Quantum.EventContent.Title">
+        <item name="android:textColor">#000000</item>
+        <item name="android:fontFamily">sans-serif-light</item>
+        <item name="android:textSize">@dimen/notification_title_text_size</item>
+        <item name="android:textStyle">bold</item>
+    </style>
+    <style name="TextAppearance.StatusBar.Quantum.EventContent.Line2">
+        <item name="android:textSize">@dimen/notification_subtext_size</item>
+    </style>
+    <style name="TextAppearance.StatusBar.Quantum.EventContent.Info">
+        <item name="android:textSize">@dimen/notification_subtext_size</item>
+        <item name="android:textColor">#888888</item>
+    </style>
+    <style name="TextAppearance.StatusBar.Quantum.EventContent.Time">
+        <item name="android:textSize">@dimen/notification_subtext_size</item>
+        <item name="android:textColor">#888888</item>
+    </style>
+    <style name="TextAppearance.StatusBar.Quantum.EventContent.Emphasis">
+        <item name="android:textColor">#555555</item>
+    </style>
+
     <style name="TextAppearance.Small.CalendarViewWeekDayView">
         <item name="android:textStyle">bold</item>
     </style>
diff --git a/core/res/res/values/styles_micro.xml b/core/res/res/values/styles_micro.xml
index 2fd283e..52d90bc 100644
--- a/core/res/res/values/styles_micro.xml
+++ b/core/res/res/values/styles_micro.xml
@@ -19,4 +19,16 @@
     <style name="Widget.Micro.TextView">
         <item name="android:fontFamily">sans-serif-condensed</item>
     </style>
+
+    <style name="Widget.Micro.NumberPicker">
+        <item name="android:internalLayout">@android:layout/number_picker_with_selector_wheel_micro</item>
+        <item name="android:solidColor">@android:color/transparent</item>
+        <item name="android:selectionDivider">@android:drawable/numberpicker_selection_divider</item>
+        <item name="android:selectionDividerHeight">0dip</item>
+        <item name="android:selectionDividersDistance">104dip</item>
+        <item name="android:internalMinWidth">64dip</item>
+        <item name="android:internalMaxHeight">180dip</item>
+        <item name="virtualButtonPressedDrawable">?android:attr/selectableItemBackground</item>
+        <item name="android:descendantFocusability">blocksDescendants</item>
+    </style>
 </resources>
diff --git a/core/res/res/values/styles_quantum.xml b/core/res/res/values/styles_quantum.xml
index df850a7..44cdb5f 100644
--- a/core/res/res/values/styles_quantum.xml
+++ b/core/res/res/values/styles_quantum.xml
@@ -88,47 +88,48 @@
 
     <!-- Begin Quantum theme styles -->
 
-    <!-- Text Styles -->
+    <!-- Text styles -->
+
     <style name="TextAppearance.Quantum" parent="TextAppearance"/>
 
     <style name="TextAppearance.Quantum.Inverse" parent="TextAppearance.Inverse">
-        <item name="textColor">?textColorPrimaryInverse</item>
-        <item name="textColorHint">?textColorHintInverse</item>
-        <item name="textColorHighlight">?textColorHighlightInverse</item>
-        <item name="textColorLink">?textColorLinkInverse</item>
+        <item name="textColor">?attr/textColorPrimaryInverse</item>
+        <item name="textColorHint">?attr/textColorHintInverse</item>
+        <item name="textColorHighlight">?attr/textColorHighlightInverse</item>
+        <item name="textColorLink">?attr/textColorLinkInverse</item>
     </style>
 
     <style name="TextAppearance.Quantum.Large" parent="TextAppearance.Large"/>
 
+    <style name="TextAppearance.Quantum.Large.Inverse">
+        <item name="textColor">?attr/textColorPrimaryInverse</item>
+        <item name="textColorHint">?attr/textColorHintInverse</item>
+        <item name="textColorHighlight">?attr/textColorHighlightInverse</item>
+        <item name="textColorLink">?attr/textColorLinkInverse</item>
+    </style>
+
     <style name="TextAppearance.Quantum.Medium" parent="TextAppearance.Medium"/>
 
+    <style name="TextAppearance.Quantum.Medium.Inverse">
+        <item name="textColor">?attr/textColorSecondaryInverse</item>
+        <item name="textColorHint">?attr/textColorHintInverse</item>
+        <item name="textColorHighlight">?attr/textColorHighlightInverse</item>
+        <item name="textColorLink">?attr/textColorLinkInverse</item>
+    </style>
+
     <style name="TextAppearance.Quantum.Small" parent="TextAppearance.Small"/>
 
-    <style name="TextAppearance.Quantum.Large.Inverse">
-        <item name="textColor">?textColorPrimaryInverse</item>
-        <item name="textColorHint">?textColorHintInverse</item>
-        <item name="textColorHighlight">?textColorHighlightInverse</item>
-        <item name="textColorLink">?textColorLinkInverse</item>
-    </style>
-
-    <style name="TextAppearance.Quantum.Medium.Inverse">
-        <item name="textColor">?textColorPrimaryInverse</item>
-        <item name="textColorHint">?textColorHintInverse</item>
-        <item name="textColorHighlight">?textColorHighlightInverse</item>
-        <item name="textColorLink">?textColorLinkInverse</item>
-    </style>
-
     <style name="TextAppearance.Quantum.Small.Inverse">
-        <item name="textColor">?textColorSecondaryInverse</item>
-        <item name="textColorHint">?textColorHintInverse</item>
-        <item name="textColorHighlight">?textColorHighlightInverse</item>
-        <item name="textColorLink">?textColorLinkInverse</item>
+        <item name="textColor">?attr/textColorSecondaryInverse</item>
+        <item name="textColorHint">?attr/textColorHintInverse</item>
+        <item name="textColorHighlight">?attr/textColorHighlightInverse</item>
+        <item name="textColorLink">?attr/textColorLinkInverse</item>
     </style>
 
     <style name="TextAppearance.Quantum.SearchResult">
         <item name="textStyle">normal</item>
-        <item name="textColor">?textColorPrimary</item>
-        <item name="textColorHint">?textColorHint</item>
+        <item name="textColor">?attr/textColorPrimary</item>
+        <item name="textColorHint">?attr/textColorHint</item>
     </style>
 
     <style name="TextAppearance.Quantum.SearchResult.Title">
@@ -137,54 +138,26 @@
 
     <style name="TextAppearance.Quantum.SearchResult.Subtitle">
         <item name="textSize">14sp</item>
-        <item name="textColor">?textColorSecondary</item>
+        <item name="textColor">?attr/textColorSecondary</item>
     </style>
 
     <style name="TextAppearance.Quantum.Widget" parent="TextAppearance.Widget"/>
 
-    <style name="TextAppearance.Quantum.Widget.Button" parent="TextAppearance.Quantum.Small.Inverse">
-        <item name="textColor">@color/primary_text_light_nodisable</item>
-    </style>
-
-    <style name="TextAppearance.Quantum.Widget.IconMenu.Item" parent="TextAppearance.Quantum.Small">
-        <item name="textColor">?textColorPrimary</item>
-    </style>
-
-    <!-- This style is for smaller screens; values-xlarge defines a version
-         for larger screens. -->
-    <style name="TextAppearance.Quantum.Widget.TabWidget">
-        <item name="textSize">14sp</item>
+    <style name="TextAppearance.Quantum.Widget.Button">
+        <item name="fontFamily">@string/font_family_button_quantum</item>
+        <item name="textSize">@dimen/text_size_button_quantum</item>
+        <item name="textAllCaps">true</item>
+        <item name="textColor">?attr/textColorPrimary</item>
         <item name="textStyle">normal</item>
-        <item name="textColor">@color/tab_indicator_text</item>
-    </style>
-
-    <style name="TextAppearance.Quantum.Widget.TextView">
-        <item name="textColor">?textColorPrimaryDisableOnly</item>
-        <item name="textColorHint">?textColorHint</item>
-    </style>
-
-    <style name="TextAppearance.Quantum.Widget.TextView.PopupMenu">
-        <item name="textSize">18sp</item>
-        <item name="textColor">?textColorPrimaryDisableOnly</item>
-        <item name="textColorHint">?textColorHint</item>
-    </style>
-
-    <style name="TextAppearance.Quantum.Widget.DropDownHint">
-        <item name="textColor">?textColorPrimary</item>
-        <item name="textSize">14sp</item>
-    </style>
-
-    <style name="TextAppearance.Quantum.Widget.DropDownItem">
-        <item name="textColor">?textColorPrimaryDisableOnly</item>
-    </style>
-
-    <style name="TextAppearance.Quantum.Widget.TextView.SpinnerItem">
-        <item name="textColor">?textColorPrimaryDisableOnly</item>
     </style>
 
     <style name="TextAppearance.Quantum.Widget.EditText">
-        <item name="textColor">@color/bright_foreground_light</item>
-        <item name="textColorHint">@color/hint_foreground_quantum_light</item>
+        <item name="textColor">?textColorPrimaryInverse</item>
+        <item name="textColorHint">?textColorHintInverse</item>
+    </style>
+
+    <style name="TextAppearance.Quantum.Widget.Switch" parent="TextAppearance.Quantum.Small">
+        <item name="textColor">@color/secondary_text_quantum_dark</item>
     </style>
 
     <style name="TextAppearance.Quantum.Widget.PopupMenu" parent="TextAppearance.Widget.PopupMenu">
@@ -199,75 +172,89 @@
         <item name="textSize">14sp</item>
     </style>
 
-    <style name="TextAppearance.Quantum.Widget.ActionBar.Title"
-           parent="TextAppearance.Quantum.Medium">
-        <item name="textSize">@dimen/action_bar_title_text_size</item>
+    <style name="TextAppearance.Quantum.Widget.DropDownHint">
+        <item name="textColor">?attr/textColorPrimary</item>
+        <item name="textSize">14sp</item>
+    </style>
+    <style name="TextAppearance.Quantum.Widget.IconMenu.Item" parent="TextAppearance.Quantum.Small">
+        <item name="textColor">?attr/textColorPrimary</item>
     </style>
 
-    <style name="TextAppearance.Quantum.Widget.ActionBar.Subtitle"
-           parent="TextAppearance.Quantum.Small">
-        <item name="textSize">@dimen/action_bar_subtitle_text_size</item>
+    <!-- This style is for smaller screens; values-xlarge defines a version
+         for larger screens. -->
+    <style name="TextAppearance.Quantum.Widget.TabWidget">
+        <item name="textSize">14sp</item>
+        <item name="textStyle">normal</item>
+        <item name="textColor">@color/tab_indicator_text</item>
     </style>
 
-    <style name="TextAppearance.Quantum.Widget.ActionBar.Title.Inverse"
-           parent="TextAppearance.Quantum.Medium.Inverse">
-        <item name="textSize">@dimen/action_bar_title_text_size</item>
+    <style name="TextAppearance.Quantum.Widget.TextView">
+        <item name="textColor">?attr/textColorPrimaryDisableOnly</item>
+        <item name="textColorHint">?attr/textColorHint</item>
     </style>
 
-    <style name="TextAppearance.Quantum.Widget.ActionBar.Subtitle.Inverse"
-           parent="TextAppearance.Quantum.Small.Inverse">
-        <item name="textSize">@dimen/action_bar_subtitle_text_size</item>
+    <style name="TextAppearance.Quantum.Widget.TextView.PopupMenu">
+        <item name="textSize">18sp</item>
     </style>
 
-    <style name="TextAppearance.Quantum.Widget.ActionBar.Menu"
-           parent="TextAppearance.Quantum.Small">
+    <style name="TextAppearance.Quantum.Widget.TextView.SpinnerItem" />
+
+    <style name="TextAppearance.Quantum.Widget.DropDownItem">
+        <item name="textColor">?attr/textColorPrimaryDisableOnly</item>
+    </style>
+
+    <style name="TextAppearance.Quantum.Widget.ActionMode"/>
+
+    <style name="TextAppearance.Quantum.Widget.ActionMode.Title" parent="TextAppearance.Quantum.Medium">
+        <item name="textSize">@dimen/action_bar_title_text_size_quantum</item>
+    </style>
+
+    <style name="TextAppearance.Quantum.Widget.ActionMode.Subtitle" parent="TextAppearance.Quantum.Small">
+        <item name="textSize">@dimen/action_bar_subtitle_text_size_quantum</item>
+    </style>
+
+    <!-- Text styles with no light versions -->
+
+    <style name="TextAppearance.Quantum.Widget.ActionBar.Title" parent="TextAppearance.Quantum.Medium">
+        <item name="textSize">@dimen/action_bar_title_text_size_quantum</item>
+    </style>
+
+    <style name="TextAppearance.Quantum.Widget.ActionBar.Subtitle" parent="TextAppearance.Quantum.Small">
+        <item name="textSize">@dimen/action_bar_subtitle_text_size_quantum</item>
+    </style>
+
+    <style name="TextAppearance.Quantum.Widget.ActionBar.Title.Inverse" parent="TextAppearance.Quantum.Medium.Inverse">
+        <item name="textSize">@dimen/action_bar_title_text_size_quantum</item>
+    </style>
+
+    <style name="TextAppearance.Quantum.Widget.ActionBar.Subtitle.Inverse" parent="TextAppearance.Quantum.Small.Inverse">
+        <item name="textSize">@dimen/action_bar_subtitle_text_size_quantum</item>
+    </style>
+
+    <style name="TextAppearance.Quantum.Widget.ActionBar.Menu" parent="TextAppearance.Quantum.Small">
         <item name="textSize">12sp</item>
         <item name="textStyle">bold</item>
         <item name="textColor">?attr/actionMenuTextColor</item>
         <item name="textAllCaps">@bool/config_actionMenuItemAllCaps</item>
     </style>
 
-    <style name="TextAppearance.Quantum.Widget.ActionMode"/>
-
-    <style name="TextAppearance.Quantum.Widget.ActionMode.Title"
-           parent="TextAppearance.Quantum.Medium">
-        <item name="textSize">@dimen/action_bar_title_text_size</item>
+    <style name="TextAppearance.Quantum.Widget.ActionMode.Title.Inverse" parent="TextAppearance.Quantum.Medium.Inverse">
+        <item name="textSize">@dimen/action_bar_title_text_size_quantum</item>
     </style>
 
-    <style name="TextAppearance.Quantum.Widget.ActionMode.Subtitle"
-           parent="TextAppearance.Quantum.Small">
-        <item name="textSize">@dimen/action_bar_subtitle_text_size</item>
-    </style>
-
-    <style name="TextAppearance.Quantum.Widget.ActionMode.Title.Inverse"
-           parent="TextAppearance.Quantum.Medium.Inverse">
-        <item name="textSize">@dimen/action_bar_title_text_size</item>
-    </style>
-
-    <style name="TextAppearance.Quantum.Widget.ActionMode.Subtitle.Inverse"
-           parent="TextAppearance.Quantum.Small.Inverse">
-        <item name="textSize">@dimen/action_bar_subtitle_text_size</item>
-    </style>
-
-    <style name="TextAppearance.Quantum.Widget.Switch" parent="TextAppearance.Quantum.Small">
-        <!-- Switch thumb asset presents a dark background. -->
-        <item name="textColor">@color/secondary_text_quantum_dark</item>
-    </style>
-
-    <style name="TextAppearance.Quantum.Light.Widget.Switch" parent="TextAppearance.Quantum.Small">
-        <!-- Switch thumb asset presents a dark background. -->
-        <item name="textColor">@color/primary_text_quantum_dark</item>
+    <style name="TextAppearance.Quantum.Widget.ActionMode.Subtitle.Inverse" parent="TextAppearance.Quantum.Small.Inverse">
+        <item name="textSize">@dimen/action_bar_subtitle_text_size_quantum</item>
     </style>
 
     <style name="TextAppearance.Quantum.WindowTitle">
-        <item name="textColor">#fff</item>
+        <item name="textColor">?attr/textColorPrimary</item>
         <item name="textSize">14sp</item>
         <item name="textStyle">bold</item>
     </style>
 
     <style name="TextAppearance.Quantum.DialogWindowTitle">
         <item name="textSize">22sp</item>
-        <item name="textColor">@color/holo_blue_light</item>
+        <item name="textColor">?attr/textColorPrimary</item>
     </style>
 
     <style name="TextAppearance.Quantum.CalendarViewWeekDayView" parent="TextAppearance.Small.CalendarViewWeekDayView">
@@ -277,12 +264,7 @@
     <!-- Light text styles -->
     <style name="TextAppearance.Quantum.Light" parent="TextAppearance.Quantum"/>
 
-    <style name="TextAppearance.Quantum.Light.Inverse">
-        <item name="textColor">?textColorPrimaryInverse</item>
-        <item name="textColorHint">?textColorHintInverse</item>
-        <item name="textColorHighlight">?textColorHighlightInverse</item>
-        <item name="textColorLink">?textColorLinkInverse</item>
-    </style>
+    <style name="TextAppearance.Quantum.Light.Inverse" parent="TextAppearance.Quantum.Inverse" />
 
     <style name="TextAppearance.Quantum.Light.Large" parent="TextAppearance.Quantum.Large"/>
 
@@ -290,48 +272,26 @@
 
     <style name="TextAppearance.Quantum.Light.Small" parent="TextAppearance.Quantum.Small"/>
 
-    <style name="TextAppearance.Quantum.Light.Large.Inverse">
-        <item name="textColor">?textColorPrimaryInverse</item>
-        <item name="textColorHint">?textColorHintInverse</item>
-        <item name="textColorHighlight">?textColorHighlightInverse</item>
-        <item name="textColorLink">?textColorLinkInverse</item>
-    </style>
+    <style name="TextAppearance.Quantum.Light.Large.Inverse" parent="TextAppearance.Quantum.Large.Inverse" />
 
-    <style name="TextAppearance.Quantum.Light.Medium.Inverse">
-        <item name="textColor">?textColorPrimaryInverse</item>
-        <item name="textColorHint">?textColorHintInverse</item>
-        <item name="textColorHighlight">?textColorHighlightInverse</item>
-        <item name="textColorLink">?textColorLinkInverse</item>
-    </style>
+    <style name="TextAppearance.Quantum.Light.Medium.Inverse" parent="TextAppearance.Quantum.Medium.Inverse" />
 
-    <style name="TextAppearance.Quantum.Light.Small.Inverse">
-        <item name="textColor">?textColorPrimaryInverse</item>
-        <item name="textColorHint">?textColorHintInverse</item>
-        <item name="textColorHighlight">?textColorHighlightInverse</item>
-        <item name="textColorLink">?textColorLinkInverse</item>
-    </style>
+    <style name="TextAppearance.Quantum.Light.Small.Inverse" parent="TextAppearance.Quantum.Small.Inverse" />
 
-    <style name="TextAppearance.Quantum.Light.SearchResult" parent="TextAppearance.Quantum.SearchResult">
-        <item name="textColor">?textColorPrimary</item>
-        <item name="textColorHint">?textColorHint</item>
-    </style>
+    <style name="TextAppearance.Quantum.Light.SearchResult" parent="TextAppearance.Quantum.SearchResult" />
 
-    <style name="TextAppearance.Quantum.Light.SearchResult.Title">
-        <item name="textSize">18sp</item>
-    </style>
+    <style name="TextAppearance.Quantum.Light.SearchResult.Title" parent="TextAppearance.Quantum.SearchResult.Title" />
 
-    <style name="TextAppearance.Quantum.Light.SearchResult.Subtitle">
-        <item name="textSize">14sp</item>
-        <item name="textColor">?textColorSecondary</item>
-    </style>
+    <style name="TextAppearance.Quantum.Light.SearchResult.Subtitle" parent="TextAppearance.Quantum.SearchResult.Subtitle" />
 
     <style name="TextAppearance.Quantum.Light.Widget" parent="TextAppearance.Widget"/>
 
-    <style name="TextAppearance.Quantum.Light.Widget.Button"/>
+    <style name="TextAppearance.Quantum.Light.Widget.Button" parent="TextAppearance.Quantum.Widget.Button" />
 
-    <style name="TextAppearance.Quantum.Light.Widget.EditText">
-        <item name="textColor">@color/bright_foreground_dark</item>
-        <item name="textColorHint">@color/hint_foreground_quantum_dark</item>
+    <style name="TextAppearance.Quantum.Light.Widget.EditText" parent="TextAppearance.Quantum.Widget.EditText" />
+
+    <style name="TextAppearance.Quantum.Light.Widget.Switch" parent="TextAppearance.Quantum.Small">
+        <item name="textColor">@color/secondary_text_quantum_dark</item>
     </style>
 
     <style name="TextAppearance.Quantum.Light.Widget.PopupMenu" parent="TextAppearance.Quantum.Widget.PopupMenu"/>
@@ -346,57 +306,59 @@
 
     <style name="TextAppearance.Quantum.Light.Widget.ActionMode.Subtitle" parent="TextAppearance.Widget.ActionMode.Subtitle"/>
 
-    <style name="TextAppearance.Quantum.Light.WindowTitle">
-        <item name="textColor">#fff</item>
-        <item name="textSize">14sp</item>
-        <item name="textStyle">bold</item>
-    </style>
+    <style name="TextAppearance.Quantum.Light.WindowTitle" parent="TextAppearance.Quantum.WindowTitle" />
 
-    <style name="TextAppearance.Quantum.Light.DialogWindowTitle">
-        <item name="textSize">22sp</item>
-        <item name="textColor">@color/holo_blue_light</item>
-    </style>
+    <style name="TextAppearance.Quantum.Light.DialogWindowTitle" parent="TextAppearance.Quantum.DialogWindowTitle" />
 
     <style name="TextAppearance.Quantum.Light.CalendarViewWeekDayView" parent="TextAppearance.Small.CalendarViewWeekDayView"/>
 
     <!-- Widget Styles -->
 
-    <style name="Widget.Quantum" parent="Widget"/>
 
     <style name="Quantum" />
     <style name="Quantum.Light" />
 
+    <style name="Widget.Quantum" parent="Widget" />
+
+    <!-- Bordered ink button -->
     <style name="Widget.Quantum.Button" parent="Widget.Button">
         <item name="background">@drawable/btn_default_quantum_dark</item>
-        <item name="textAppearance">?attr/textAppearanceMedium</item>
-        <item name="textColor">@color/primary_text_quantum_dark</item>
+        <item name="textAppearance">?attr/textAppearanceButton</item>
         <item name="minHeight">48dip</item>
-        <item name="minWidth">64dip</item>
+        <item name="minWidth">96dip</item>
     </style>
 
-    <style name="Widget.Quantum.StackView">
-        <item name="resOutColor">@color/holo_blue_light</item>
-        <item name="clickColor">@color/holo_blue_light</item>
-    </style>
-
-    <style name="Widget.Quantum.Button.Borderless">
-        <item name="background">?attr/selectableItemBackground</item>
-        <item name="paddingStart">4dip</item>
-        <item name="paddingEnd">4dip</item>
-    </style>
-
-    <style name="Widget.Quantum.Button.Borderless.Small">
-        <item name="textSize">14sp</item>
-    </style>
-
+    <!-- Small bordered ink button -->
     <style name="Widget.Quantum.Button.Small">
-        <item name="background">@drawable/btn_default_quantum_dark</item>
-        <item name="textAppearance">?attr/textAppearanceSmall</item>
-        <item name="textColor">@color/primary_text_quantum_dark</item>
         <item name="minHeight">48dip</item>
         <item name="minWidth">48dip</item>
     </style>
 
+    <!-- Bordered paper button -->
+    <style name="Widget.Quantum.Button.Paper">
+        <!-- TODO: Specify pressed state animation. -->
+    </style>
+
+    <!-- Bordered paper button with color -->
+    <style name="Widget.Quantum.Button.Paper.Color">
+        <item name="background">@drawable/btn_color_quantum_dark</item>
+    </style>
+
+    <!-- Borderless ink button -->
+    <style name="Widget.Quantum.Button.Borderless">
+        <item name="background">@drawable/btn_borderless_quantum_dark</item>
+    </style>
+
+    <!-- Small borderless ink button -->
+    <style name="Widget.Quantum.Button.Borderless.Small">
+        <item name="minHeight">48dip</item>
+        <item name="minWidth">48dip</item>
+    </style>
+
+    <!-- Borderless paper button -->
+    <style name="Widget.Quantum.Button.Borderless.Paper">
+        <!-- TODO: Specify pressed state animation. -->
+    </style>
     <style name="Widget.Quantum.Button.Inset">
         <item name="background">@drawable/button_inset</item>
     </style>
@@ -405,7 +367,6 @@
         <item name="background">@drawable/btn_toggle_holo_dark</item>
         <item name="textOn">@string/capital_on</item>
         <item name="textOff">@string/capital_off</item>
-        <item name="disabledAlpha">?attr/disabledAlpha</item>
         <item name="textAppearance">?attr/textAppearanceSmall</item>
         <item name="minHeight">48dip</item>
     </style>
@@ -430,12 +391,17 @@
         <item name="dividerPadding">0dp</item>
     </style>
 
+    <style name="Widget.Quantum.StackView">
+        <item name="resOutColor">@color/holo_blue_light</item>
+        <item name="clickColor">@color/holo_blue_light</item>
+    </style>
+
     <style name="Widget.Quantum.TextView" parent="Widget.TextView"/>
 
     <style name="Widget.Quantum.CheckedTextView" parent="Widget.CheckedTextView"/>
 
     <style name="Widget.Quantum.TextView.ListSeparator" parent="Widget.TextView.ListSeparator">
-        <item name="background">@drawable/list_section_divider_holo_dark</item>
+        <item name="background">@drawable/list_section_divider_quantum_dark</item>
         <item name="textAllCaps">true</item>
     </style>
 
@@ -446,8 +412,8 @@
     <style name="Widget.Quantum.AbsListView" parent="Widget.AbsListView"/>
 
     <style name="Widget.Quantum.AutoCompleteTextView" parent="Widget.AutoCompleteTextView">
-        <item name="dropDownSelector">@drawable/list_selector_quantum_dark</item>
-        <item name="popupBackground">@drawable/menu_dropdown_panel_holo_dark</item>
+        <item name="dropDownSelector">@drawable/list_selector_holo_dark</item>
+        <item name="popupBackground">?attr/colorBackground</item>
     </style>
 
     <style name="Widget.Quantum.CompoundButton" parent="Widget.CompoundButton"/>
@@ -459,7 +425,7 @@
     <style name="Widget.Quantum.EditText" parent="Widget.EditText"/>
 
     <style name="Widget.Quantum.ExpandableListView" parent="Widget.Quantum.ListView">
-        <item name="groupIndicator">@drawable/expander_group_holo_dark</item>
+        <item name="groupIndicator">@drawable/expander_group_quantum_dark</item>
         <item name="indicatorLeft">?attr/expandableListPreferredItemIndicatorLeft</item>
         <item name="indicatorRight">?attr/expandableListPreferredItemIndicatorRight</item>
         <item name="childDivider">?attr/listDivider</item>
@@ -545,7 +511,7 @@
     </style>
 
     <style name="Widget.Quantum.ProgressBar.Horizontal" parent="Widget.ProgressBar.Horizontal">
-        <item name="progressDrawable">@drawable/progress_horizontal_holo_dark</item>
+        <item name="progressDrawable">@drawable/progress_horizontal_quantum_dark</item>
         <item name="indeterminateDrawable">@drawable/progress_indeterminate_horizontal_holo</item>
         <item name="minHeight">16dip</item>
         <item name="maxHeight">16dip</item>
@@ -569,11 +535,11 @@
 
     <style name="Widget.Quantum.SeekBar">
         <item name="indeterminateOnly">false</item>
-        <item name="progressDrawable">@drawable/scrubber_progress_horizontal_holo_dark</item>
-        <item name="indeterminateDrawable">@drawable/scrubber_progress_horizontal_holo_dark</item>
+        <item name="progressDrawable">@drawable/scrubber_progress_horizontal_quantum_dark</item>
+        <item name="indeterminateDrawable">@drawable/scrubber_progress_horizontal_quantum_dark</item>
         <item name="minHeight">13dip</item>
         <item name="maxHeight">13dip</item>
-        <item name="thumb">@drawable/scrubber_control_selector_holo</item>
+        <item name="thumb">@drawable/scrubber_control_selector_quantum_dark</item>
         <item name="thumbOffset">16dip</item>
         <item name="focusable">true</item>
         <item name="paddingStart">16dip</item>
@@ -607,9 +573,9 @@
     <style name="Widget.Quantum.HorizontalScrollView" parent="Widget.HorizontalScrollView"/>
 
     <style name="Widget.Quantum.Spinner" parent="Widget.Spinner.DropDown">
-        <item name="background">@drawable/spinner_background_holo_dark</item>
-        <item name="dropDownSelector">@drawable/list_selector_quantum_dark</item>
-        <item name="popupBackground">@drawable/menu_dropdown_panel_holo_dark</item>
+        <item name="background">@drawable/spinner_background_quantum_dark</item>
+        <item name="dropDownSelector">@drawable/list_selector_holo_dark</item>
+        <item name="popupBackground">?attr/colorBackground</item>
         <item name="dropDownVerticalOffset">0dip</item>
         <item name="dropDownHorizontalOffset">0dip</item>
         <item name="dropDownWidth">wrap_content</item>
@@ -621,11 +587,11 @@
     <style name="Widget.Quantum.Spinner.DropDown"/>
 
     <style name="Widget.Quantum.Spinner.DropDown.ActionBar">
-        <item name="background">@drawable/spinner_ab_holo_dark</item>
+        <item name="background">@drawable/spinner_background_quantum_dark</item>
     </style>
 
     <style name="Widget.Quantum.CompoundButton.Star" parent="Widget.CompoundButton.Star">
-        <item name="button">@drawable/btn_star_holo_dark</item>
+        <item name="button">@drawable/btn_star_quantum_dark</item>
     </style>
 
     <style name="Widget.Quantum.TabWidget" parent="Widget.TabWidget">
@@ -640,7 +606,7 @@
     </style>
 
     <style name="Widget.Quantum.Tab" parent="Widget.Quantum.ActionBar.TabView">
-        <item name="background">@drawable/tab_indicator_holo</item>
+        <item name="background">@drawable/tab_indicator_quantum_dark</item>
         <item name="layout_width">0dip</item>
         <item name="layout_weight">1</item>
         <item name="minWidth">80dip</item>
@@ -683,8 +649,8 @@
     <style name="Widget.Quantum.QuickContactBadgeSmall.WindowLarge" parent="Widget.QuickContactBadgeSmall.WindowLarge"/>
 
     <style name="Widget.Quantum.ListPopupWindow" parent="Widget.ListPopupWindow">
-        <item name="dropDownSelector">@drawable/list_selector_quantum_dark</item>
-        <item name="popupBackground">@drawable/menu_panel_holo_dark</item>
+        <item name="dropDownSelector">@drawable/list_selector_holo_dark</item>
+        <item name="popupBackground">?attr/colorBackground</item>
         <item name="dropDownVerticalOffset">0dip</item>
         <item name="dropDownHorizontalOffset">0dip</item>
         <item name="dropDownWidth">wrap_content</item>
@@ -708,7 +674,7 @@
     </style>
 
     <style name="Widget.Quantum.ActionButton.Overflow">
-        <item name="src">@drawable/ic_menu_moreoverflow_holo_dark</item>
+        <item name="src">@drawable/ic_menu_moreoverflow_quantum_dark</item>
         <item name="background">?attr/actionBarItemBackground</item>
         <item name="contentDescription">@string/action_menu_overflow_description</item>
     </style>
@@ -716,7 +682,7 @@
     <style name="Widget.Quantum.ActionButton.TextButton" parent="Widget.Quantum.ButtonBar.Button"/>
 
     <style name="Widget.Quantum.ActionBar.TabView" parent="Widget.ActionBar.TabView">
-        <item name="background">@drawable/tab_indicator_ab_holo</item>
+        <item name="background">@drawable/tab_indicator_quantum_dark</item>
         <item name="paddingStart">16dip</item>
         <item name="paddingEnd">16dip</item>
     </style>
@@ -749,7 +715,7 @@
     <style name="Widget.Quantum.ActionBar" parent="Widget.ActionBar">
         <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
         <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
-        <item name="background">@drawable/ab_transparent_dark_holo</item>
+        <item name="background">@drawable/ab_transparent_quantum_dark</item>
         <item name="backgroundStacked">@drawable/ab_stacked_transparent_dark_holo</item>
         <item name="backgroundSplit">@drawable/ab_bottom_transparent_dark_holo</item>
         <item name="divider">?attr/dividerVertical</item>
@@ -773,53 +739,65 @@
     </style>
 
     <style name="Widget.Quantum.CompoundButton.Switch">
-        <item name="track">@drawable/switch_track_holo_dark</item>
-        <item name="thumb">@drawable/switch_inner_holo_dark</item>
+        <item name="track">@drawable/switch_track_quantum_dark</item>
+        <item name="thumb">@drawable/switch_inner_quantum_dark</item>
         <item name="switchTextAppearance">@style/TextAppearance.Quantum.Widget.Switch</item>
-        <item name="textOn">@string/capital_on</item>
-        <item name="textOff">@string/capital_off</item>
+        <item name="textOn"></item>
+        <item name="textOff"></item>
         <item name="thumbTextPadding">12dip</item>
-        <item name="switchMinWidth">96dip</item>
+        <item name="switchMinWidth">72dip</item>
         <item name="switchPadding">16dip</item>
     </style>
 
     <!-- Light widget styles -->
 
-    <style name="Widget.Quantum.Light"/>
+    <style name="Widget.Quantum.Light" parent="Widget" />
 
-    <style name="Widget.Quantum.Light.Button" parent="Widget.Button">
+    <!-- Bordered ink button -->
+    <style name="Widget.Quantum.Light.Button" parent="Widget.Quantum.Button">
         <item name="background">@drawable/btn_default_quantum_light</item>
-        <item name="textAppearance">?attr/textAppearanceMediumInverse</item>
-        <item name="textColor">@color/primary_text_quantum_light</item>
+        <item name="textAppearance">?attr/textAppearanceButton</item>
         <item name="minHeight">48dip</item>
-        <item name="minWidth">64dip</item>
+        <item name="minWidth">96dip</item>
     </style>
 
-    <style name="Widget.Quantum.Light.Button.Borderless">
-        <item name="background">?attr/selectableItemBackground</item>
-        <item name="paddingStart">4dip</item>
-        <item name="paddingEnd">4dip</item>
-    </style>
-
-    <style name="Widget.Quantum.Light.Button.Borderless.Small">
-        <item name="textSize">14sp</item>
-    </style>
-
+    <!-- Small bordered ink button -->
     <style name="Widget.Quantum.Light.Button.Small">
-        <item name="background">@drawable/btn_default_quantum_light</item>
-        <item name="textAppearance">?attr/textAppearanceSmall</item>
-        <item name="textColor">@color/primary_text_quantum_light</item>
         <item name="minHeight">48dip</item>
         <item name="minWidth">48dip</item>
     </style>
 
+    <!-- Bordered paper button -->
+    <style name="Widget.Quantum.Light.Button.Paper">
+        <!-- TODO: Specify pressed state animation. -->
+    </style>
+
+    <!-- Bordered paper button with color -->
+    <style name="Widget.Quantum.Light.Button.Paper.Color">
+        <item name="background">@drawable/btn_color_quantum_light</item>
+    </style>
+
+    <!-- Borderless ink button -->
+    <style name="Widget.Quantum.Light.Button.Borderless">
+        <item name="background">@drawable/btn_borderless_quantum_light</item>
+    </style>
+
+    <!-- Small borderless ink button -->
+    <style name="Widget.Quantum.Light.Button.Borderless.Small">
+        <item name="minHeight">48dip</item>
+        <item name="minWidth">48dip</item>
+    </style>
+
+    <!-- Borderless paper button -->
+    <style name="Widget.Quantum.Light.Button.Borderless.Paper">
+        <!-- TODO: Specify pressed state animation. -->
+    </style>
     <style name="Widget.Quantum.Light.Button.Inset"/>
 
     <style name="Widget.Quantum.Light.Button.Toggle">
         <item name="background">@drawable/btn_toggle_holo_light</item>
         <item name="textOn">@string/capital_on</item>
         <item name="textOff">@string/capital_off</item>
-        <item name="disabledAlpha">?attr/disabledAlpha</item>
         <item name="textAppearance">?attr/textAppearanceSmall</item>
         <item name="minHeight">48dip</item>
     </style>
@@ -840,7 +818,7 @@
     <style name="Widget.Quantum.Light.CheckedTextView" parent="Widget.CheckedTextView"/>
 
     <style name="Widget.Quantum.Light.TextView.ListSeparator" parent="Widget.TextView.ListSeparator">
-        <item name="background">@drawable/list_section_divider_holo_light</item>
+        <item name="background">@drawable/list_section_divider_quantum_light</item>
         <item name="textAllCaps">true</item>
     </style>
 
@@ -851,8 +829,8 @@
     <style name="Widget.Quantum.Light.AbsListView" parent="Widget.AbsListView"/>
 
     <style name="Widget.Quantum.Light.AutoCompleteTextView" parent="Widget.AutoCompleteTextView">
-        <item name="dropDownSelector">@drawable/list_selector_quantum_light</item>
-        <item name="popupBackground">@drawable/menu_dropdown_panel_holo_light</item>
+        <item name="dropDownSelector">@drawable/list_selector_holo_light</item>
+        <item name="popupBackground">?attr/colorBackground</item>
     </style>
 
     <style name="Widget.Quantum.Light.CompoundButton.CheckBox" parent="Widget.CompoundButton.CheckBox"/>
@@ -862,7 +840,7 @@
     <style name="Widget.Quantum.Light.EditText" parent="Widget.Quantum.EditText"/>
 
     <style name="Widget.Quantum.Light.ExpandableListView" parent="Widget.Quantum.Light.ListView">
-        <item name="groupIndicator">@drawable/expander_group_holo_light</item>
+        <item name="groupIndicator">@drawable/expander_group_quantum_light</item>
         <item name="indicatorLeft">?attr/expandableListPreferredItemIndicatorLeft</item>
         <item name="indicatorRight">?attr/expandableListPreferredItemIndicatorRight</item>
         <item name="childDivider">?attr/listDivider</item>
@@ -930,7 +908,7 @@
     <style name="Widget.Quantum.Light.ProgressBar" parent="Widget.Quantum.ProgressBar"/>
 
     <style name="Widget.Quantum.Light.ProgressBar.Horizontal" parent="Widget.Quantum.ProgressBar.Horizontal">
-        <item name="progressDrawable">@drawable/progress_horizontal_holo_light</item>
+        <item name="progressDrawable">@drawable/progress_horizontal_quantum_light</item>
     </style>
 
     <style name="Widget.Quantum.Light.ProgressBar.Small" parent="Widget.Quantum.ProgressBar.Small"/>
@@ -946,8 +924,9 @@
     <style name="Widget.Quantum.Light.ProgressBar.Large.Inverse" parent="Widget.Quantum.ProgressBar.Large.Inverse"/>
 
     <style name="Widget.Quantum.Light.SeekBar" parent="Widget.Quantum.SeekBar">
-        <item name="progressDrawable">@drawable/scrubber_progress_horizontal_holo_light</item>
-        <item name="indeterminateDrawable">@drawable/scrubber_progress_horizontal_holo_light</item>
+        <item name="progressDrawable">@drawable/scrubber_progress_horizontal_quantum_light</item>
+        <item name="indeterminateDrawable">@drawable/scrubber_progress_horizontal_quantum_light</item>
+        <item name="thumb">@drawable/scrubber_control_selector_quantum_light</item>
     </style>
 
     <style name="Widget.Quantum.Light.RatingBar" parent="Widget.RatingBar">
@@ -976,9 +955,9 @@
     <style name="Widget.Quantum.Light.HorizontalScrollView" parent="Widget.HorizontalScrollView"/>
 
     <style name="Widget.Quantum.Light.Spinner" parent="Widget.Quantum.Spinner">
-        <item name="background">@drawable/spinner_background_holo_light</item>
-        <item name="dropDownSelector">@drawable/list_selector_quantum_light</item>
-        <item name="popupBackground">@drawable/menu_dropdown_panel_holo_light</item>
+        <item name="background">@drawable/spinner_background_quantum_light</item>
+        <item name="dropDownSelector">@drawable/list_selector_holo_light</item>
+        <item name="popupBackground">?attr/colorBackground</item>
         <item name="dropDownVerticalOffset">0dip</item>
         <item name="dropDownHorizontalOffset">0dip</item>
         <item name="dropDownWidth">wrap_content</item>
@@ -988,11 +967,11 @@
     <style name="Widget.Quantum.Light.Spinner.DropDown"/>
 
     <style name="Widget.Quantum.Light.Spinner.DropDown.ActionBar">
-        <item name="background">@drawable/spinner_ab_holo_light</item>
+        <item name="background">@drawable/spinner_background_quantum_light</item>
     </style>
 
     <style name="Widget.Quantum.Light.CompoundButton.Star" parent="Widget.CompoundButton.Star">
-        <item name="button">@drawable/btn_star_holo_light</item>
+        <item name="button">@drawable/btn_star_quantum_light</item>
     </style>
 
     <style name="Widget.Quantum.Light.TabWidget" parent="Widget.Quantum.TabWidget"/>
@@ -1022,8 +1001,8 @@
     <style name="Widget.Quantum.Light.QuickContactBadgeSmall.WindowLarge" parent="Widget.QuickContactBadgeSmall.WindowLarge"/>
 
     <style name="Widget.Quantum.Light.ListPopupWindow" parent="Widget.ListPopupWindow">
-        <item name="dropDownSelector">@drawable/list_selector_quantum_light</item>
-        <item name="popupBackground">@drawable/menu_panel_holo_light</item>
+        <item name="dropDownSelector">@drawable/list_selector_holo_light</item>
+        <item name="popupBackground">?attr/colorBackground</item>
         <item name="dropDownVerticalOffset">0dip</item>
         <item name="dropDownHorizontalOffset">0dip</item>
         <item name="dropDownWidth">wrap_content</item>
@@ -1034,14 +1013,15 @@
     <style name="Widget.Quantum.Light.ActionButton" parent="Widget.Quantum.ActionButton"/>
 
     <style name="Widget.Quantum.Light.ActionButton.Overflow">
-        <item name="src">@drawable/ic_menu_moreoverflow_holo_light</item>
+        <item name="src">@drawable/ic_menu_moreoverflow_quantum_light</item>
         <item name="contentDescription">@string/action_menu_overflow_description</item>
     </style>
 
-    <style name="Widget.Quantum.Light.ActionBar.TabView" parent="Widget.Quantum.ActionBar.TabView"/>
+    <style name="Widget.Quantum.Light.ActionBar.TabView" parent="Widget.Quantum.ActionBar.TabView">
+        <item name="background">@drawable/tab_indicator_quantum_light</item>
+    </style>
 
     <style name="Widget.Quantum.Light.Tab" parent="Widget.Quantum.Light.ActionBar.TabView">
-        <item name="background">@drawable/tab_indicator_holo</item>
         <item name="layout_width">0dip</item>
         <item name="layout_weight">1</item>
         <item name="minWidth">80dip</item>
@@ -1076,10 +1056,10 @@
     <style name="Widget.Quantum.Light.ActionBar" parent="Widget.Quantum.ActionBar">
         <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
         <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
-        <item name="background">@drawable/ab_transparent_light_holo</item>
+        <item name="background">@drawable/ab_transparent_quantum_light</item>
         <item name="backgroundStacked">@drawable/ab_stacked_transparent_light_holo</item>
         <item name="backgroundSplit">@drawable/ab_bottom_transparent_light_holo</item>
-        <item name="homeAsUpIndicator">@drawable/ic_ab_back_holo_light</item>
+        <item name="homeAsUpIndicator">@drawable/ic_ab_back_quantum_light</item>
         <item name="progressBarStyle">@style/Widget.Quantum.Light.ProgressBar.Horizontal</item>
         <item name="indeterminateProgressStyle">@style/Widget.Quantum.Light.ProgressBar</item>
     </style>
@@ -1103,7 +1083,7 @@
         <item name="background">@drawable/ab_solid_dark_holo</item>
         <item name="backgroundStacked">@drawable/ab_stacked_solid_dark_holo</item>
         <item name="backgroundSplit">@drawable/ab_bottom_solid_inverse_holo</item>
-        <item name="divider">@drawable/list_divider_holo_dark</item>
+        <item name="divider">@drawable/list_divider_quantum_dark</item>
         <item name="progressBarStyle">@style/Widget.Quantum.ProgressBar.Horizontal</item>
         <item name="indeterminateProgressStyle">@style/Widget.Quantum.ProgressBar</item>
         <item name="progressBarPadding">32dip</item>
@@ -1111,11 +1091,11 @@
     </style>
 
     <style name="Widget.Quantum.Light.CompoundButton.Switch" parent="Widget.CompoundButton.Switch">
-        <item name="track">@drawable/switch_track_holo_light</item>
-        <item name="thumb">@drawable/switch_inner_holo_light</item>
+        <item name="track">@drawable/switch_track_quantum_light</item>
+        <item name="thumb">@drawable/switch_inner_quantum_light</item>
         <item name="switchTextAppearance">@style/TextAppearance.Quantum.Light.Widget.Switch</item>
-        <item name="textOn">@string/capital_on</item>
-        <item name="textOff">@string/capital_off</item>
+        <item name="textOn"></item>
+        <item name="textOff"></item>
         <item name="thumbTextPadding">12dip</item>
         <item name="switchMinWidth">96dip</item>
         <item name="switchPadding">16dip</item>
@@ -1132,16 +1112,16 @@
     <!-- Dialog styles -->
 
     <style name="AlertDialog.Quantum" parent="AlertDialog">
-        <item name="fullDark">@drawable/dialog_full_holo_dark</item>
-        <item name="topDark">@drawable/dialog_top_holo_dark</item>
-        <item name="centerDark">@drawable/dialog_middle_holo_dark</item>
-        <item name="bottomDark">@drawable/dialog_bottom_holo_dark</item>
-        <item name="fullBright">@drawable/dialog_full_holo_dark</item>
-        <item name="topBright">@drawable/dialog_top_holo_dark</item>
-        <item name="centerBright">@drawable/dialog_middle_holo_dark</item>
-        <item name="bottomBright">@drawable/dialog_bottom_holo_dark</item>
-        <item name="bottomMedium">@drawable/dialog_bottom_holo_dark</item>
-        <item name="centerMedium">@drawable/dialog_middle_holo_dark</item>
+        <item name="fullDark">?attr/colorBackground</item>
+        <item name="topDark">?attr/colorBackground</item>
+        <item name="centerDark">?attr/colorBackground</item>
+        <item name="bottomDark">?attr/colorBackground</item>
+        <item name="fullBright">?attr/colorBackground</item>
+        <item name="topBright">?attr/colorBackground</item>
+        <item name="centerBright">?attr/colorBackground</item>
+        <item name="bottomBright">?attr/colorBackground</item>
+        <item name="bottomMedium">?attr/colorBackground</item>
+        <item name="centerMedium">?attr/colorBackground</item>
         <item name="layout">@layout/alert_dialog_holo</item>
         <item name="listLayout">@layout/select_dialog_holo</item>
         <item name="progressLayout">@layout/progress_dialog_holo</item>
@@ -1151,18 +1131,7 @@
         <item name="singleChoiceItemLayout">@layout/select_dialog_singlechoice_holo</item>
     </style>
 
-    <style name="AlertDialog.Quantum.Light">
-        <item name="fullDark">@drawable/dialog_full_holo_light</item>
-        <item name="topDark">@drawable/dialog_top_holo_light</item>
-        <item name="centerDark">@drawable/dialog_middle_holo_light</item>
-        <item name="bottomDark">@drawable/dialog_bottom_holo_light</item>
-        <item name="fullBright">@drawable/dialog_full_holo_light</item>
-        <item name="topBright">@drawable/dialog_top_holo_light</item>
-        <item name="centerBright">@drawable/dialog_middle_holo_light</item>
-        <item name="bottomBright">@drawable/dialog_bottom_holo_light</item>
-        <item name="bottomMedium">@drawable/dialog_bottom_holo_light</item>
-        <item name="centerMedium">@drawable/dialog_middle_holo_light</item>
-    </style>
+    <style name="AlertDialog.Quantum.Light" />
 
     <!-- Window title -->
     <style name="WindowTitleBackground.Quantum">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index b1bf781..6624da4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -289,6 +289,7 @@
   <java-symbol type="bool" name="config_useFixedVolume" />
   <java-symbol type="bool" name="config_forceDefaultOrientation" />
   <java-symbol type="bool" name="config_wifi_batched_scan_supported" />
+  <java-symbol type="bool" name="config_enableMultiUserUI"/>
 
   <java-symbol type="integer" name="config_cursorWindowSize" />
   <java-symbol type="integer" name="config_extraFreeKbytesAdjust" />
@@ -1302,6 +1303,7 @@
   <java-symbol type="bool" name="config_lidControlsSleep" />
   <java-symbol type="bool" name="config_reverseDefaultRotation" />
   <java-symbol type="bool" name="config_showNavigationBar" />
+  <java-symbol type="bool" name="config_supportAutoRotation" />
   <java-symbol type="bool" name="target_honeycomb_needs_options_menu" />
   <java-symbol type="dimen" name="navigation_bar_height" />
   <java-symbol type="dimen" name="navigation_bar_height_landscape" />
@@ -1369,6 +1371,7 @@
   <java-symbol type="layout" name="screen_progress" />
   <java-symbol type="layout" name="screen_simple" />
   <java-symbol type="layout" name="screen_simple_overlay_action_mode" />
+  <java-symbol type="layout" name="screen_swipe_dismiss" />
   <java-symbol type="layout" name="screen_title" />
   <java-symbol type="layout" name="screen_title_icons" />
   <java-symbol type="string" name="system_ui_date_pattern" />
@@ -1625,7 +1628,16 @@
   <java-symbol type="integer" name="config_maxResolverActivityColumns" />
   <java-symbol type="array" name="config_notificationScorers" />
 
-  <!-- From SystemUI -->
+  <java-symbol type="layout" name="notification_quantum_action" />
+  <java-symbol type="layout" name="notification_quantum_action_list" />
+  <java-symbol type="layout" name="notification_quantum_action_tombstone" />
+  <java-symbol type="layout" name="notification_template_quantum_base" />
+  <java-symbol type="layout" name="notification_template_quantum_big_base" />
+  <java-symbol type="layout" name="notification_template_quantum_big_picture" />
+  <java-symbol type="layout" name="notification_template_quantum_big_text" />
+  <java-symbol type="layout" name="notification_template_quantum_inbox" />
+
+    <!-- From SystemUI -->
   <java-symbol type="anim" name="push_down_in" />
   <java-symbol type="anim" name="push_down_out" />
   <java-symbol type="anim" name="push_up_in" />
diff --git a/core/res/res/values/themes_micro.xml b/core/res/res/values/themes_micro.xml
index be5fa99..7c0b7bc 100644
--- a/core/res/res/values/themes_micro.xml
+++ b/core/res/res/values/themes_micro.xml
@@ -14,14 +14,45 @@
      limitations under the License.
 -->
 <resources>
-    <style name="Theme.Micro" parent="Theme.Holo" />
+    <style name="Theme.Micro" parent="Theme.Holo.NoActionBar">
+        <item name="textViewStyle">@android:style/Widget.Micro.TextView</item>
+        <item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item>
+        <item name="windowAnimationStyle">@android:style/Animation.SwipeDismiss</item>
+        <item name="windowIsFloating">false</item>
+        <item name="windowIsTranslucent">true</item>
+        <item name="windowSwipeToDismiss">true</item>
+	</style>
 
-    <style name="Theme.Micro.Light" parent="Theme.Holo.Light"/>
+    <style name="Theme.Micro.NoActionBar" parent="Theme.Holo.NoActionBar">
+        <item name="textViewStyle">@android:style/Widget.Micro.TextView</item>
+        <item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item>
+        <item name="windowAnimationStyle">@android:style/Animation.SwipeDismiss</item>
+        <item name="windowIsFloating">false</item>
+        <item name="windowIsTranslucent">true</item>
+        <item name="windowSwipeToDismiss">true</item>
+    </style>
+    <style name="Theme.Micro.Light" parent="Theme.Holo.Light">
+        <item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item>
+        <item name="windowAnimationStyle">@android:style/Animation.SwipeDismiss</item>
+        <item name="windowIsFloating">false</item>
+        <item name="windowIsTranslucent">true</item>
+        <item name="windowSwipeToDismiss">true</item>
+	</style>
     <style name="Theme.Micro.Light.NoActionBar" parent="Theme.Holo.Light.NoActionBar">
         <item name="textViewStyle">@android:style/Widget.Micro.TextView</item>
+        <item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item>
+        <item name="windowAnimationStyle">@android:style/Animation.SwipeDismiss</item>
+        <item name="windowIsFloating">false</item>
+        <item name="windowIsTranslucent">true</item>
+        <item name="windowSwipeToDismiss">true</item>
     </style>
     <style name="Theme.Micro.Light.DarkActionBar" parent="Theme.Holo.Light.DarkActionBar">
         <item name="textViewStyle">@android:style/Widget.Micro.TextView</item>
+        <item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item>
+        <item name="windowAnimationStyle">@android:style/Animation.SwipeDismiss</item>
+        <item name="windowIsFloating">false</item>
+        <item name="windowIsTranslucent">true</item>
+        <item name="windowSwipeToDismiss">true</item>
     </style>
 
 </resources>
diff --git a/core/res/res/values/themes_quantum.xml b/core/res/res/values/themes_quantum.xml
index f0db46c..d2eee28 100644
--- a/core/res/res/values/themes_quantum.xml
+++ b/core/res/res/values/themes_quantum.xml
@@ -49,42 +49,31 @@
         <item name="disabledAlpha">0.5</item>
         <item name="backgroundDimAmount">0.6</item>
 
-        <item name="colorPressedHighlight">@color/holo_gray_light</item>
-        <item name="colorLongPressedHighlight">@color/holo_gray_bright</item>
-        <item name="colorFocusedHighlight">@color/holo_blue_dark</item>
-        <item name="colorMultiSelectHighlight">@color/holo_green_light</item>
-        <item name="colorActivatedHighlight">@color/holo_blue_dark</item>
-
         <!-- Text styles -->
         <item name="textAppearance">@style/TextAppearance.Quantum</item>
         <item name="textAppearanceInverse">@style/TextAppearance.Quantum.Inverse</item>
 
         <item name="textColorPrimary">@color/primary_text_quantum_dark</item>
-        <item name="textColorSecondary">@color/secondary_text_quantum_dark</item>
-        <item name="textColorTertiary">@color/tertiary_text_quantum_dark</item>
         <item name="textColorPrimaryInverse">@color/primary_text_quantum_light</item>
-        <item name="textColorSecondaryInverse">@color/secondary_text_quantum_light</item>
-        <item name="textColorTertiaryInverse">@color/tertiary_text_quantum_light</item>
         <item name="textColorPrimaryDisableOnly">@color/primary_text_disable_only_quantum_dark</item>
-        <item name="textColorPrimaryInverseDisableOnly">@color/primary_text_disable_only_quantum_light</item>
-        <item name="textColorPrimaryNoDisable">@color/primary_text_nodisable_quantum_dark</item>
-        <item name="textColorSecondaryNoDisable">@color/secondary_text_nodisable_quantum_dark</item>
-        <item name="textColorPrimaryInverseNoDisable">@color/primary_text_nodisable_quantum_light</item>
-        <item name="textColorSecondaryInverseNoDisable">@color/secondary_text_nodisable_quantum_light</item>
+        <item name="textColorSecondary">@color/secondary_text_quantum_dark</item>
+        <item name="textColorSecondaryInverse">@color/secondary_text_quantum_light</item>
+        <item name="textColorTertiary">@color/tertiary_text_quantum_dark</item>
+        <item name="textColorTertiaryInverse">@color/tertiary_text_quantum_light</item>
         <item name="textColorHint">@color/hint_foreground_quantum_dark</item>
         <item name="textColorHintInverse">@color/hint_foreground_quantum_light</item>
-        <item name="textColorSearchUrl">@color/search_url_text_quantum_dark</item>
         <item name="textColorHighlight">@color/highlighted_text_quantum_dark</item>
         <item name="textColorHighlightInverse">@color/highlighted_text_quantum_light</item>
-        <item name="textColorLink">@color/holo_blue_light</item>
-        <item name="textColorLinkInverse">@color/holo_blue_light</item>
+        <item name="textColorLink">@color/quantum_teal_500</item>
+        <item name="textColorLinkInverse">@color/quantum_teal_500</item>
+        <item name="textColorSearchUrl">@color/search_url_text_quantum_dark</item>
         <item name="textColorAlertDialogListItem">@color/primary_text_quantum_dark</item>
 
         <item name="textAppearanceLarge">@style/TextAppearance.Quantum.Large</item>
-        <item name="textAppearanceMedium">@style/TextAppearance.Quantum.Medium</item>
-        <item name="textAppearanceSmall">@style/TextAppearance.Quantum.Small</item>
         <item name="textAppearanceLargeInverse">@style/TextAppearance.Quantum.Large.Inverse</item>
+        <item name="textAppearanceMedium">@style/TextAppearance.Quantum.Medium</item>
         <item name="textAppearanceMediumInverse">@style/TextAppearance.Quantum.Medium.Inverse</item>
+        <item name="textAppearanceSmall">@style/TextAppearance.Quantum.Small</item>
         <item name="textAppearanceSmallInverse">@style/TextAppearance.Quantum.Small.Inverse</item>
         <item name="textAppearanceSearchResultTitle">@style/TextAppearance.Quantum.SearchResult.Title</item>
         <item name="textAppearanceSearchResultSubtitle">@style/TextAppearance.Quantum.SearchResult.Subtitle</item>
@@ -92,7 +81,7 @@
         <item name="textAppearanceButton">@style/TextAppearance.Quantum.Widget.Button</item>
 
         <item name="editTextColor">?attr/textColorPrimary</item>
-        <item name="editTextBackground">@drawable/edit_text_holo_dark</item>
+        <item name="editTextBackground">@drawable/edit_text_quantum_dark</item>
 
         <item name="candidatesTextStyleSpans">@string/candidates_style</item>
 
@@ -104,17 +93,16 @@
 
         <!-- Button styles -->
         <item name="buttonStyle">@style/Widget.Quantum.Button</item>
-
         <item name="buttonStyleSmall">@style/Widget.Quantum.Button.Small</item>
         <item name="buttonStyleInset">@style/Widget.Quantum.Button.Inset</item>
-
         <item name="buttonStyleToggle">@style/Widget.Quantum.Button.Toggle</item>
+
         <item name="switchStyle">@style/Widget.Quantum.CompoundButton.Switch</item>
         <item name="mediaRouteButtonStyle">@style/Widget.Quantum.MediaRouteButton</item>
 
         <item name="selectableItemBackground">@drawable/item_background_quantum_dark</item>
         <item name="borderlessButtonStyle">@style/Widget.Quantum.Button.Borderless</item>
-        <item name="homeAsUpIndicator">@drawable/ic_ab_back_holo_dark</item>
+        <item name="homeAsUpIndicator">@drawable/ic_ab_back_quantum_dark</item>
 
         <!-- List attributes -->
         <item name="listPreferredItemHeight">64dip</item>
@@ -129,17 +117,17 @@
 
         <!-- @hide -->
         <item name="searchResultListItemHeight">58dip</item>
-        <item name="listDivider">@drawable/list_divider_holo_dark</item>
+        <item name="listDivider">@drawable/list_divider_quantum_dark</item>
         <item name="listSeparatorTextViewStyle">@style/Widget.Quantum.TextView.ListSeparator</item>
 
-        <item name="listChoiceIndicatorSingle">@drawable/btn_radio_holo_dark</item>
-        <item name="listChoiceIndicatorMultiple">@drawable/btn_check_holo_dark</item>
+        <item name="listChoiceIndicatorSingle">@drawable/btn_radio_quantum_dark</item>
+        <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum_dark</item>
 
-        <item name="listChoiceBackgroundIndicator">@drawable/list_selector_quantum_dark</item>
+        <item name="listChoiceBackgroundIndicator">@drawable/list_selector_holo_dark</item>
 
-        <item name="activatedBackgroundIndicator">@drawable/activated_background_holo_dark</item>
+        <item name="activatedBackgroundIndicator">@drawable/activated_background_quantum_dark</item>
 
-        <item name="listDividerAlertDialog">@drawable/list_divider_holo_dark</item>
+        <item name="listDividerAlertDialog">@drawable/list_divider_quantum_dark</item>
 
         <item name="expandableListPreferredItemPaddingLeft">40dip</item>
         <item name="expandableListPreferredChildPaddingLeft">?attr/expandableListPreferredItemPaddingLeft</item>
@@ -148,8 +136,8 @@
         <item name="expandableListPreferredItemIndicatorRight">0dip</item>
         <item name="expandableListPreferredChildIndicatorLeft">?attr/expandableListPreferredItemIndicatorLeft</item>
         <item name="expandableListPreferredChildIndicatorRight">?attr/expandableListPreferredItemIndicatorRight</item>
-        <item name="findOnPageNextDrawable">@drawable/ic_find_next_holo_dark</item>
-        <item name="findOnPagePreviousDrawable">@drawable/ic_find_previous_holo_dark</item>
+        <item name="findOnPageNextDrawable">@drawable/ic_find_next_quantum_dark</item>
+        <item name="findOnPagePreviousDrawable">@drawable/ic_find_previous_quantum_dark</item>
 
         <!-- Gallery attributes -->
         <item name="galleryItemBackground">@drawable/gallery_item_background</item>
@@ -182,7 +170,7 @@
         <item name="alertDialogTheme">@style/Theme.Quantum.Dialog.Alert</item>
         <item name="alertDialogStyle">@style/AlertDialog.Quantum</item>
         <item name="alertDialogCenterButtons">false</item>
-        <item name="alertDialogIcon">@drawable/ic_dialog_alert_holo_dark</item>
+        <item name="alertDialogIcon">@drawable/ic_dialog_alert_quantum_dark</item>
 
         <!-- Presentation attributes -->
         <item name="presentationTheme">@style/Theme.Quantum.Dialog.Presentation</item>
@@ -191,7 +179,7 @@
         <item name="toastFrameBackground">@drawable/toast_frame</item>
 
         <!-- Panel attributes -->
-        <item name="panelBackground">@drawable/menu_hardkey_panel_holo_dark</item>
+        <item name="panelBackground">?attr/colorBackground</item>
         <item name="panelFullBackground">@drawable/menu_background_fill_parent_width</item>
         <!-- These three attributes do not seems to be used by the framework. Declared public though -->
         <item name="panelColorBackground">#000</item>
@@ -206,8 +194,8 @@
         <item name="scrollbarFadeDuration">250</item>
         <item name="scrollbarDefaultDelayBeforeFade">300</item>
         <item name="scrollbarSize">10dip</item>
-        <item name="scrollbarThumbHorizontal">@drawable/scrollbar_handle_holo_dark</item>
-        <item name="scrollbarThumbVertical">@drawable/scrollbar_handle_holo_dark</item>
+        <item name="scrollbarThumbHorizontal">@drawable/scrollbar_handle_quantum_dark</item>
+        <item name="scrollbarThumbVertical">@drawable/scrollbar_handle_quantum_dark</item>
         <item name="scrollbarTrackHorizontal">@null</item>
         <item name="scrollbarTrackVertical">@null</item>
 
@@ -217,7 +205,7 @@
         <item name="textSelectHandle">@drawable/text_select_handle_middle</item>
         <item name="textSelectHandleWindowStyle">@style/Widget.Quantum.TextSelectHandle</item>
         <item name="textSuggestionsWindowStyle">@style/Widget.Quantum.TextSuggestionsPopupWindow</item>
-        <item name="textCursorDrawable">@drawable/text_cursor_holo_dark</item>
+        <item name="textCursorDrawable">@drawable/text_cursor_quantum_dark</item>
 
         <!-- Widget styles -->
         <item name="absListViewStyle">@style/Widget.Quantum.AbsListView</item>
@@ -291,7 +279,7 @@
         <item name="editTextPreferenceStyle">@style/Preference.Quantum.DialogPreference.EditTextPreference</item>
         <item name="ringtonePreferenceStyle">@style/Preference.Quantum.RingtonePreference</item>
         <item name="preferenceLayoutChild">@layout/preference_child_holo</item>
-        <item name="detailsElementBackground">@drawable/panel_bg_holo_dark</item>
+        <item name="detailsElementBackground">?attr/colorBackground</item>
 
         <!-- Search widget styles -->
         <item name="searchWidgetCorpusItemBackground">@color/search_widget_corpus_item_background</item>
@@ -300,9 +288,9 @@
         <item name="actionDropDownStyle">@style/Widget.Quantum.Spinner.DropDown.ActionBar</item>
         <item name="actionButtonStyle">@style/Widget.Quantum.ActionButton</item>
         <item name="actionOverflowButtonStyle">@style/Widget.Quantum.ActionButton.Overflow</item>
-        <item name="actionModeBackground">@drawable/cab_background_top_holo_dark</item>
-        <item name="actionModeSplitBackground">@drawable/cab_background_bottom_holo_dark</item>
-        <item name="actionModeCloseDrawable">@drawable/ic_cab_done_holo_dark</item>
+        <item name="actionModeBackground">@color/theme_color_700</item>
+        <item name="actionModeSplitBackground">@color/theme_color_700</item>
+        <item name="actionModeCloseDrawable">@drawable/ic_cab_done_quantum_dark</item>
         <item name="actionBarTabStyle">@style/Widget.Quantum.ActionBar.TabView</item>
         <item name="actionBarTabBarStyle">@style/Widget.Quantum.ActionBar.TabBar</item>
         <item name="actionBarTabTextStyle">@style/Widget.Quantum.ActionBar.TabText</item>
@@ -312,14 +300,15 @@
         <item name="actionBarSize">@dimen/action_bar_default_height</item>
         <item name="actionModePopupWindowStyle">@style/Widget.Quantum.PopupWindow.ActionMode</item>
         <item name="actionBarWidgetTheme">@null</item>
+        <item name="actionBarItemBackground">@drawable/item_background_borderless_quantum_dark</item>
 
-        <item name="actionModeCutDrawable">@drawable/ic_menu_cut_holo_dark</item>
-        <item name="actionModeCopyDrawable">@drawable/ic_menu_copy_holo_dark</item>
-        <item name="actionModePasteDrawable">@drawable/ic_menu_paste_holo_dark</item>
-        <item name="actionModeSelectAllDrawable">@drawable/ic_menu_selectall_holo_dark</item>
-        <item name="actionModeShareDrawable">@drawable/ic_menu_share_holo_dark</item>
-        <item name="actionModeFindDrawable">@drawable/ic_menu_find_holo_dark</item>
-        <item name="actionModeWebSearchDrawable">@drawable/ic_menu_search_holo_dark</item>
+        <item name="actionModeCutDrawable">@drawable/ic_menu_cut_quantum_dark</item>
+        <item name="actionModeCopyDrawable">@drawable/ic_menu_copy_quantum_dark</item>
+        <item name="actionModePasteDrawable">@drawable/ic_menu_paste_quantum_dark</item>
+        <item name="actionModeSelectAllDrawable">@drawable/ic_menu_selectall_quantum_dark</item>
+        <item name="actionModeShareDrawable">@drawable/ic_menu_share_quantum_dark</item>
+        <item name="actionModeFindDrawable">@drawable/ic_menu_find_quantum_dark</item>
+        <item name="actionModeWebSearchDrawable">@drawable/ic_menu_search_quantum_dark</item>
 
         <item name="dividerVertical">?attr/listDivider</item>
         <item name="dividerHorizontal">?attr/listDivider</item>
@@ -359,12 +348,12 @@
         <!-- DatePicker style -->
         <item name="datePickerStyle">@style/Widget.Quantum.DatePicker</item>
 
-        <item name="fastScrollThumbDrawable">@drawable/fastscroll_thumb_holo</item>
+        <!-- TODO: This belongs in a FastScroll style -->
+        <item name="fastScrollThumbDrawable">@drawable/fastscroll_thumb_quantum_light</item>
         <item name="fastScrollPreviewBackgroundLeft">@drawable/fastscroll_label_left_holo_dark</item>
         <item name="fastScrollPreviewBackgroundRight">@drawable/fastscroll_label_right_holo_dark</item>
-        <item name="fastScrollTrackDrawable">@drawable/fastscroll_track_holo_dark</item>
+        <item name="fastScrollTrackDrawable">@drawable/fastscroll_track_quantum_dark</item>
         <item name="fastScrollOverlayPosition">atThumb</item>
-
     </style>
 
     <!-- Quantum Paper theme (light version). -->
@@ -376,42 +365,32 @@
         <item name="disabledAlpha">0.5</item>
         <item name="backgroundDimAmount">0.6</item>
 
-        <item name="colorPressedHighlight">@color/holo_gray_light</item>
-        <item name="colorLongPressedHighlight">@color/holo_gray_bright</item>
-        <item name="colorFocusedHighlight">@color/holo_blue_dark</item>
-        <item name="colorMultiSelectHighlight">@color/holo_green_light</item>
-        <item name="colorActivatedHighlight">@color/holo_blue_dark</item>
-
         <!-- Text styles -->
         <item name="textAppearance">@style/TextAppearance.Quantum.Light</item>
         <item name="textAppearanceInverse">@style/TextAppearance.Quantum.Light.Inverse</item>
 
         <item name="textColorPrimary">@color/primary_text_quantum_light</item>
-        <item name="textColorSecondary">@color/secondary_text_quantum_light</item>
-        <item name="textColorTertiary">@color/tertiary_text_quantum_light</item>
         <item name="textColorPrimaryInverse">@color/primary_text_quantum_dark</item>
+        <item name="textColorSecondary">@color/secondary_text_quantum_light</item>
         <item name="textColorSecondaryInverse">@color/secondary_text_quantum_dark</item>
+        <item name="textColorTertiary">@color/tertiary_text_quantum_light</item>
         <item name="textColorTertiaryInverse">@color/tertiary_text_quantum_dark</item>
         <item name="textColorPrimaryDisableOnly">@color/primary_text_disable_only_quantum_light</item>
         <item name="textColorPrimaryInverseDisableOnly">@color/primary_text_disable_only_quantum_dark</item>
-        <item name="textColorPrimaryNoDisable">@color/primary_text_nodisable_quantum_light</item>
-        <item name="textColorSecondaryNoDisable">@color/secondary_text_nodisable_quantum_light</item>
-        <item name="textColorPrimaryInverseNoDisable">@color/primary_text_nodisable_quantum_dark</item>
-        <item name="textColorSecondaryInverseNoDisable">@color/secondary_text_nodisable_quantum_dark</item>
         <item name="textColorHint">@color/hint_foreground_quantum_light</item>
         <item name="textColorHintInverse">@color/hint_foreground_quantum_dark</item>
-        <item name="textColorSearchUrl">@color/search_url_text_quantum_light</item>
         <item name="textColorHighlight">@color/highlighted_text_quantum_light</item>
         <item name="textColorHighlightInverse">@color/highlighted_text_quantum_dark</item>
-        <item name="textColorLink">@color/holo_blue_light</item>
-        <item name="textColorLinkInverse">@color/holo_blue_light</item>
+        <item name="textColorLink">@color/quantum_teal_500</item>
+        <item name="textColorLinkInverse">@color/quantum_teal_500</item>
+        <item name="textColorSearchUrl">@color/search_url_text_quantum_light</item>
         <item name="textColorAlertDialogListItem">@color/primary_text_quantum_light</item>
 
         <item name="textAppearanceLarge">@style/TextAppearance.Quantum.Light.Large</item>
-        <item name="textAppearanceMedium">@style/TextAppearance.Quantum.Light.Medium</item>
-        <item name="textAppearanceSmall">@style/TextAppearance.Quantum.Light.Small</item>
         <item name="textAppearanceLargeInverse">@style/TextAppearance.Quantum.Light.Large.Inverse</item>
+        <item name="textAppearanceMedium">@style/TextAppearance.Quantum.Light.Medium</item>
         <item name="textAppearanceMediumInverse">@style/TextAppearance.Quantum.Light.Medium.Inverse</item>
+        <item name="textAppearanceSmall">@style/TextAppearance.Quantum.Light.Small</item>
         <item name="textAppearanceSmallInverse">@style/TextAppearance.Quantum.Light.Small.Inverse</item>
         <item name="textAppearanceSearchResultTitle">@style/TextAppearance.Quantum.Light.SearchResult.Title</item>
         <item name="textAppearanceSearchResultSubtitle">@style/TextAppearance.Quantum.Light.SearchResult.Subtitle</item>
@@ -419,7 +398,7 @@
         <item name="textAppearanceButton">@style/TextAppearance.Quantum.Light.Widget.Button</item>
 
         <item name="editTextColor">?attr/textColorPrimary</item>
-        <item name="editTextBackground">@drawable/edit_text_holo_light</item>
+        <item name="editTextBackground">@drawable/edit_text_quantum_light</item>
 
         <item name="candidatesTextStyleSpans">@string/candidates_style</item>
 
@@ -441,7 +420,7 @@
 
         <item name="selectableItemBackground">@drawable/item_background_quantum_light</item>
         <item name="borderlessButtonStyle">@style/Widget.Quantum.Light.Button.Borderless</item>
-        <item name="homeAsUpIndicator">@drawable/ic_ab_back_holo_light</item>
+        <item name="homeAsUpIndicator">@drawable/ic_ab_back_quantum_light</item>
 
         <!-- List attributes -->
         <item name="listPreferredItemHeight">64dip</item>
@@ -456,15 +435,15 @@
 
         <!-- @hide -->
         <item name="searchResultListItemHeight">58dip</item>
-        <item name="listDivider">@drawable/list_divider_holo_light</item>
+        <item name="listDivider">@drawable/list_divider_quantum_light</item>
         <item name="listSeparatorTextViewStyle">@style/Widget.Quantum.Light.TextView.ListSeparator</item>
 
-        <item name="listChoiceIndicatorSingle">@drawable/btn_radio_holo_light</item>
-        <item name="listChoiceIndicatorMultiple">@drawable/btn_check_holo_light</item>
+        <item name="listChoiceIndicatorSingle">@drawable/btn_radio_quantum_light</item>
+        <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum_light</item>
 
-        <item name="listChoiceBackgroundIndicator">@drawable/list_selector_quantum_light</item>
+        <item name="listChoiceBackgroundIndicator">@drawable/list_selector_holo_light</item>
 
-        <item name="activatedBackgroundIndicator">@drawable/activated_background_holo_light</item>
+        <item name="activatedBackgroundIndicator">@drawable/activated_background_quantum_light</item>
 
         <item name="expandableListPreferredItemPaddingLeft">40dip</item>
         <item name="expandableListPreferredChildPaddingLeft">?attr/expandableListPreferredItemPaddingLeft</item>
@@ -474,9 +453,9 @@
         <item name="expandableListPreferredChildIndicatorLeft">?attr/expandableListPreferredItemIndicatorLeft</item>
         <item name="expandableListPreferredChildIndicatorRight">?attr/expandableListPreferredItemIndicatorRight</item>
 
-        <item name="listDividerAlertDialog">@drawable/list_divider_holo_light</item>
-        <item name="findOnPageNextDrawable">@drawable/ic_find_next_holo_light</item>
-        <item name="findOnPagePreviousDrawable">@drawable/ic_find_previous_holo_light</item>
+        <item name="listDividerAlertDialog">@drawable/list_divider_quantum_light</item>
+        <item name="findOnPageNextDrawable">@drawable/ic_find_next_quantum_light</item>
+        <item name="findOnPagePreviousDrawable">@drawable/ic_find_previous_quantum_light</item>
 
         <!-- Gallery attributes -->
         <item name="galleryItemBackground">@drawable/gallery_item_background</item>
@@ -488,7 +467,7 @@
         <item name="windowFullscreen">false</item>
         <item name="windowOverscan">false</item>
         <item name="windowIsFloating">false</item>
-        <item name="windowContentOverlay">@drawable/ab_solid_shadow_holo</item>
+        <item name="windowContentOverlay">@drawable/ab_solid_shadow_qntm</item>
         <item name="windowShowWallpaper">false</item>
         <item name="windowTitleStyle">@style/WindowTitle.Quantum</item>
         <item name="windowTitleSize">25dip</item>
@@ -508,7 +487,7 @@
         <item name="alertDialogTheme">@style/Theme.Quantum.Light.Dialog.Alert</item>
         <item name="alertDialogStyle">@style/AlertDialog.Quantum.Light</item>
         <item name="alertDialogCenterButtons">false</item>
-        <item name="alertDialogIcon">@drawable/ic_dialog_alert_holo_light</item>
+        <item name="alertDialogIcon">@drawable/ic_dialog_alert_quantum_light</item>
 
         <!-- Presentation attributes -->
         <item name="presentationTheme">@style/Theme.Quantum.Light.Dialog.Presentation</item>
@@ -517,7 +496,7 @@
         <item name="toastFrameBackground">@drawable/toast_frame</item>
 
         <!-- Panel attributes -->
-        <item name="panelBackground">@drawable/menu_hardkey_panel_holo_light</item>
+        <item name="panelBackground">?attr/colorBackground</item>
         <item name="panelFullBackground">@drawable/menu_background_fill_parent_width</item>
         <!-- These three attributes do not seems to be used by the framework. Declared public though -->
         <item name="panelColorBackground">#000</item>
@@ -532,8 +511,8 @@
         <item name="scrollbarFadeDuration">250</item>
         <item name="scrollbarDefaultDelayBeforeFade">300</item>
         <item name="scrollbarSize">10dip</item>
-        <item name="scrollbarThumbHorizontal">@drawable/scrollbar_handle_holo_light</item>
-        <item name="scrollbarThumbVertical">@drawable/scrollbar_handle_holo_light</item>
+        <item name="scrollbarThumbHorizontal">@drawable/scrollbar_handle_quantum_light</item>
+        <item name="scrollbarThumbVertical">@drawable/scrollbar_handle_quantum_light</item>
         <item name="scrollbarTrackHorizontal">@null</item>
         <item name="scrollbarTrackVertical">@null</item>
 
@@ -543,7 +522,7 @@
         <item name="textSelectHandle">@drawable/text_select_handle_middle</item>
         <item name="textSelectHandleWindowStyle">@style/Widget.Quantum.TextSelectHandle</item>
         <item name="textSuggestionsWindowStyle">@style/Widget.Quantum.Light.TextSuggestionsPopupWindow</item>
-        <item name="textCursorDrawable">@drawable/text_cursor_holo_light</item>
+        <item name="textCursorDrawable">@drawable/text_cursor_quantum_light</item>
 
         <!-- Widget styles -->
         <item name="absListViewStyle">@style/Widget.Quantum.Light.AbsListView</item>
@@ -617,7 +596,7 @@
         <item name="editTextPreferenceStyle">@style/Preference.Quantum.DialogPreference.EditTextPreference</item>
         <item name="ringtonePreferenceStyle">@style/Preference.Quantum.RingtonePreference</item>
         <item name="preferenceLayoutChild">@layout/preference_child_holo</item>
-        <item name="detailsElementBackground">@drawable/panel_bg_holo_light</item>
+        <item name="detailsElementBackground">?attr/colorBackground</item>
 
         <!-- PreferenceFrameLayout attributes -->
         <item name="preferenceFrameLayoutStyle">@style/Widget.Quantum.PreferenceFrameLayout</item>
@@ -631,7 +610,7 @@
         <item name="actionOverflowButtonStyle">@style/Widget.Quantum.Light.ActionButton.Overflow</item>
         <item name="actionModeBackground">@drawable/cab_background_top_holo_light</item>
         <item name="actionModeSplitBackground">@drawable/cab_background_bottom_holo_light</item>
-        <item name="actionModeCloseDrawable">@drawable/ic_cab_done_holo_light</item>
+        <item name="actionModeCloseDrawable">@drawable/ic_cab_done_quantum_light</item>
         <item name="actionBarTabStyle">@style/Widget.Quantum.Light.ActionBar.TabView</item>
         <item name="actionBarTabBarStyle">@style/Widget.Quantum.Light.ActionBar.TabBar</item>
         <item name="actionBarTabTextStyle">@style/Widget.Quantum.Light.ActionBar.TabText</item>
@@ -641,14 +620,15 @@
         <item name="actionBarSize">@dimen/action_bar_default_height</item>
         <item name="actionModePopupWindowStyle">@style/Widget.Quantum.Light.PopupWindow.ActionMode</item>
         <item name="actionBarWidgetTheme">@null</item>
+        <item name="actionBarItemBackground">@drawable/item_background_borderless_quantum_light</item>
 
-        <item name="actionModeCutDrawable">@drawable/ic_menu_cut_holo_light</item>
-        <item name="actionModeCopyDrawable">@drawable/ic_menu_copy_holo_light</item>
-        <item name="actionModePasteDrawable">@drawable/ic_menu_paste_holo_light</item>
-        <item name="actionModeSelectAllDrawable">@drawable/ic_menu_selectall_holo_light</item>
-        <item name="actionModeShareDrawable">@drawable/ic_menu_share_holo_light</item>
-        <item name="actionModeFindDrawable">@drawable/ic_menu_find_holo_light</item>
-        <item name="actionModeWebSearchDrawable">@drawable/ic_menu_search_holo_light</item>
+        <item name="actionModeCutDrawable">@drawable/ic_menu_cut_quantum_light</item>
+        <item name="actionModeCopyDrawable">@drawable/ic_menu_copy_quantum_light</item>
+        <item name="actionModePasteDrawable">@drawable/ic_menu_paste_quantum_light</item>
+        <item name="actionModeSelectAllDrawable">@drawable/ic_menu_selectall_quantum_light</item>
+        <item name="actionModeShareDrawable">@drawable/ic_menu_share_quantum_light</item>
+        <item name="actionModeFindDrawable">@drawable/ic_menu_find_quantum_light</item>
+        <item name="actionModeWebSearchDrawable">@drawable/ic_menu_search_quantum_light</item>
 
         <item name="dividerVertical">?attr/listDivider</item>
         <item name="dividerHorizontal">?attr/listDivider</item>
@@ -685,45 +665,18 @@
         <!-- DatePicker style -->
         <item name="datePickerStyle">@style/Widget.Quantum.Light.DatePicker</item>
 
-        <item name="fastScrollThumbDrawable">@drawable/fastscroll_thumb_holo</item>
+        <item name="fastScrollThumbDrawable">@drawable/fastscroll_thumb_quantum_light</item>
         <item name="fastScrollPreviewBackgroundLeft">@drawable/fastscroll_label_left_holo_light</item>
         <item name="fastScrollPreviewBackgroundRight">@drawable/fastscroll_label_right_holo_light</item>
-        <item name="fastScrollTrackDrawable">@drawable/fastscroll_track_holo_light</item>
+        <item name="fastScrollTrackDrawable">@drawable/fastscroll_track_quantum_light</item>
         <item name="fastScrollOverlayPosition">atThumb</item>
-
     </style>
 
     <!-- Variant of the quantum (light) theme that has a solid (opaque) action bar
          with an inverse color profile. The dark action bar sharply stands out against
          the light content. -->
     <style name="Theme.Quantum.Light.DarkActionBar">
-        <item name="windowContentOverlay">@drawable/ab_solid_shadow_holo</item>
-        <item name="actionBarStyle">@style/Widget.Quantum.Light.ActionBar.Solid.Inverse</item>
-        <item name="actionBarWidgetTheme">@style/Theme.Quantum</item>
-
-        <item name="actionDropDownStyle">@style/Widget.Quantum.Spinner.DropDown.ActionBar</item>
-        <item name="actionButtonStyle">@style/Widget.Quantum.ActionButton</item>
-        <item name="actionOverflowButtonStyle">@style/Widget.Quantum.ActionButton.Overflow</item>
-        <item name="actionModeBackground">@drawable/cab_background_top_holo_dark</item>
-        <item name="actionModeSplitBackground">@drawable/cab_background_bottom_holo_dark</item>
-        <item name="actionModeCloseDrawable">@drawable/ic_cab_done_holo_dark</item>
-        <item name="homeAsUpIndicator">@drawable/ic_ab_back_holo_dark</item>
-        <item name="actionBarTabStyle">@style/Widget.Quantum.Light.ActionBar.TabView.Inverse</item>
-        <item name="actionBarTabBarStyle">@style/Widget.Quantum.Light.ActionBar.TabBar.Inverse</item>
-        <item name="actionBarTabTextStyle">@style/Widget.Quantum.Light.ActionBar.TabText.Inverse</item>
-        <item name="actionBarDivider">@drawable/list_divider_holo_dark</item>
-        <item name="actionMenuTextColor">?attr/textColorPrimaryInverse</item>
-        <item name="actionModeStyle">@style/Widget.Quantum.Light.ActionMode.Inverse</item>
-        <item name="actionModeCloseButtonStyle">@style/Widget.Quantum.ActionButton.CloseMode</item>
-        <item name="actionModePopupWindowStyle">@style/Widget.Quantum.PopupWindow.ActionMode</item>
-
-        <item name="actionModeCutDrawable">@drawable/ic_menu_cut_holo_dark</item>
-        <item name="actionModeCopyDrawable">@drawable/ic_menu_copy_holo_dark</item>
-        <item name="actionModePasteDrawable">@drawable/ic_menu_paste_holo_dark</item>
-        <item name="actionModeSelectAllDrawable">@drawable/ic_menu_selectall_holo_dark</item>
-        <item name="actionModeShareDrawable">@drawable/ic_menu_share_holo_dark</item>
-        <item name="actionModeFindDrawable">@drawable/ic_menu_find_holo_dark</item>
-        <item name="actionModeWebSearchDrawable">@drawable/ic_menu_search_holo_dark</item>
+        <item name="actionBarTheme">@style/Theme.Quantum</item>
     </style>
 
     <!-- Variant of the quantum (dark) theme with no action bar. -->
@@ -877,7 +830,7 @@
     <style name="Theme.Quantum.Dialog">
         <item name="windowFrame">@null</item>
         <item name="windowTitleStyle">@style/DialogWindowTitle.Quantum</item>
-        <item name="windowBackground">@drawable/dialog_full_holo_dark</item>
+        <item name="windowBackground">?attr/colorBackground</item>
         <item name="windowIsFloating">true</item>
         <item name="windowContentOverlay">@null</item>
         <item name="windowAnimationStyle">@style/Animation.Quantum.Dialog</item>
@@ -999,7 +952,7 @@
     <style name="Theme.Quantum.Light.Dialog">
         <item name="windowFrame">@null</item>
         <item name="windowTitleStyle">@style/DialogWindowTitle.Quantum.Light</item>
-        <item name="windowBackground">@drawable/dialog_full_holo_light</item>
+        <item name="windowBackground">?attr/colorBackground</item>
         <item name="windowIsFloating">true</item>
         <item name="windowContentOverlay">@null</item>
         <item name="windowAnimationStyle">@style/Animation.Quantum.Dialog</item>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
index b942eb6..cad030a 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
@@ -252,26 +252,26 @@
                 if (!validateEapValue(eapValue)) {
                     throw new SAXException();
                 }
-		if (eapValue.equals("TLS")) {
-		    config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
-		} else if (eapValue.equals("TTLS")) {
-		    config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS);
-		} else if (eapValue.equals("PEAP")) {
-		    config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.PEAP);
-		}
+                if (eapValue.equals("TLS")) {
+                    config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+                } else if (eapValue.equals("TTLS")) {
+                    config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS);
+                } else if (eapValue.equals("PEAP")) {
+                    config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.PEAP);
+                }
                 eap = false;
             }
             if (phase2) {
                 String phase2Value = new String(ch, start, length);
-		if (phase2Value.equals("PAP")) {
+                if (phase2Value.equals("PAP")) {
                     config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.PAP);
-		} else if (phase2Value.equals("MSCHAP")) {
+                } else if (phase2Value.equals("MSCHAP")) {
                     config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.MSCHAP);
-		} else if (phase2Value.equals("MSCHAPV2")) {
+                } else if (phase2Value.equals("MSCHAPV2")) {
                     config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.MSCHAPV2);
-		} else if (phase2Value.equals("GTC")) {
+                } else if (phase2Value.equals("GTC")) {
                     config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.GTC);
-		}
+                }
                 phase2 = false;
             }
             if (identity) {
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/NetworkState.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/NetworkState.java
index 5a4a2d0..9d97ac5 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/NetworkState.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/NetworkState.java
@@ -101,9 +101,10 @@
     }
 
     /*
-     * Transition from CONNECTED -> DISCONNECTED:
-     *    CONNECTED->DISCONNECTING->DISCONNECTED
-     * return false if any state transition is not valid and save a message in mReason
+     * Verifies state transition from CONNECTED->...-> DISCONNECTED.
+     *
+     * returns false if initial state or target state is not correct, or if there is
+     * any transition from DISCONNECTING/DISCONNECTED -> CONNECTED.
      */
     public boolean transitToDisconnection () {
         mReason = "states: " + printStates();
@@ -120,13 +121,13 @@
         for (int i = 1; i < mStateDepository.size() - 1; i++) {
             State preState = mStateDepository.get(i-1);
             State curState = mStateDepository.get(i);
-            if ((preState == State.CONNECTED) && ((curState == State.DISCONNECTING) ||
+            if (preState == curState) {
+                continue;
+            } else if ((preState == State.CONNECTED) && ((curState == State.DISCONNECTING) ||
                     (curState == State.DISCONNECTED))) {
                 continue;
             } else if ((preState == State.DISCONNECTING) && (curState == State.DISCONNECTED)) {
                 continue;
-            } else if ((preState == State.DISCONNECTED) && (curState == State.DISCONNECTED)) {
-                continue;
             } else {
                 mReason += " Transition state from " + preState.toString() + " to " +
                         curState.toString() + " is not valid.";
@@ -136,7 +137,12 @@
         return true;
     }
 
-    // DISCONNECTED->CONNECTING->CONNECTED
+    /*
+     * Verifies state transition from DISCONNECTED->...-> CONNECTED.
+     *
+     * returns false if initial state or target state is not correct, or if there is
+     * any transition from CONNECED -> DISCONNECTED.
+     */
     public boolean transitToConnection() {
         mReason = "states: " + printStates();
         if (mStateDepository.get(0) != State.DISCONNECTED) {
@@ -152,14 +158,15 @@
         for (int i = 1; i < mStateDepository.size(); i++) {
             State preState = mStateDepository.get(i-1);
             State curState = mStateDepository.get(i);
+            if (preState == curState) {
+                continue;
+            }
             if ((preState == State.DISCONNECTED) && ((curState == State.CONNECTING) ||
-                    (curState == State.CONNECTED) || (curState == State.DISCONNECTED))) {
+                    (curState == State.CONNECTED))) {
                 continue;
-            } else if ((preState == State.CONNECTING) && (curState == State.CONNECTED)) {
-                continue;
-            } else if ((preState == State.CONNECTED) && (curState == State.CONNECTED)) {
-                continue;
-            } else {
+             } else if ((preState == State.CONNECTING) && (curState == State.CONNECTED)) {
+                 continue;
+             } else {
                 mReason += " Transition state from " + preState.toString() + " to " +
                         curState.toString() + " is not valid.";
                 return false;
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
index 04ce4b7..91c3093 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
@@ -27,6 +27,7 @@
 import android.net.wifi.WifiManager;
 import android.os.Environment;
 import android.os.PowerManager;
+import android.os.SystemClock;
 import android.provider.Settings;
 import android.view.KeyEvent;
 import android.test.suitebuilder.annotation.LargeTest;
@@ -52,6 +53,7 @@
         extends ConnectivityManagerTestBase {
     private final static String TAG = "WifiStressTest";
 
+    private final static long SCREEN_OFF_TIMER = 500; //500ms
     /**
      * Wi-Fi idle time for default sleep policy
      */
@@ -157,11 +159,11 @@
             writeOutput(String.format("average scanning time is %d", averageScanTime));
             writeOutput(String.format("ssid appear %d out of %d scan iterations",
                     ssidAppearInScanResultsCount, i));
-            long startTime = System.currentTimeMillis();
+            long startTime = SystemClock.uptimeMillis();
             scanResultAvailable = false;
             assertTrue("start scan failed", mWifiManager.startScan());
             while (true) {
-                if ((System.currentTimeMillis() - startTime) >
+                if ((SystemClock.uptimeMillis() - startTime) >
                 WIFI_SCAN_TIMEOUT) {
                     fail("Wifi scanning takes more than " + WIFI_SCAN_TIMEOUT + " ms");
                 }
@@ -172,7 +174,7 @@
                         e.printStackTrace();
                     }
                     if (scanResultAvailable) {
-                        long scanTime = (System.currentTimeMillis() - startTime);
+                        long scanTime = (SystemClock.uptimeMillis() - startTime);
                         scanTimeSum += scanTime;
                         break;
                     }
@@ -255,8 +257,13 @@
                     i, mReconnectIterations));
             log("iteration: " + i);
             turnScreenOff();
+            // Use clock time since boot for intervals.
+            long start = SystemClock.uptimeMillis();
             PowerManager pm =
                 (PowerManager)mRunner.getContext().getSystemService(Context.POWER_SERVICE);
+            while (pm.isScreenOn() && ((SystemClock.uptimeMillis() - start) < SCREEN_OFF_TIMER)) {
+                sleep(100, "wait for screen off");
+            }
             assertFalse(pm.isScreenOn());
             sleep(WIFI_IDLE_MS + WIFI_SHUTDOWN_DELAY, "Interruped while wait for wifi to be idle");
             assertTrue("Wait for Wi-Fi to idle timeout",
@@ -287,14 +294,14 @@
             mRunner.sendKeyDownUpSync(KeyEvent.KEYCODE_MENU);
 
             // Measure the time for Wi-Fi to get connected
-            long startTime = System.currentTimeMillis();
+            long startTime = SystemClock.uptimeMillis();
             assertTrue("Wait for Wi-Fi enable timeout after wake up",
                     waitForWifiState(WifiManager.WIFI_STATE_ENABLED,
                     SHORT_TIMEOUT));
             assertTrue("Wait for Wi-Fi connection timeout after wake up",
                     waitForNetworkState(ConnectivityManager.TYPE_WIFI, State.CONNECTED,
                     WIFI_CONNECTION_TIMEOUT));
-            long connectionTime = System.currentTimeMillis() - startTime;
+            long connectionTime = SystemClock.uptimeMillis() - startTime;
             sum += connectionTime;
             log("average reconnection time is: " + sum/(i+1));
 
diff --git a/core/tests/coretests/src/android/app/TranslucentFancyActivity.java b/core/tests/coretests/src/android/app/TranslucentFancyActivity.java
index ec5ad7a..35abaaa 100644
--- a/core/tests/coretests/src/android/app/TranslucentFancyActivity.java
+++ b/core/tests/coretests/src/android/app/TranslucentFancyActivity.java
@@ -53,7 +53,7 @@
      * describe what is to be displayed in the screen.
      */
     @Override
-	protected void onCreate(Bundle icicle)
+    protected void onCreate(Bundle icicle)
     {
         // Be sure to call the super class.
         super.onCreate(icicle);
diff --git a/core/tests/coretests/src/android/app/activity/AbortReceiver.java b/core/tests/coretests/src/android/app/activity/AbortReceiver.java
index fef1775..8d5c022 100644
--- a/core/tests/coretests/src/android/app/activity/AbortReceiver.java
+++ b/core/tests/coretests/src/android/app/activity/AbortReceiver.java
@@ -32,7 +32,7 @@
 
     public void onReceive(Context context, Intent intent)
     {
-	//Log.i("AbortReceiver", "onReceiveIntent!");
+        //Log.i("AbortReceiver", "onReceiveIntent!");
         try {
             IBinder caller = intent.getIBinderExtra("caller");
             Parcel data = Parcel.obtain();
diff --git a/core/tests/coretests/src/android/app/activity/RemoteSubActivityScreen.java b/core/tests/coretests/src/android/app/activity/RemoteSubActivityScreen.java
index e969d10..9f402a5 100644
--- a/core/tests/coretests/src/android/app/activity/RemoteSubActivityScreen.java
+++ b/core/tests/coretests/src/android/app/activity/RemoteSubActivityScreen.java
@@ -24,19 +24,19 @@
 import android.util.Log;
 
 public class RemoteSubActivityScreen extends SubActivityScreen {
-	Handler mHandler = new Handler();
-	boolean mFirst = false;
+    Handler mHandler = new Handler();
+    boolean mFirst = false;
 
     public RemoteSubActivityScreen() {
     }
 
     @Override
     public void onCreate(Bundle icicle) {
-    	// We are running in a remote process, so want to have the sub-activity
-    	// sending the result back in the original process.
+        // We are running in a remote process, so want to have the sub-activity
+        // sending the result back in the original process.
         Intent intent = getIntent();
-    	intent.setClass(this, SubActivityScreen.class);
-    	
+        intent.setClass(this, SubActivityScreen.class);
+        
         super.onCreate(icicle);
         
         boolean kill = intent.getBooleanExtra("kill", false);
@@ -44,16 +44,16 @@
         //        + " kill=" + kill);
         
         if (kill) {
-	        // After finishing initialization, kill the process!  But only if
-	        // this is the first time...
-	        if (icicle == null) {
-		        mHandler.post(new Runnable() {
-		        	public void run() {
-		        		handleBeforeStopping();
-		        		Process.killProcess(Process.myPid());
-		        	}
-		        });
-	        }
+            // After finishing initialization, kill the process!  But only if
+            // this is the first time...
+            if (icicle == null) {
+                mHandler.post(new Runnable() {
+                    public void run() {
+                        handleBeforeStopping();
+                        Process.killProcess(Process.myPid());
+                    }
+                });
+            }
         }
     }
 }
diff --git a/core/tests/coretests/src/android/app/activity/SubActivityScreen.java b/core/tests/coretests/src/android/app/activity/SubActivityScreen.java
index 919c591..3caec7a 100644
--- a/core/tests/coretests/src/android/app/activity/SubActivityScreen.java
+++ b/core/tests/coretests/src/android/app/activity/SubActivityScreen.java
@@ -44,24 +44,24 @@
         // Move on to the next thing that will generate a result...  but only
         // if we are being launched for the first time.
         if (icicle == null) {
-	        if (mMode == PENDING_RESULT_MODE) {
-	            PendingIntent apr = createPendingResult(1, null,
-	                    Intent.FILL_IN_ACTION);
-	            Intent res = new Intent();
+            if (mMode == PENDING_RESULT_MODE) {
+                PendingIntent apr = createPendingResult(1, null,
+                        Intent.FILL_IN_ACTION);
+                Intent res = new Intent();
                 res.putExtra("tkey", "tval");
                 res.setAction("test");
-	            try {
-    	            apr.send(this, RESULT_OK, res);
-	            } catch (PendingIntent.CanceledException e) {
-	            }
-	        } else if (mMode < CHILD_OFFSET) {
-	            Intent intent = new Intent();
-	        	intent.setClass(this, SubActivityScreen.class);
-	            intent.putExtra("mode", CHILD_OFFSET+mMode);
-	            //System.out.println("*** Starting from onStart: " + intent);
-	            startActivityForResult(intent, 1);
-	            return;
-	        }
+                try {
+                    apr.send(this, RESULT_OK, res);
+                } catch (PendingIntent.CanceledException e) {
+                }
+            } else if (mMode < CHILD_OFFSET) {
+                Intent intent = new Intent();
+                intent.setClass(this, SubActivityScreen.class);
+                intent.putExtra("mode", CHILD_OFFSET+mMode);
+                //System.out.println("*** Starting from onStart: " + intent);
+                startActivityForResult(intent, 1);
+                return;
+            }
         }
     }
 
@@ -77,15 +77,15 @@
         //Log.i("foo", "SubActivityScreen pid=" + Process.myPid() + " onResume");
         
         if (mMode >= CHILD_OFFSET) {
-        	// Wait a little bit, to give our parent time to kill itself
-        	// if that is something it is into.
-        	try {
-	        	Thread.sleep(500);
-        	} catch (InterruptedException e) {
-        		setResult(RESULT_CANCELED, (new Intent()).setAction("Interrupted!"));
-        		finish();
-        		return;
-        	}
+            // Wait a little bit, to give our parent time to kill itself
+            // if that is something it is into.
+            try {
+                Thread.sleep(500);
+            } catch (InterruptedException e) {
+                setResult(RESULT_CANCELED, (new Intent()).setAction("Interrupted!"));
+                finish();
+                return;
+            }
             //System.out.println("Resuming sub-activity: mode=" + mMode);
             switch (mMode-CHILD_OFFSET) {
             case NO_RESULT_MODE:
diff --git a/core/tests/coretests/src/android/database/DatabaseCursorTest.java b/core/tests/coretests/src/android/database/DatabaseCursorTest.java
index 36f0f4b..08cd027 100644
--- a/core/tests/coretests/src/android/database/DatabaseCursorTest.java
+++ b/core/tests/coretests/src/android/database/DatabaseCursorTest.java
@@ -51,8 +51,8 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-	File dbDir = getContext().getDir("tests", Context.MODE_PRIVATE);
-	mDatabaseFile = new File(dbDir, "database_test.db");
+        File dbDir = getContext().getDir("tests", Context.MODE_PRIVATE);
+        mDatabaseFile = new File(dbDir, "database_test.db");
 
         if (mDatabaseFile.exists()) {
             mDatabaseFile.delete();
diff --git a/core/tests/coretests/src/android/database/DatabaseStatementTest.java b/core/tests/coretests/src/android/database/DatabaseStatementTest.java
index 512d5cd..895d715 100644
--- a/core/tests/coretests/src/android/database/DatabaseStatementTest.java
+++ b/core/tests/coretests/src/android/database/DatabaseStatementTest.java
@@ -41,8 +41,8 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-	File dbDir = getContext().getDir("tests", Context.MODE_PRIVATE);
-	mDatabaseFile = new File(dbDir, "database_test.db");
+        File dbDir = getContext().getDir("tests", Context.MODE_PRIVATE);
+        mDatabaseFile = new File(dbDir, "database_test.db");
 
         if (mDatabaseFile.exists()) {
             mDatabaseFile.delete();
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
new file mode 100644
index 0000000..9f04228
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
@@ -0,0 +1,41 @@
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := 9
+
+LOCAL_PACKAGE_NAME := MultiDexLegacyVersionedTestApp_v1
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex
+
+mainDexList:= \
+	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
+
+LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
+
+include $(BUILD_PACKAGE)
+
+$(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
+	$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
+	echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@
+
+$(built_dex_intermediate): $(mainDexList)
+
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/AndroidManifest.xml
new file mode 100644
index 0000000..c7b066d
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.framework.multidexlegacyversionedtestapp"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="9"
+        android:targetSdkVersion="18" />
+
+    <application
+        android:name="android.support.multidex.MultiDexApplication"
+        android:allowBackup="true"
+        android:label="MultiDexLegacyVersionedTestApp_v1">
+        <activity
+            android:name="com.android.framework.multidexlegacyversionedtestapp.MainActivity"
+            android:label="MultiDexLegacyVersionedTestApp_v1" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+                     android:targetPackage="com.android.framework.multidexlegacyversionedtestapp"
+                     android:label="Test for MultiDexLegacyVersionedTestApp_v1" />
+
+</manifest>
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/res/layout/activity_main.xml b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/res/layout/activity_main.xml
new file mode 100644
index 0000000..58ae67a
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/res/layout/activity_main.xml
@@ -0,0 +1,7 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".MainActivity" >
+
+</RelativeLayout>
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/ClassForMainDex.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/ClassForMainDex.java
new file mode 100644
index 0000000..8662562
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/ClassForMainDex.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2014 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.framework.multidexlegacyversionedtestapp;
+
+/**
+ * Class directly referenced from Activity, will be kept in main dex. The class is not referenced
+ * by <clinit> or <init>, its direct references are not kept in main dex.
+ */
+public class ClassForMainDex {
+
+    public static int getVersion() {
+        return Version.getVersion();
+    }
+
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/MainActivity.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/MainActivity.java
new file mode 100644
index 0000000..351d860
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/MainActivity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014 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.framework.multidexlegacyversionedtestapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class MainActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+    }
+
+    public int getVersion() {
+        return ClassForMainDex.getVersion();
+    }
+
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.java
new file mode 100644
index 0000000..24b4d69
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2014 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.framework.multidexlegacyversionedtestapp;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+ * Run the tests with: <code>adb shell am instrument -w
+ com.android.framework.multidexlegacyversionedtestapp/android.test.InstrumentationTestRunner
+</code>
+ */
+public class MultiDexUpdateTest extends ActivityInstrumentationTestCase2<MainActivity>
+{
+    public MultiDexUpdateTest() {
+        super(MainActivity.class);
+    }
+
+    /**
+     * Tests that all classes of the application can be loaded. Verifies also that we load the
+     * correct version of {@link Version} ie the class is the secondary dex file.
+     */
+    public void testAllClassAvailable()
+    {
+        assertEquals(1, getActivity().getVersion());
+    }
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/Version.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/Version.java
new file mode 100644
index 0000000..eb9827a
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/src/com/android/framework/multidexlegacyversionedtestapp/Version.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2014 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.framework.multidexlegacyversionedtestapp;
+
+/* can go in secondary dex */
+public class Version {
+
+    public static int getVersion() {
+        return 1;
+    }
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
new file mode 100644
index 0000000..1b8da41
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
@@ -0,0 +1,41 @@
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := 9
+
+LOCAL_PACKAGE_NAME := MultiDexLegacyVersionedTestApp_v2
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex
+
+mainDexList:= \
+	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
+
+LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
+
+include $(BUILD_PACKAGE)
+
+$(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
+	$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
+	echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@
+
+$(built_dex_intermediate): $(mainDexList)
+
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/AndroidManifest.xml
new file mode 100644
index 0000000..4d24793
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.framework.multidexlegacyversionedtestapp"
+    android:versionCode="2"
+    android:versionName="2.0" >
+
+    <uses-sdk
+        android:minSdkVersion="9"
+        android:targetSdkVersion="18" />
+
+    <application
+        android:name="android.support.multidex.MultiDexApplication"
+        android:allowBackup="true"
+        android:label="MultiDexLegacyVersionedTestApp_v2">
+        <activity
+            android:name="com.android.framework.multidexlegacyversionedtestapp.MainActivity"
+            android:label="MultiDexLegacyVersionedTestApp_v2" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+                     android:targetPackage="com.android.framework.multidexlegacyversionedtestapp"
+                     android:label="Test for MultiDexLegacyVersionedTestApp_v2" />
+
+</manifest>
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/res/layout/activity_main.xml b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/res/layout/activity_main.xml
new file mode 100644
index 0000000..58ae67a
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/res/layout/activity_main.xml
@@ -0,0 +1,7 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".MainActivity" >
+
+</RelativeLayout>
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/ClassForMainDex.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/ClassForMainDex.java
new file mode 100644
index 0000000..8662562
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/ClassForMainDex.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2014 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.framework.multidexlegacyversionedtestapp;
+
+/**
+ * Class directly referenced from Activity, will be kept in main dex. The class is not referenced
+ * by <clinit> or <init>, its direct references are not kept in main dex.
+ */
+public class ClassForMainDex {
+
+    public static int getVersion() {
+        return Version.getVersion();
+    }
+
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/MainActivity.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/MainActivity.java
new file mode 100644
index 0000000..351d860
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/MainActivity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014 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.framework.multidexlegacyversionedtestapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class MainActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+    }
+
+    public int getVersion() {
+        return ClassForMainDex.getVersion();
+    }
+
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.java
new file mode 100644
index 0000000..f130cb2
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2014 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.framework.multidexlegacyversionedtestapp;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+ * Run the tests with: <code>adb shell am instrument -w
+ com.android.framework.multidexlegacyversionedtestapp/android.test.InstrumentationTestRunner
+</code>
+ */
+public class MultiDexUpdateTest extends ActivityInstrumentationTestCase2<MainActivity>
+{
+    public MultiDexUpdateTest() {
+        super(MainActivity.class);
+    }
+
+    /**
+     * Tests that all classes of the application can be loaded. Verifies also that we load the
+     * correct version of {@link Version} ie the class is the secondary dex file.
+     */
+    public void testAllClassAvailable()
+    {
+        assertEquals(2, getActivity().getVersion());
+    }
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/Version.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/Version.java
new file mode 100644
index 0000000..1f2305f
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/src/com/android/framework/multidexlegacyversionedtestapp/Version.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2014 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.framework.multidexlegacyversionedtestapp;
+
+/* can go in secondary dex */
+public class Version {
+
+    public static int getVersion() {
+        return 2;
+    }
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
new file mode 100644
index 0000000..945bfcca
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
@@ -0,0 +1,41 @@
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := 9
+
+LOCAL_PACKAGE_NAME := MultiDexLegacyVersionedTestApp_v3
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex
+
+mainDexList:= \
+	$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
+
+LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
+
+include $(BUILD_PACKAGE)
+
+$(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
+	$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
+	echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@
+
+$(built_dex_intermediate): $(mainDexList)
+
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/AndroidManifest.xml
new file mode 100644
index 0000000..76c92dd
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.framework.multidexlegacyversionedtestapp"
+    android:versionCode="3"
+    android:versionName="3.0" >
+
+    <uses-sdk
+        android:minSdkVersion="9"
+        android:targetSdkVersion="18" />
+
+    <application
+        android:name="android.support.multidex.MultiDexApplication"
+        android:allowBackup="true"
+        android:label="MultiDexLegacyVersionedTestApp_v3">
+        <activity
+            android:name="com.android.framework.multidexlegacyversionedtestapp.MainActivity"
+            android:label="MultiDexLegacyVersionedTestApp_v3" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+                     android:targetPackage="com.android.framework.multidexlegacyversionedtestapp"
+                     android:label="Test for MultiDexLegacyVersionedTestApp_v3" />
+
+</manifest>
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/res/layout/activity_main.xml b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/res/layout/activity_main.xml
new file mode 100644
index 0000000..58ae67a
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/res/layout/activity_main.xml
@@ -0,0 +1,7 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".MainActivity" >
+
+</RelativeLayout>
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/ClassForMainDex.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/ClassForMainDex.java
new file mode 100644
index 0000000..8662562
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/ClassForMainDex.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2014 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.framework.multidexlegacyversionedtestapp;
+
+/**
+ * Class directly referenced from Activity, will be kept in main dex. The class is not referenced
+ * by <clinit> or <init>, its direct references are not kept in main dex.
+ */
+public class ClassForMainDex {
+
+    public static int getVersion() {
+        return Version.getVersion();
+    }
+
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/MainActivity.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/MainActivity.java
new file mode 100644
index 0000000..351d860
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/MainActivity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014 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.framework.multidexlegacyversionedtestapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class MainActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+    }
+
+    public int getVersion() {
+        return ClassForMainDex.getVersion();
+    }
+
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.java
new file mode 100644
index 0000000..67aa478
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2014 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.framework.multidexlegacyversionedtestapp;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+ * Run the tests with: <code>adb shell am instrument -w
+ com.android.framework.multidexlegacyversionedtestapp/android.test.InstrumentationTestRunner
+</code>
+ */
+public class MultiDexUpdateTest extends ActivityInstrumentationTestCase2<MainActivity>
+{
+    public MultiDexUpdateTest() {
+        super(MainActivity.class);
+    }
+
+    /**
+     * Tests that all classes of the application can be loaded. Verifies also that we load the
+     * correct version of {@link Version} ie the class is the secondary dex file.
+     */
+    public void testAllClassAvailable()
+    {
+        assertEquals(3, getActivity().getVersion());
+    }
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/Version.java b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/Version.java
new file mode 100644
index 0000000..1c8ef3b
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/src/com/android/framework/multidexlegacyversionedtestapp/Version.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2014 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.framework.multidexlegacyversionedtestapp;
+
+/* can go in secondary dex */
+public class Version {
+
+    public static int getVersion() {
+        return 3;
+    }
+}
diff --git a/core/tests/inputmethodtests/run_core_inputmethod_test.sh b/core/tests/inputmethodtests/run_core_inputmethod_test.sh
index 5e123ec..b0b119b 100755
--- a/core/tests/inputmethodtests/run_core_inputmethod_test.sh
+++ b/core/tests/inputmethodtests/run_core_inputmethod_test.sh
@@ -21,4 +21,4 @@
   $COMMAND
 fi
 
-adb shell am instrument -w -e class android.os.InputMethodTest com.android.frameworks.coretests.inputmethod/android.test.InstrumentationTestRunner
+adb shell am instrument -w -e class android.os.InputMethodTest,android.os.InputMethodSubtypeArrayTest com.android.frameworks.coretests.inputmethod/android.test.InstrumentationTestRunner
diff --git a/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeArrayTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeArrayTest.java
new file mode 100644
index 0000000..1e0a919
--- /dev/null
+++ b/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeArrayTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.inputmethod.InputMethodSubtype;
+import android.view.inputmethod.InputMethodSubtypeArray;
+import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
+
+import java.util.ArrayList;
+
+public class InputMethodSubtypeArrayTest extends InstrumentationTestCase {
+    @SmallTest
+    public void testInstanciate() throws Exception {
+        final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+        subtypes.add(createDummySubtype(0, "en_US"));
+        subtypes.add(createDummySubtype(1, "en_US"));
+        subtypes.add(createDummySubtype(2, "ja_JP"));
+
+        final InputMethodSubtypeArray array = new InputMethodSubtypeArray(subtypes);
+        assertEquals(subtypes.size(), array.getCount());
+        assertEquals(subtypes.get(0), array.get(0));
+        assertEquals(subtypes.get(1), array.get(1));
+        assertEquals(subtypes.get(2), array.get(2));
+
+        final InputMethodSubtypeArray clonedArray = cloneViaParcel(array);
+        assertEquals(subtypes.size(), clonedArray.getCount());
+        assertEquals(subtypes.get(0), clonedArray.get(0));
+        assertEquals(subtypes.get(1), clonedArray.get(1));
+        assertEquals(subtypes.get(2), clonedArray.get(2));
+
+        final InputMethodSubtypeArray clonedClonedArray = cloneViaParcel(clonedArray);
+        assertEquals(clonedArray.getCount(), clonedClonedArray.getCount());
+        assertEquals(clonedArray.get(0), clonedClonedArray.get(0));
+        assertEquals(clonedArray.get(1), clonedClonedArray.get(1));
+        assertEquals(clonedArray.get(2), clonedClonedArray.get(2));
+    }
+
+    InputMethodSubtypeArray cloneViaParcel(final InputMethodSubtypeArray original) {
+        Parcel parcel = null;
+        try {
+            parcel = Parcel.obtain();
+            original.writeToParcel(parcel);
+            parcel.setDataPosition(0);
+            return new InputMethodSubtypeArray(parcel);
+        } finally {
+            if (parcel != null) {
+                parcel.recycle();
+            }
+        }
+    }
+
+    private static InputMethodSubtype createDummySubtype(final int id, final String locale) {
+        final InputMethodSubtypeBuilder builder = new InputMethodSubtypeBuilder();
+        return builder.setSubtypeNameResId(0)
+                .setSubtypeIconResId(0)
+                .setSubtypeId(id)
+                .setSubtypeLocale(locale)
+                .setIsAsciiCapable(true)
+                .build();
+    }
+}
diff --git a/core/tests/inputmethodtests/src/android/os/InputMethodTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
index 0a2b50c..fa1bd8f 100644
--- a/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
+++ b/core/tests/inputmethodtests/src/android/os/InputMethodTest.java
@@ -34,6 +34,7 @@
     private static final boolean IS_AUX = true;
     private static final boolean IS_DEFAULT = true;
     private static final boolean IS_AUTO = true;
+    private static final ArrayList<InputMethodSubtype> NO_SUBTYPE = null;
 
     @SmallTest
     public void testDefaultEnabledImesWithDefaultVoiceIme() throws Exception {
@@ -45,6 +46,7 @@
         imis.add(createNonDefaultDummyVoiceIme2());
         imis.add(createDefaultDummyEnUSKeyboardIme());
         imis.add(createNonDefaultDummyJaJPKeyboardIme());
+        imis.add(createNonDefaultDummyJaJPKeyboardImeWithoutSubtypes());
         final ArrayList<InputMethodInfo> enabledImis = InputMethodUtils.getDefaultEnabledImes(
                 context, true, imis);
         assertEquals(2, enabledImis.size());
@@ -69,6 +71,7 @@
         imis.add(createNonDefaultDummyVoiceIme2());
         imis.add(createDefaultDummyEnUSKeyboardIme());
         imis.add(createNonDefaultDummyJaJPKeyboardIme());
+        imis.add(createNonDefaultDummyJaJPKeyboardImeWithoutSubtypes());
         final ArrayList<InputMethodInfo> enabledImis = InputMethodUtils.getDefaultEnabledImes(
                 context, true, imis);
         assertEquals(3, enabledImis.size());
@@ -86,6 +89,55 @@
         }
     }
 
+    @SmallTest
+    public void testParcelable() throws Exception {
+        final ArrayList<InputMethodInfo> originalList = new ArrayList<InputMethodInfo>();
+        originalList.add(createNonDefaultAutoDummyVoiceIme0());
+        originalList.add(createNonDefaultAutoDummyVoiceIme1());
+        originalList.add(createNonDefaultDummyVoiceIme2());
+        originalList.add(createDefaultDummyEnUSKeyboardIme());
+        originalList.add(createNonDefaultDummyJaJPKeyboardIme());
+        originalList.add(createNonDefaultDummyJaJPKeyboardImeWithoutSubtypes());
+
+        final List<InputMethodInfo> clonedList = cloneViaParcel(originalList);
+        assertNotNull(clonedList);
+        final List<InputMethodInfo> clonedClonedList = cloneViaParcel(clonedList);
+        assertNotNull(clonedClonedList);
+        assertEquals(originalList, clonedList);
+        assertEquals(clonedList, clonedClonedList);
+        assertEquals(originalList.size(), clonedList.size());
+        assertEquals(clonedList.size(), clonedClonedList.size());
+        for (int imeIndex = 0; imeIndex < originalList.size(); ++imeIndex) {
+            verifyEquality(originalList.get(imeIndex), clonedList.get(imeIndex));
+            verifyEquality(clonedList.get(imeIndex), clonedClonedList.get(imeIndex));
+        }
+    }
+
+    private static List<InputMethodInfo> cloneViaParcel(final List<InputMethodInfo> list) {
+        Parcel p = null;
+        try {
+            p = Parcel.obtain();
+            p.writeTypedList(list);
+            p.setDataPosition(0);
+            return p.createTypedArrayList(InputMethodInfo.CREATOR);
+        } finally {
+            if (p != null) {
+                p.recycle();
+            }
+        }
+    }
+
+    private static void verifyEquality(InputMethodInfo expected, InputMethodInfo actual) {
+        assertEquals(expected, actual);
+        assertEquals(expected.getSubtypeCount(), actual.getSubtypeCount());
+        for (int subtypeIndex = 0; subtypeIndex < expected.getSubtypeCount(); ++subtypeIndex) {
+            final InputMethodSubtype expectedSubtype = expected.getSubtypeAt(subtypeIndex);
+            final InputMethodSubtype actualSubtype = actual.getSubtypeAt(subtypeIndex);
+            assertEquals(expectedSubtype, actualSubtype);
+            assertEquals(expectedSubtype.hashCode(), actualSubtype.hashCode());
+        }
+    }
+
     private static InputMethodInfo createDummyInputMethodInfo(String packageName, String name,
             CharSequence label, boolean isAuxIme, boolean isDefault,
             List<InputMethodSubtype> subtypes) {
@@ -155,4 +207,12 @@
         return createDummyInputMethodInfo("DummyNonDefaultJaJPKeyboardIme", "dummy.keyboard1",
                 "DummyKeyboard1", !IS_AUX, !IS_DEFAULT, subtypes);
     }
+
+    // Although IMEs that have no subtype are considered to be deprecated, the Android framework
+    // must still be able to handle such IMEs as well as IMEs that have at least one subtype.
+    private static InputMethodInfo createNonDefaultDummyJaJPKeyboardImeWithoutSubtypes() {
+        final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+        return createDummyInputMethodInfo("DummyNonDefaultJaJPKeyboardImeWithoutSubtypes",
+                "dummy.keyboard2", "DummyKeyboard2", !IS_AUX, !IS_DEFAULT, NO_SUBTYPE);
+    }
 }
diff --git a/data/fonts/system_fonts.xml b/data/fonts/system_fonts.xml
index 16e4c7c..549f061b 100644
--- a/data/fonts/system_fonts.xml
+++ b/data/fonts/system_fonts.xml
@@ -75,7 +75,6 @@
             <name>baskerville</name>
             <name>goudy</name>
             <name>fantasy</name>
-            <name>cursive</name>
             <name>ITC Stone Serif</name>
         </nameset>
         <fileset>
@@ -108,4 +107,32 @@
         </fileset>
     </family>
 
+    <family>
+        <nameset>
+            <name>casual</name>
+        </nameset>
+        <fileset>
+            <file>ComingSoon.ttf</file>
+        </fileset>
+    </family>
+
+    <family>
+        <nameset>
+            <name>cursive</name>
+        </nameset>
+        <fileset>
+            <file>DancingScript-Regular.ttf</file>
+            <file>DancingScript-Bold.ttf</file>
+        </fileset>
+    </family>
+
+    <family>
+        <nameset>
+            <name>sans-serif-smallcaps</name>
+        </nameset>
+        <fileset>
+            <file>CarroisGothicSC-Regular.ttf</file>
+        </fileset>
+    </family>
+
 </familyset>
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index 2042345..0cdcb1c 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -161,8 +161,8 @@
 key 139   MENU              WAKE_DROPPED
 key 140   CALCULATOR
 # key 141 "KEY_SETUP"
-key 142   POWER             WAKE
-key 143   POWER             WAKE
+key 142   SLEEP             WAKE
+key 143   WAKEUP            WAKE
 # key 144 "KEY_FILE"
 # key 145 "KEY_SENDFILE"
 # key 146 "KEY_DELETEFILE"
diff --git a/data/keyboards/Vendor_18d1_Product_2c40.kl b/data/keyboards/Vendor_18d1_Product_2c40.kl
new file mode 100644
index 0000000..903f13b6
--- /dev/null
+++ b/data/keyboards/Vendor_18d1_Product_2c40.kl
@@ -0,0 +1,42 @@
+# Copyright (C) 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Odie
+
+key 304 BUTTON_A
+key 305 BUTTON_B
+key 307 BUTTON_X
+key 308 BUTTON_Y
+key 310 BUTTON_L1
+key 311 BUTTON_R1
+key 316 BUTTON_MODE
+key 317 BUTTON_THUMBL
+key 318 BUTTON_THUMBR
+
+key 158 BACK            WAKE_DROPPED
+key 172 HOME
+
+axis 0x00 X
+axis 0x01 Y
+axis 0x02 Z
+axis 0x05 RZ
+axis 0x09 RTRIGGER
+axis 0x0a LTRIGGER
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+led 0x00 CONTROLLER_1
+led 0x01 CONTROLLER_2
+led 0x02 CONTROLLER_3
+led 0x03 CONTROLLER_4
diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index bcd4607..6d29c69 100644
--- a/docs/html/about/dashboards/index.jd
+++ b/docs/html/about/dashboards/index.jd
@@ -61,7 +61,7 @@
 </div>
 
 
-<p style="clear:both"><em>Data collected during a 7-day period ending on February 4, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on March 3, 2014.
 <br/>Any versions with less than 0.1% distribution are not shown.</em>
 </p>
 
@@ -92,7 +92,7 @@
 </div>
 
 
-<p style="clear:both"><em>Data collected during a 7-day period ending on February 4, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on March 3, 2014.
 <br/>Any screen configurations with less than 0.1% distribution are not shown.</em></p>
 
 
@@ -133,17 +133,17 @@
 </tr>
 <tr>
 <td>2.0</th>
-<td>92.3%</td>
+<td>91.1%</td>
 </tr>
 <tr>
 <td>3.0</th>
-<td>7.6%</td>
+<td>8.8%</td>
 </tr>
 </table>
 
 
 
-<p style="clear:both"><em>Data collected during a 7-day period ending on February 4, 2014</em></p>
+<p style="clear:both"><em>Data collected during a 7-day period ending on March 3, 2014</em></p>
 
 
 
@@ -161,17 +161,17 @@
 var VERSION_DATA =
 [
   {
-    "chart": "//chart.googleapis.com/chart?cht=p&chs=500x250&chl=Froyo%7CGingerbread%7CHoneycomb%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat&chf=bg%2Cs%2C00000000&chd=t%3A1.3%2C20.0%2C0.1%2C16.1%2C60.7%2C1.8&chco=c4df9b%2C6fad0c",
+    "chart": "//chart.googleapis.com/chart?chl=Froyo%7CGingerbread%7CHoneycomb%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat&chd=t%3A1.2%2C19.0%2C0.1%2C15.2%2C62.0%2C2.5&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&chs=500x250&cht=p",
     "data": [
       {
         "api": 8,
         "name": "Froyo",
-        "perc": "1.3"
+        "perc": "1.2"
       },
       {
         "api": 10,
         "name": "Gingerbread",
-        "perc": "20.0"
+        "perc": "19.0"
       },
       {
         "api": 13,
@@ -181,27 +181,27 @@
       {
         "api": 15,
         "name": "Ice Cream Sandwich",
-        "perc": "16.1"
+        "perc": "15.2"
       },
       {
         "api": 16,
         "name": "Jelly Bean",
-        "perc": "35.5"
+        "perc": "35.3"
       },
       {
         "api": 17,
         "name": "Jelly Bean",
-        "perc": "16.3"
+        "perc": "17.1"
       },
       {
         "api": 18,
         "name": "Jelly Bean",
-        "perc": "8.9"
+        "perc": "9.6"
       },
       {
         "api": 19,
         "name": "KitKat",
-        "perc": "1.8"
+        "perc": "2.5"
       }
     ]
   }
@@ -217,17 +217,17 @@
     "data": {
       "Large": {
         "hdpi": "0.6",
-        "ldpi": "0.8",
-        "mdpi": "4.4",
-        "tvdpi": "1.6",
+        "ldpi": "0.7",
+        "mdpi": "4.3",
+        "tvdpi": "1.5",
         "xhdpi": "0.6"
       },
       "Normal": {
-        "hdpi": "33.3",
-        "ldpi": "0.1",
-        "mdpi": "13.9",
-        "xhdpi": "20.2",
-        "xxhdpi": "11.3"
+        "hdpi": "33.7",
+        "ldpi": "0.2",
+        "mdpi": "13.6",
+        "xhdpi": "19.9",
+        "xxhdpi": "11.9"
       },
       "Small": {
         "ldpi": "8.1"
@@ -235,12 +235,12 @@
       "Xlarge": {
         "hdpi": "0.3",
         "ldpi": "0.1",
-        "mdpi": "4.5",
+        "mdpi": "4.3",
         "xhdpi": "0.2"
       }
     },
-    "densitychart": "//chart.googleapis.com/chart?cht=p&chs=400x250&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chf=bg%2Cs%2C00000000&chd=t%3A9.1%2C22.8%2C1.6%2C34.3%2C21.0%2C11.3&chco=c4df9b%2C6fad0c",
-    "layoutchart": "//chart.googleapis.com/chart?cht=p&chs=400x250&chl=Xlarge%7CLarge%7CNormal%7CSmall&chf=bg%2Cs%2C00000000&chd=t%3A5.1%2C8.0%2C78.9%2C8.1&chco=c4df9b%2C6fad0c"
+    "densitychart": "//chart.googleapis.com/chart?chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chd=t%3A9.1%2C22.2%2C1.5%2C34.6%2C20.7%2C11.9&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&chs=400x250&cht=p",
+    "layoutchart": "//chart.googleapis.com/chart?chl=Xlarge%7CLarge%7CNormal%7CSmall&chd=t%3A4.9%2C7.7%2C79.3%2C8.1&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&chs=400x250&cht=p"
   }
 ];
 
diff --git a/docs/html/distribute/googleplay/promote/badge-files.jd b/docs/html/distribute/googleplay/promote/badge-files.jd
index ede1e21..03ebd01 100644
--- a/docs/html/distribute/googleplay/promote/badge-files.jd
+++ b/docs/html/distribute/googleplay/promote/badge-files.jd
@@ -18,107 +18,112 @@
 
 <div class="col-4" style="margin-left:0">
 
-       <a href="{@docRoot}downloads/brand/en_generic_rgb_wo.ai">English (English)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/english_get.ai">English (English)</a><br/>
+
+       <a href="{@docRoot}downloads/brand/v2/amharic_get.ai">ኣማርኛ (Amharic)</a><br/>
 
        <a href="{@docRoot}downloads/brand/af_generic_rgb_wo.ai">Afrikaans (Afrikaans)</a><br/>
 <!--
        <a href="{@docRoot}downloads/brand/ar_generic_rgb_wo.ai">العربية (Arabic)</a><br/>
 -->
-       <a href="{@docRoot}downloads/brand/be_generic_rgb_wo.ai">Беларуская (Belarusian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/belarusian_get.ai">Беларуская (Belarusian)</a><br/>
        
-       <a href="{@docRoot}downloads/brand/bg_generic_rgb_wo.ai">български (Bulgarian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/bulgarian_get.ai">български (Bulgarian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/ca_generic_rgb_wo.ai">Català (Catalan)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/catalan_get.ai">Català (Catalan)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/zh-cn_generic_rgb_wo.ai">中文 (中国) (Chinese)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/traditional_chinese_get.ai">中文 (中国) (Chinese)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/zh-hk_generic_rgb_wo.ai">中文(香港) (Chinese Hong Kong)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/hongkong_chinese_get.ai">中文(香港) (Chinese Hong Kong)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/zh-tw_generic_rgb_wo.ai">中文 (台灣) (Chinese Taiwan)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/taiwan_chinese_get.ai">中文 (台灣) (Chinese Taiwan)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/hr_generic_rgb_wo.ai">Hrvatski (Croatian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/croatian_get.ai">Hrvatski (Croatian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/cs_generic_rgb_wo.ai">Česky (Czech)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/czech_get.ai">Česky (Czech)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/da_generic_rgb_wo.ai">Dansk (Danish)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/danish_get.ai">Dansk (Danish)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/nl_generic_rgb_wo.ai">Nederlands (Dutch)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/dutch_get.ai">Nederlands (Dutch)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/et_generic_rgb_wo.ai">Eesti keel (Estonian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/estonian_get.ai">Eesti keel (Estonian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/fa_generic_rgb_wo.ai">فارسی (Farsi Persian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/farsi_get.ai">فارسی (Farsi Persian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/fil_generic_rgb_wo.ai">Tagalog (Filipino)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/filipino_get.ai">Tagalog (Filipino)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/fi_generic_rgb_wo.ai">Suomi (Finnish)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/finnish_get.ai">Suomi (Finnish)</a><br/>
 
 </div>
 
 <div class="col-4">
 
-       <a href="{@docRoot}downloads/brand/fr_generic_rgb_wo.ai">Français (French)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/french_get.ai">Français (French)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/de_generic_rgb_wo.ai">Deutsch (German)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/german_get.ai">Deutsch (German)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/el_generic_rgb_wo.ai">Ελληνικά (Greek)</a><br/>
-<!--
-       <a href="{@docRoot}downloads/brand/iw-he_generic_rgb_wo.ai">עברית (Hebrew)</a><br/>
--->
-       <a href="{@docRoot}downloads/brand/hu_generic_rgb_wo.ai">Magyar (Hungarian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/greek_get.ai">Ελληνικά (Greek)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/id-in_generic_rgb_wo.ai">Bahasa Indonesia (Indonesian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/hebrew_get.ai">עברית (Hebrew)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/it_generic_rgb_wo.ai">Italiano (Italian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/hindi_get.ai">हिन्दी (Hindi)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/ja_generic_rgb_wo.ai">日本語 (Japanese)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/hungarian_get.ai">Magyar (Hungarian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/ko_generic_rgb_wo.ai">한국어 (Korean)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/indonesian_get.ai">Bahasa Indonesia (Indonesian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/lv_generic_rgb_wo.ai">Latviski (Latvian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/italian_get.ai">Italiano (Italian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/lt_generic_rgb_wo.ai">Lietuviškai (Lithuanian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/japanese_get.ai">日本語 (Japanese)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/ms_generic_rgb_wo.ai">Bahasa Melayu (Malay)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/kazakh_get.ai">Қазақ тілі (Kazakh)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/no_generic_rgb_wo.ai">Norsk (Norwegian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/korean_get.ai">한국어 (Korean)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/pl_generic_rgb_wo.ai">Polski (Polish)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/latvian_get.ai">Latviski (Latvian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/pt-pt_generic_rgb_wo.ai">Português (Portuguese)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/lithuanian_get.ai">Lietuviškai (Lithuanian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/pt-br_generic_rgb_wo.ai">Português Brasil (Portuguese Brazil)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/malay_get.ai">Bahasa Melayu (Malay)</a><br/>
+
+       <a href="{@docRoot}downloads/brand/v2/norwegian_get.ai">Norsk (Norwegian)</a><br/>
+
+       <a href="{@docRoot}downloads/brand/v2/polish_get.ai">Polski (Polish)</a><br/>
 
 </div>
 
 <div class="col-4" style="margin-right:0">
 
-       <a href="{@docRoot}downloads/brand/ro_generic_rgb_wo.ai">Românã (Romanian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/portugal_portuguese_get.ai">Português (Portuguese)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/ru_generic_rgb_wo.ai">Pусский (Russian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/brazilian_portuguese_get.ai">Português Brasil (Portuguese Brazil)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/sr_generic_rgb_wo.ai">Српски / srpski (Serbian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/romanian_get.ai">Românã (Romanian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/sk_generic_rgb_wo.ai">Slovenčina (Slovak)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/russian_get.ai">Pусский (Russian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/sl_generic_rgb_wo.ai">Slovenščina (Slovenian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/serbian_get.ai">Српски / srpski (Serbian)</a><br/>
+
+       <a href="{@docRoot}downloads/brand/v2/slovak_get.ai">Slovenčina (Slovak)</a><br/>
+
+       <a href="{@docRoot}downloads/brand/v2/slovenian_get.ai">Slovenščina (Slovenian)</a><br/>
        
-       <a href="{@docRoot}downloads/brand/es_generic_rgb_wo.ai">Español (Spanish)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/spanish_get.ai">Español (Spanish)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/es-419_generic_rgb_wo.ai">Español Latinoamérica (Spanish Latin America)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/spanish_latam_get.ai">Español Latinoamérica (Spanish Latin America)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/sv_generic_rgb_wo.ai">Svenska (Swedish)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/swahili_get.ai">Kiswahili (Swahili)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/sw_generic_rgb_wo.ai">Kiswahili (Swahili)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/swedish_get.ai">Svenska (Swedish)</a><br/>
        
-       <a href="{@docRoot}downloads/brand/th_generic_rgb_wo.ai">ภาษาไทย (Thai)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/thai_get.ai">ภาษาไทย (Thai)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/tr_generic_rgb_wo.ai">Türkçe (Turkish)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/turkish_get.ai">Türkçe (Turkish)</a><br/>
 
        <a href="{@docRoot}downloads/brand/uk_generic_rgb_wo.ai">Українська (Ukrainian)</a><br/>
-
        <a href="{@docRoot}downloads/brand/vi_generic_rgb_wo.ai">Tiếng Việt (Vietnamese)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/zu_generic_rgb_wo.ai">isiZulu (Zulu)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/zulu_get.ai">isiZulu (Zulu)</a><br/>
 
 </div>
 <div style="clear:left">&nbsp;</div>
@@ -128,126 +133,122 @@
 
 
 
+
+
+
 <hr>
 <img src="{@docRoot}images/brand/en_app_rgb_wo_60.png" alt="Android App On Google Play">
 
 <div style="clear:left">&nbsp;</div>
 
-<div class="col-8" style="margin-left:0">
+<div class="col-4" style="margin-left:0">
 
-       <a href="{@docRoot}downloads/brand/en_app_rgb_wo.ai">English (English)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/english_app.ai">English (English)</a><br/>
+      
+       <a href="{@docRoot}downloads/brand/v2/afrikaans_app.ai">Afrikaans (Afrikaans)</a><br/>
+
+       <a href="{@docRoot}downloads/brand/v2/amharic_app.ai">ኣማርኛ (Amharic)</a><br/>
+
+       <a href="{@docRoot}downloads/brand/v2/arabic_app.ai">العربية (Arabic)</a><br/>
+
+       <a href="{@docRoot}downloads/brand/v2/belarusian_app.ai">Беларуская (Belarusian)</a><br/>
        
-<!--
-       <a href="{@docRoot}downloads/brand/af_app_rgb_wo.ai">Afrikaans (Afrikaans)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/bulgarian_app.ai">български (Bulgarian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/ar_app_rgb_wo.ai">العربية (Arabic)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/catalan_app.ai">Català (Catalan)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/be_app_rgb_wo.ai">Беларуская (Belarusian)</a><br/>
-       
-       <a href="{@docRoot}downloads/brand/bg_app_rgb_wo.ai">български (Bulgarian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/traditional_chinese_app.ai">中文 (中国) (Chinese)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/ca_app_rgb_wo.ai">Català (Catalan)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/hongkong_chinese_app.ai">中文(香港) (Chinese Hong Kong)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/zh-cn_app_rgb_wo.ai">中文 (中国) (Chinese)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/taiwan_chinese_app.ai">中文 (台灣) (Chinese Taiwan)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/zh-hk_app_rgb_wo.ai">中文(香港) (Chinese Hong Kong)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/croatian_app.ai">Hrvatski (Croatian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/zh-tw_app_rgb_wo.ai">中文 (台灣) (Chinese Taiwan)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/czech_app.ai">Česky (Czech)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/hr_app_rgb_wo.ai">Hrvatski (Croatian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/danish_app.ai">Dansk (Danish)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/cs_app_rgb_wo.ai">Česky (Czech)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/dutch_app.ai">Nederlands (Dutch)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/da_app_rgb_wo.ai">Dansk (Danish)</a><br/>
--->
+       <a href="{@docRoot}downloads/brand/v2/estonian_app.ai">Eesti keel (Estonian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/nl_app_rgb_wo.ai">Nederlands (Dutch)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/farsi_app.ai">فارسی (Farsi Persian)</a><br/>
 
-<!--
-       <a href="{@docRoot}downloads/brand/et_app_rgb_wo.ai">Eesti keel (Estonian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/filipino_app.ai">Tagalog (Filipino)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/fa_app_rgb_wo.ai">فارسی (Farsi Persian)</a><br/>
-
-       <a href="{@docRoot}downloads/brand/fil_app_rgb_wo.ai">Tagalog (Filipino)</a><br/>
-
-       <a href="{@docRoot}downloads/brand/fi_app_rgb_wo.ai">Suomi (Finnish)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/finnish_app.ai">Suomi (Finnish)</a><br/>
 
 </div>
 
 <div class="col-4">
--->
 
-       <a href="{@docRoot}downloads/brand/fr_app_rgb_wo.ai">Français (French)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/french_app.ai">Français (French)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/de_app_rgb_wo.ai">Deutsch (German)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/german_app.ai">Deutsch (German)</a><br/>
 
-<!--
-       <a href="{@docRoot}downloads/brand/el_app_rgb_wo.ai">Ελληνικά (Greek)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/greek_app.ai">Ελληνικά (Greek)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/iw-he_app_rgb_wo.ai">עברית (Hebrew)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/hebrew_app.ai">עברית (Hebrew)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/hu_app_rgb_wo.ai">Magyar (Hungarian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/hindi_app.ai">हिन्दी (Hindi)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/id-in_app_rgb_wo.ai">Bahasa Indonesia (Indonesian)</a><br/>
--->
+       <a href="{@docRoot}downloads/brand/v2/hungarian_app.ai">Magyar (Hungarian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/it_app_rgb_wo.ai">Italiano (Italian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/indonesian_app.ai">Bahasa Indonesia (Indonesian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/ja_app_rgb_wo.ai">日本語 (Japanese)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/italian_app.ai">Italiano (Italian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/ko_app_rgb_wo.ai">한국어 (Korean)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/japanese_app.ai">日本語 (Japanese)</a><br/>
 
-<!--
-       <a href="{@docRoot}downloads/brand/lv_app_rgb_wo.ai">Latviski (Latvian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/korean_app.ai">한국어 (Korean)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/lt_app_rgb_wo.ai">Lietuviškai (Lithuanian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/latvian_app.ai">Latviski (Latvian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/ms_app_rgb_wo.ai">Bahasa Melayu (Malay)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/lithuanian_app.ai">Lietuviškai (Lithuanian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/no_app_rgb_wo.ai">Norsk (Norwegian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/malay_app.ai">Bahasa Melayu (Malay)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/pl_app_rgb_wo.ai">Polski (Polish)</a><br/>
--->
+       <a href="{@docRoot}downloads/brand/v2/norwegian_app.ai">Norsk (Norwegian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/pt-pt_app_rgb_wo.ai">Português (Portuguese)</a><br/>
-
-       <a href="{@docRoot}downloads/brand/pt-br_app_rgb_wo.ai">Português Brasil (Portuguese Brazil)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/polish_app.ai">Polski (Polish)</a><br/>
 
 
-<!--
 </div>
 
 <div class="col-4" style="margin-right:0">
-       <a href="{@docRoot}downloads/brand/ro_app_rgb_wo.ai">Românã (Romanian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/ru_app_rgb_wo.ai">Pусский (Russian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/portugal_portuguese_app.ai">Português (Portuguese)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/sr_app_rgb_wo.ai">Српски / srpski (Serbian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/brazilian_portuguese_app.ai">Português Brasil (Portuguese Brazil)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/sk_app_rgb_wo.ai">Slovenčina (Slovak)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/romanian_app.ai">Românã (Romanian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/sl_app_rgb_wo.ai">Slovenščina (Slovenian)</a><br/>
--->
+       <a href="{@docRoot}downloads/brand/v2/russian_app.ai">Pусский (Russian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/es_app_rgb_wo.ai">Español (Spanish)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/serbian_app.ai">Српски / srpski (Serbian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/es-419_app_rgb_wo.ai">Español Latinoamérica (Spanish Latin America)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/slovak_app.ai">Slovenčina (Slovak)</a><br/>
 
-<!--
-       <a href="{@docRoot}downloads/brand/sv_app_rgb_wo.ai">Svenska (Swedish)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/slovenian_app.ai">Slovenščina (Slovenian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/sw_app_rgb_wo.ai">Kiswahili (Swahili)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/spanish_app.ai">Español (Spanish)</a><br/>
+
+       <a href="{@docRoot}downloads/brand/v2/spanish_latam_app.ai">Español Latinoamérica (Spanish Latin America)</a><br/>
+
+       <a href="{@docRoot}downloads/brand/v2/swahili_app.ai">Kiswahili (Swahili)</a><br/>
+
+       <a href="{@docRoot}downloads/brand/v2/swedish_app.ai">Svenska (Swedish)</a><br/>
        
-       <a href="{@docRoot}downloads/brand/th_app_rgb_wo.ai">ภาษาไทย (Thai)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/thai_app.ai">ภาษาไทย (Thai)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/tr_app_rgb_wo.ai">Türkçe (Turkish)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/turkish_app.ai">Türkçe (Turkish)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/uk_app_rgb_wo.ai">Українська (Ukrainian)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/ukranian_app.ai">Українська (Ukrainian)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/vi_app_rgb_wo.ai">Tiếng Việt (Vietnamese)</a><br/>
+       <a href="{@docRoot}downloads/brand/v2/vietnamese_app.ai">Tiếng Việt (Vietnamese)</a><br/>
 
-       <a href="{@docRoot}downloads/brand/zu_app_rgb_wo.ai">isiZulu (Zulu)</a><br/>
--->
+       <a href="{@docRoot}downloads/brand/v2/zulu_app.ai">isiZulu (Zulu)</a><br/>
 
 </div>
 <div style="clear:left">&nbsp;</div>
diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd
index bd1edc2..b648d48 100644
--- a/docs/html/guide/topics/manifest/activity-element.jd
+++ b/docs/html/guide/topics/manifest/activity-element.jd
@@ -580,7 +580,7 @@
   <a href="#nm"><code>android:name</code></a> attribute.
 
 <p>The system reads this attribute to determine which activity should be started when
-  the use presses the Up button in the action bar. The system can also use this information to
+  the user presses the Up button in the action bar. The system can also use this information to
   synthesize a back stack of activities with {@link android.app.TaskStackBuilder}.</p>
 
 <p>To support API levels 4 - 16, you can also declare the parent activity with a {@code
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index bc22416..bc793f1 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -27,21 +27,21 @@
 
 
 
-sdk.linux_download=android-sdk_r22.3-linux.tgz
-sdk.linux_bytes=100968558
-sdk.linux_checksum=6ae581a906d6420ad67176dff25a31cc
+sdk.linux_download=android-sdk_r22.6-linux.tgz
+sdk.linux_bytes=100992666
+sdk.linux_checksum=dde27b72715e52693c1ebc908742fc40
 
-sdk.mac_download=android-sdk_r22.3-macosx.zip
-sdk.mac_bytes=74893875
-sdk.mac_checksum=ecde88ca1f05955826697848fcb4a9e7
+sdk.mac_download=android-sdk_r22.6-macosx.zip
+sdk.mac_bytes=74547402
+sdk.mac_checksum=10c0e2ab65444c4911d69356ca2343f5
 
-sdk.win_download=android-sdk_r22.3-windows.zip
-sdk.win_bytes=108847452
-sdk.win_checksum=9f0fe8c8884d6aee2b298fee203c62dc
+sdk.win_download=android-sdk_r22.6-windows.zip
+sdk.win_bytes=108862292
+sdk.win_checksum=6faa487d328be352a456c53d9cbf0e3d
 
-sdk.win_installer=installer_r22.3-windows.exe
-sdk.win_installer_bytes=88845794
-sdk.win_installer_checksum=ad50c4dd9e23cee65a1ed740ff3345fa
+sdk.win_installer=installer_r22.6-windows.exe
+sdk.win_installer_bytes=88856450
+sdk.win_installer_checksum=6e5351b414bd554f3ac4c79f9dd4d213
 
 
 
@@ -363,8 +363,8 @@
 <div class="col-6 reqs" style="margin:0 0 15px 20px;display:none;">
 <h5>Eclipse IDE</h5>
     <ul>
-      <li><a href="http://eclipse.org/mobile/">Eclipse</a> 3.6.2 (Helios) or greater
-<p class="note"><strong>Note:</strong> Eclipse 3.5 (Galileo) is no longer
+      <li><a href="http://eclipse.org/mobile/">Eclipse</a> 3.7.2 (Indigo) or greater
+<p class="note"><strong>Note:</strong> Eclipse 3.6 (Helios) is no longer
 supported with the latest version of ADT.</p></li>
       <li>Eclipse <a href="http://www.eclipse.org/jdt">JDT</a> plugin (included
 in most Eclipse IDE packages) </li>
diff --git a/docs/html/sdk/installing/installing-adt.jd b/docs/html/sdk/installing/installing-adt.jd
index 66c3034..42cb92c 100644
--- a/docs/html/sdk/installing/installing-adt.jd
+++ b/docs/html/sdk/installing/installing-adt.jd
@@ -1,8 +1,8 @@
 page.title=Installing the Eclipse Plugin
-adt.zip.version=22.3.0
-adt.zip.download=ADT-22.3.0.zip
-adt.zip.bytes=14493723
-adt.zip.checksum=0189080b23dfa0f866adafaaafcc34ab
+adt.zip.version=22.6.0
+adt.zip.download=ADT-22.6.0.zip
+adt.zip.bytes=14585211
+adt.zip.checksum=d95c6d8e678881f6c89f063b58d4162f
 
 @jd:body
 
diff --git a/docs/html/tools/help/avd-manager.jd b/docs/html/tools/help/avd-manager.jd
index ed90f43..20f6253 100644
--- a/docs/html/tools/help/avd-manager.jd
+++ b/docs/html/tools/help/avd-manager.jd
@@ -8,8 +8,11 @@
 
 <p>You can launch the AVD Manager in one of the following ways:</p>
 <ul>
-  <li>In Eclipse: select <strong>Window &gt; AVD Manager</strong>, or click
-  the AVD Manager icon in the Eclipse toolbar.</li>
+  <li>In Eclipse: select <strong>Window &gt; Android Virtual Device Manager</strong>, or click
+  the AVD Manager icon in the toolbar.</li>
+
+  <li>In Android Studio: select <strong>Tools &gt; Android &gt; AVD Manager</strong>, or click
+  the AVD Manager icon in the toolbar.</li>
 
   <li>In other IDEs: Navigate to your SDK's <code>tools/</code> directory and execute
   <code>android avd</code>.</li>
diff --git a/docs/html/tools/help/sdk-manager.jd b/docs/html/tools/help/sdk-manager.jd
index 276206f..57271bb 100644
--- a/docs/html/tools/help/sdk-manager.jd
+++ b/docs/html/tools/help/sdk-manager.jd
@@ -9,6 +9,8 @@
 <ul>
   <li>From Eclipse (with <a href="{@docRoot}tools/help/adt.html">ADT</a>),
   select <strong>Window</strong> &gt; <strong>Android SDK Manager</strong>.</li>
+  <li>From Android Studio, select <strong>Tools</strong> &gt; <strong>Android</strong>
+  &gt; <strong>SDK Manager</strong>.</li>
   <li>On Windows, double-click the <code>SDK Manager.exe</code> file at the root of the Android
 SDK directory.</li>
   <li>On Mac or Linux, open a terminal and navigate to the <code>tools/</code> directory in the
diff --git a/docs/html/tools/revisions/build-tools.jd b/docs/html/tools/revisions/build-tools.jd
index 749808f..c3c83ef 100644
--- a/docs/html/tools/revisions/build-tools.jd
+++ b/docs/html/tools/revisions/build-tools.jd
@@ -77,6 +77,18 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>Build Tools, Revision 19.0.3</a> <em>(March 2014)</em>
+  </p>
+  <div class="toggle-content-toggleme">
+
+    <p>Fixed an issue with RenderScript support.</p>
+
+  </div>
+</div>
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>Build Tools, Revision 19.0.2</a> <em>(February 2014)</em>
   </p>
   <div class="toggle-content-toggleme">
diff --git a/docs/html/tools/sdk/eclipse-adt.jd b/docs/html/tools/sdk/eclipse-adt.jd
index c584ae5..d711e44 100644
--- a/docs/html/tools/sdk/eclipse-adt.jd
+++ b/docs/html/tools/sdk/eclipse-adt.jd
@@ -53,10 +53,73 @@
 <p>For a summary of all known issues in ADT, see <a
 href="http://tools.android.com/knownissues">http://tools.android.com/knownissues</a>.</p>
 
-
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>ADT 22.6.0</a> <em>(March 2014)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+<dl>
+  <dt>Dependencies:</dt>
+
+  <dd>
+    <ul>
+      <li>Java 1.6 or higher is required.</li>
+      <li>Eclipse Indigo (Version 3.7.2) or higher is required.</li>
+      <li>This version of ADT is designed for use with
+        <a href="{@docRoot}tools/sdk/tools-notes.html">SDK Tools r22.6</a>.
+        If you haven't already installed SDK Tools r22.6 into your SDK, use the
+        Android SDK Manager to do so.</li>
+    </ul>
+  </dd>
+
+  <dt>General Notes:</dt>
+  <dd>
+    <ul>
+      <li><p>Added support for Java 7 language features like multi-catch, try-with-resources,
+            and the diamond operator. These features require version 19 or higher
+            of the Build Tools. Try-with-resources requires <code>minSdkVersion</code>
+            19; the rest of the new language features require
+            <code>minSdkVersion</code> 8 or higher.</p>
+          <p>To use the new language features after installing ADT 22.6.0, ensure
+            that you run Eclipse on JDK 7 and change your application project settings
+            to use JDK 7.</p>
+      </li>
+      <li>Added new lint checks:
+        <ul>
+          <li>Security:
+            <ul>
+              <li>Look for code potentially affected by a <code>SecureRandom</code>
+                  vulnerability.</li>
+              <li>Check that calls to <code>checkPermission</code> use the return
+                  value.</li>
+            </ul>
+          </li>
+          <li>Check that production builds do not use mock location providers.</li>
+        </ul>
+      </li>
+      <li>Updated the New Project templates to include the
+          <a href="{@docRoot}tools/support-library/features.html#v7-appcompat">
+          v7 appcompat Support Library</a>.</li>
+      <li>Updated the Android tools libraries to include the rendering sandbox,
+          improvements for converting resource XML string declarations to layout
+          strings, and other updates.</li>
+      <li>Improved the Gradle export wizard. Note that the new importer in Android
+          Studio is the preferred way to migrate existing projects to Gradle.</li>
+      <li>Fixed a deadlock during startup.</li>
+      <li>Fixed an issue with RenderScript support. Using RenderScript support mode
+          now requires version 19.0.3 of the Build Tools.</li>
+    </ul>
+  </dd>
+
+</dl>
+</div>
+</div>
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
       alt=""/>ADT 22.3.0</a> <em>(October 2013)</em>
   </p>
 
diff --git a/docs/html/tools/sdk/ndk/index.jd b/docs/html/tools/sdk/ndk/index.jd
index 4e50d98..a22dc90 100644
--- a/docs/html/tools/sdk/ndk/index.jd
+++ b/docs/html/tools/sdk/ndk/index.jd
@@ -2,33 +2,33 @@
 page.template=sdk
 
 
-ndk.mac64_download=android-ndk-r9c-darwin-x86_64.tar.bz2
-ndk.mac64_bytes=358350393
-ndk.mac64_checksum=154bc0248671b8609037218d3faa47f5
+ndk.mac64_download=android-ndk-r9d-darwin-x86_64.tar.bz2
+ndk.mac64_bytes=400339614
+ndk.mac64_checksum=c914164b1231c574dbe40debef7048be
 
-ndk.mac32_download=android-ndk-r9c-darwin-x86.tar.bz2
-ndk.mac32_bytes=352900444
-ndk.mac32_checksum=0ba391eb12d4eed6bd7dbff5d8804e0f
+ndk.mac32_download=android-ndk-r9d-darwin-x86.tar.bz2
+ndk.mac32_bytes=393866116
+ndk.mac32_checksum=ee6544bd8093c79ea08c2e3a6ffe3573
 
-ndk.linux64_download=android-ndk-r9c-linux-x86_64.tar.bz2
-ndk.linux64_bytes=371254928
-ndk.linux64_checksum=e9c3fd9881c811753bb57f701b3e05b1
+ndk.linux64_download=android-ndk-r9d-linux-x86_64.tar.bz2
+ndk.linux64_bytes=412879983
+ndk.linux64_checksum=c7c775ab3342965408d20fd18e71aa45
 
-ndk.linux32_download=android-ndk-r9c-linux-x86.tar.bz2
-ndk.linux32_bytes=365412557
-ndk.linux32_checksum=93d2aa9a40501b568037642cdb174643
+ndk.linux32_download=android-ndk-r9d-linux-x86.tar.bz2
+ndk.linux32_bytes=405218267
+ndk.linux32_checksum=6c1d7d99f55f0c17ecbcf81ba0eb201f
 
-ndk.win64_download=android-ndk-r9c-windows-x86_64.zip
-ndk.win64_bytes=483804820
-ndk.win64_checksum=9e84d0d59ce7d4a24370b619fb8799e4
+ndk.win64_download=android-ndk-r9d-windows-x86_64.zip
+ndk.win64_bytes=520997454
+ndk.win64_checksum=8cd244fc799d0e6e59d65a59a8692588
 
-ndk.win32_download=android-ndk-r9c-windows-x86.zip
-ndk.win32_bytes=460676475
-ndk.win32_checksum=863b5ab371b63c3e9bf0d39e47903763
+ndk.win32_download=android-ndk-r9d-windows-x86.zip
+ndk.win32_bytes=491440074
+ndk.win32_checksum=b16516b611841a075685a10c59d6d7a2
 
-ndk.debug_info_download=android-ndk-r9c-cxx-stl-libs-with-debugging-info.zip
-ndk.debug_info_bytes=100364569
-ndk.debug_info_checksum=37911716e1fd2fe3abb8a410750d73e6
+ndk.debug_info_download=android-ndk-r9d-cxx-stl-libs-with-debug-info.zip
+ndk.debug_info_bytes=104947363
+ndk.debug_info_checksum=906c8d88e0f02295c3bfe6b8e98a1a35
 
 
 page.title=Android NDK
@@ -272,19 +272,84 @@
  <p>
    <a href="#" onclick="return toggleContent(this)"> <img
      src="/assets/images/triangle-opened.png" class="toggle-content-img" alt=""
-   >Android NDK, Revision 9c</a> <em>(December 2013)</em>
+   >Android NDK, Revision 9d</a> <em>(March 2014)</em>
  </p>
  <div class="toggle-content-toggleme">
-<p>This is a bug-fix-only release.</p>
+    <dl>
+      <dt>Important changes:</dt>
+      <dd>
+      <ul>
+        <li>Added support for the Clang 3.4 compiler. The
+<code>NDK_TOOLCHAIN_VERSION=clang</code> option now picks Clang 3.4. GCC 4.6 is
+still the default compiler.</li>
+        <li>Added <code>APP_ABI=armeabi-v7a-hard</code>, with
+additional multilib option <code>-mfloat-abi=hard</code>. These options are for
+use with ARM GCC 4.6/4.8 and clang 3.3/3.4 (which use 4.8's assembler, linker,
+and libs). When using these options, note the following changes:</li>
+        <ul>
+           <li> When executing the <code>ndk-build</code> script, add the
+following options for armeabi-v7a target:
+<pre>TARGET_CFLAGS += -mhard-float -D_NDK_MATH_NO_SOFTFP=1
+TARGET_LDFLAGS += -Wl,--no-warn-mismatch -lm_hard</pre>
+The built library is copied to <code>libs/armeabi-v7a</code>. For make to
+behave as expected, you cannot specify both <code>armeabi-v7a</code> and
+<code>armeabi-v7a-hard</code> as make targets (i.e., on the APP_ABI= line).
+Doing so causes one of them to be ignored. Note that <code>APP_ABI=all</code>
+is still equivalent to
+<code>armeabi armeabi-v7a x86 mips</code>.</li>
+           <li>The <code>make-standalone-toolchain.sh</code> script copies
+additional libaries under <code>/hard</code> directories.
+      Add the above <code>CFLAGS</code> and <code>LFLAGS</code> to your
+makefile to enable GCC or Clang to link with
+      libraries in <code>/hard</code>.</li>
+        </ul>
+        <li>Added the yasm assembler, as well as <code>LOCAL_ASMFLAGS</code>
+and <code>EXPORT_ASMFLAGS</code> flags for x86
+targets. The <code>ndk-build</code> script uses
+<code>prebuilts/*/bin/yasm*</code> to build <code>LOCAL_SRC_FILES</code> that
+have the <code>.asm</code> extension.</li>
+        <li>Updated MClinker to 2.6.0, which adds <code>-gc-sections</code>
+support.</li>
+        <li>Added experimental libc++ support (upstream r201101).  Use this new
+feature by following these steps:
+        <ul>
+           <li>Add <code>APP_STL := c++_static</code> or <code>APP_STL :=
+c++_shared</code> in <code>Application.mk</code>.
+      You may rebuild from source via <code>LIBCXX_FORCE_REBUILD :=
+true</code></li>
+           <li>Execute <code>make-standalone-toolchain.sh --stl=libc++</code>
+to create a standalone toolchain with libc++ headers/lib.</li>
+        </ul>
+        For more information, see
+<code>CPLUSPLUS-SUPPORT.html</code>.
+(Issue <a href="b.android.com/36496">36496</a>)</li>
+      </ul>
+      </dd>
    <dl>
      <dt>Important bug fixes:</dt>
      <dd>
      <ul>
-       <li>Fixed a problem with GCC 4.8 ARM, in which the stack pointer is restored too early. This problem prevented the frame pointer from reliably accessing a variable in the stack frame. For more information, see <a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58854">http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58854</a>.</li>
-<li>- Fixed a problem with GCC 4.8 libstdc++, in which a bug in std::nth_element was causing generation of code that produced a random segfault. For more information, see <a href="https://code.google.com/p/android/issues/detail?id=62910">https://code.google.com/p/android/issues/detail?id=62910</a>.</li>
-           <li>Fixed GCC 4.8 ICE in cc1/cc1plus with <code>-fuse-ld=mcld</code>, so that the following error no longer occurs:
-<pre>cc1: internal compiler error: in common_handle_option, at opts.c:1774</pre></li>
-           <li>Fixed <code>-mhard-float</code> support for <code>__builtin</code> math functions. For ongoing information on fixes for -mhard-float with STL, please follow <a href="http://b.android.com/61784">http://b.android.com/61784</a>.</li>
+       <li>Fixed an uncaught throw from an unexpected
+exception handler for GCC 4.6/4.8 ARM EABI. (GCC Issue <a
+href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59392">59392</a>)</li>
+       <li>Fixed GCC 4.8 so that it now correctly resolves partial
+specialization of a template with
+  a dependent, non-type template argument. (GCC Issue <a
+href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59052">59052</a>)</li>
+       <li>Added more modules to prebuilt python (Issue <a
+href="b.android.com/59902">59902</a>):
+               <ul>
+                 <li>Mac OS X: <code>zlib</code>, <code>bz2</code>,
+<code>_curses</code>, <code>_curses_panel</code>, <code>_hashlib</code>,
+<code>_ssl</code></li>
+                 <li>Linux: <code>zlib</code>, <code>nis</code>,
+<code>crypt</code>, <code>_curses</code>, and <code>_curses_panel</code></li>
+               </ul>
+       <li>Fixed the x86 and MIPS gdbserver
+<code>event_getmsg_helper</code>.</li>
+       <li>Fixed numerous issues in the RenderScript NDK toolchain, including
+issues with compatibility across older devices and C++ reflection.</li>
+<br>
      </ul>
      </dd>
 
@@ -293,33 +358,187 @@
      <ul>
        <li>Header fixes:
          <ul>
-           <li>Changed prototype of <code>poll</code> to <code>poll(struct pollfd *, nfds_t, int);</code> in <code>poll.h</code>.</li>
-           <li>Added <code>utimensat</code> to <code>libc.so</code> in API levels 12 and 19. It is now present in levels 12-19.</li>
-<li>Introduced <code>futimens</code> into <code>libc.so</code>, as of API level 19.</li>
-<li>Added missing <code>clock_settime()</code> and <code>clock_nanosleep()</code> to <code>time.h</code> for API 8 and higher.</li>
-<li>Added <code>CLOCK_MONOTONIC_RAW, CLOCK_REALTIME_COARSE, CLOCK_MONOTONIC_COARSE, CLOCK_BOOTTIME, CLOCK_REALTIME_ALARM,</code> and <code>CLOCK_BOOTTIME_ALARM</code> in <code>time.h.</code></li>
-<li>Removed obsolete <code>CLOCK_REALTIME_HR</code> and <code>CLOCK_MONOTONIC_HR.</code></li>
+           <li>Fixed a missing <code>#include &lt;sys/types.h&gt;</code> in
+<code>android/asset_manager.h</code> for Android API level 13 and higher.
+     (Issue <a href="http://b.android.com/64988">64988</a>)</li>
+           <li>Fixed a missing <code>#include <stdint.h></code> in
+<code>android/rect_manager.h</code> for Android API level 14 and higher.</li>
+           <li>Added <code>JNICALL</code> to <code>JNI_OnLoad</code> and
+<code>JNI_OnUnload</code> in <code>jni.h</code>. Note that <code>JNICALL</code>
+ is defined as <code>__NDK_FPABI__</code> For more information, see
+<code>sys/cdefs.h</code>.</li>
+           <li>Updated the following headers so that they can be included
+without the need to
+manually include their dependencies (Issue <a
+href="http://b.android.com/64679">64679</a>):</li>
+<pre>
+android/tts.h
+EGL/eglext.h
+fts.h
+GLES/glext.h
+GLES2/gl2ext.h
+OMXAL/OpenMAXSL_Android.h
+SLES/OpenSLES_Android.h
+sys/prctl.h
+sys/utime.h
+</pre>
+           <li>Added <code>sys/cachectl.h</code> for all architectures. MIPS
+developers can now include this header instead of writing <code>#ifdef
+__mips__</code>.</li>
+           <li></code>Fixed <code>platforms/android-18/include/android/input.h
+</code> by adding <code>__NDK_FPABI__</code> to functions taking or returning
+float or double values.</li>
+           <li>Fixed MIPS <code>struct stat</code>, which was incorrectly set
+to its 64-bit counterpart for Android API level 12 and later. This wrong
+setting was a
+regression introduced in release r9c.</li>
+           <li>Defined <code>__PTHREAD_MUTEX_INIT_VALUE</code>,
+<code>__PTHREAD_RECURSIVE_MUTEX_INIT_VALUE</code>,
+     and <code>__PTHREAD_ERRORCHECK_MUTEX_INIT_VALUE</code> for Android API
+level 9 and lower.</li>
+           <li>Added <code>scalbln</code>, <code>scalblnf</code>, and
+<code>scalblnl</code> to x86 <code>libm.so</code> for APIs 18 and later.</li>
+           <li>Fixed a typo in
+<code>sources/android/support/include/iconv.h</code>.
+     (Issue <a href="http://b.android.com/63806">63806</a>)</li>
+
          </ul>
        </li>
-       <li>Refactored samples Teapot, MoreTeapots, and <code>source/android/ndk_helper</code> as follows:
+       <li>Fixed gabi++ <code>std::unexpected()</code> to call
+<code>std::terminate()</code> so that
+  a user-defined <code>std::terminate()</code> handler has a chance to run.
+</li>
+       <li>Fixed gabi++ to catch <code>std::nullptr</code>.</li>
+       <li>Fixed samples Teapot and MoreTeapots:
          <ul>
-<li>They now use a hard-float abi for armeabi-v7a.</li>
-<li>Android-19 now has immersive mode.</li>
-<li>Fixed a problem with <code>Check_ReleaseStringUTFChars</code> in <code>/system/lib/libdvm.so</code> that was causing crashes on x86 devices.</li>
+      <li>Solved a problem with Tegra 2 and 3 chips by changing specular
+variables to use medium precision. Values for specular power can now be less
+than 1.0. </li>
+      <li>Changed the samples so that pressing the volume button restores
+immersive mode and invalidates
+<code>SYSTEM_UI_FLAG_IMMERSIVE_STICKY</code>. Screen rotation does not
+trigger <code>onSystemUiVisibilityChange</code>, and so does not restore
+immersive mode.</li>
          </ul>
         </li>
-<li>Fixed ndk-build fails that happen in cygwin when the NDK package is referenced via symlink.</li>
-<li>Fixed ndk-build.cmd fails that happen in windows <code>cmd.exe</code> when <code>LOCAL_SRC_FILES</code> contains absolute paths. See <a href="https://android-review.googlesource.com/#/c/69992">https://android-review.googlesource.com/#/c/69992.</a></li>
-<li>Fixed ndk-stack to proceed even when it can't parse a frame due to inability to find a routine, filename, or line number. In any of those cases, it prints "??".</li>
-<li>Fixed ndk-stack windows-x64_64 so that it no longer erroneously matches a frame line with a line in the <code>stack:</code>
-  section that doesn't contain <code>pc</code>, <code>eip</code>, or <code>ip</code>. For example:
-<pre>I/DEBUG   ( 1151):     #00  5f09db68  401f01c4  /system/lib/libc.so</pre></li>
+        <li>Fixed the <code>ndk-build</code> script to add
+<code>-rpath-link=$SYSROOT/usr/lib</code> and
+<code>-rpath-link=$TARGET_OUT</code> in order to use <code>ld.bfd</code> to
+link executables. (Issue  <a href="http://b.android.com/64266">64266</a>)</li>
+        <li>Removed <code>-Bsymbolic</code> from all STL builds.</li>
+        <li>Fixed <code>ndk-gdb-py.cmd</code> by setting <code>SHELL</code> as
+an environment variable
+instead of passing it to
+  <code>python.exe</code>, which ignores the setting.
+  (Issue <a href="http://b.android.com/63054">63054</a>)</li>
+        <li>Fixed the <code>make-standalone-toolchain.sh</code> script so that
+the <code>--stl=stlport</code> option copies the gabi++ headers instead of
+symlinking them; the <code>cmd.exe</code> and MinGW shells do not understand
+symlinks created by cygwin.</li>
+     </ul>
+     </dd>
+
+     <dt>Other changes:</dt>
+     <dd>
+     <ul>
+        <li>Applied execution permissions to all <code>*cmd</code> scripts
+previously intended for use only in the <code>cmd.exe</code> shell, in case
+developers prefer to use <code>ndk-build.cmd</code> in cygwin instead of the
+recommended <code>ndk-build</code> script.</li>
+        <li>Improved the speed of the <code>make-standalone-toolchain.sh</code>
+script by moving instead of copying if the specified destination directory does
+not exist.</li>
+     </dd>
+     </ul>
+   </dl>
+ </div>
+</div>
+
+<div class="toggle-content closed">
+ <p>
+   <a href="#" onclick="return toggleContent(this)"> <img
+     src="/assets/images/triangle-closed.png" class="toggle-content-img" alt=""
+   >Android NDK, Revision 9c</a> <em>(December 2013)</em>
+ </p>
+ <div class="toggle-content-toggleme">
+<p>This is a bug-fix-only release.</p>
+   <dl>
+     <dt>Important bug fixes:</dt>
+     <dd>
+     <ul>
+       <li>Fixed a problem with GCC 4.8 ARM, in which the stack pointer is
+restored too early. This problem prevented the frame pointer from reliably
+accessing a variable in the stack frame. (GCC Issue <a
+href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58854">58854</a>)</li>
+<li>Fixed a problem with GCC 4.8 libstdc++, in which a bug in
+std::nth_element was causing generation of code that produced a random
+segfault. (Issue <a
+href="https://code.google.com/p/android/issues/detail?id=62910">62910</a>)</li>
+           <li>Fixed GCC 4.8 ICE in cc1/cc1plus with
+<code>-fuse-ld=mcld</code>, so that the following error no longer occurs:
+<pre>cc1: internal compiler error: in common_handle_option, at
+opts.c:1774</pre></li>
+           <li>Fixed <code>-mhard-float</code> support for
+<code>__builtin</code> math functions. For ongoing information on fixes for
+<code>-mhard-float</code> with STL, please follow Issue <a
+href="http://b.android.com/61784">61784</a>.</li>
+     </ul>
+     </dd>
+
+     <dt>Other bug fixes:</dt>
+     <dd>
+     <ul>
+       <li>Header fixes:
+         <ul>
+           <li>Changed prototype of <code>poll</code> to <code>poll(struct
+pollfd *, nfds_t, int);</code> in <code>poll.h</code>.</li>
+           <li>Added <code>utimensat</code> to <code>libc.so</code> for Android
+API levels 12 and 19. These libraries are now included for all Android API
+levels 12 through 19.</li>
+<li>Introduced <code>futimens</code> into <code>libc.so</code>, for Android API
+level 19.</li>
+<li>Added missing <code>clock_settime()</code> and
+<code>clock_nanosleep()</code> to <code>time.h</code> for Android API level 8
+and higher.</li>
+<li>Added <code>CLOCK_MONOTONIC_RAW, CLOCK_REALTIME_COARSE,
+CLOCK_MONOTONIC_COARSE, CLOCK_BOOTTIME, CLOCK_REALTIME_ALARM,</code> and
+<code>CLOCK_BOOTTIME_ALARM</code> in <code>time.h.</code></li>
+<li>Removed obsolete <code>CLOCK_REALTIME_HR</code> and
+<code>CLOCK_MONOTONIC_HR.</code></li>
+         </ul>
+       </li>
+       <li>In samples Teapot, MoreTeapots, and
+<code>source/android/ndk_helper</code>:
+         <ul>
+<li>Changed them so that they now use a hard-float abi for armeabi-v7a.</li>
+<li>Updated them to use immersive mode on Android API level 19 and
+higher.</li>
+<li>Fixed a problem with <code>Check_ReleaseStringUTFChars</code> in
+<code>/system/lib/libdvm.so</code> that was causing crashes on x86 devices.</li>
+         </ul>
+        </li>
+<li>Fixed <code>ndk-build</code> fails that happen in cygwin when the NDK
+package is
+referenced via symlink.</li>
+<li>Fixed <code>ndk-build.cmd</code> fails that happen in windows
+<code>cmd.exe</code> when
+<code>LOCAL_SRC_FILES</code> contains absolute paths. (Issue <a
+href="https://android-review.googlesource.com/#/c/69992">69992</a>)</li>
+<li>Fixed the <code>ndk-stack</code> script to proceed even when it can't parse
+a frame due to inability to find a routine, filename, or line number. In any of
+these cases, it prints <code>??</code>.</li>
+<li>Fixed the <code>ndk-stack</code> stack for windows-x64_64 targets so that
+it no longer erroneously matches a frame line with a line in the
+<code>stack:</code> section that doesn't contain <code>pc</code>,
+<code>eip</code>, or <code>ip</code>. For example:
+<pre>I/DEBUG   ( 1151):     #00  5f09db68  401f01c4
+/system/lib/libc.so</pre></li>
 <li>Fixed gabi++ so that it:
      <ul>
          <li>Does not use malloc() to allocate C++ thread-local
   objects.</li>
-         <li>Avoids deadlocks in gabi++ in cases where libc.debug.malloc is non-zero in
-  userdebug/eng Android platform builds.</li>
+         <li>Avoids deadlocks in gabi++ in cases where libc.debug.malloc is
+non-zero in userdebug/eng Android platform builds.</li>
      </ul>
      </ul>
      </dd>
@@ -328,12 +547,29 @@
      <dd>
      <ul>
        <li>Added <code>LOCAL_EXPORT_LDFLAGS</code>.</li>
-<li>Introduced the <code>NDK_PROJECT_PATH=null</code> setting for use in an integrated build system where options are explicitly passed to <code>ndk-build</code>. With this setting, <code>ndk-build</code> makes no attempt to look for <code>NDK_PROJECT_PATH.</code> This setting also prevents variables from deriving default settings from NDK_PROJECT_PATH. As a result, the following variables must now be explicitly specified (with their default values if such exist): <code>NDK_OUT, NDK_LIBS_OUT, APP_BUILD_SCRIPT, NDK_DEBUG</code> (optional, default to 0), and other <code>APP_*</code>'s contained in <code>Application.mk</code>.</li>
-<li><code>APP_ABI</code> can now be enumerated in a comma-delimited list. For example:
+<li>Introduced the <code>NDK_PROJECT_PATH=null</code> setting for use in an
+integrated build system where options are explicitly passed to
+<code>ndk-build</code>. With this setting, <code>ndk-build</code> makes no
+attempt to look for <code>NDK_PROJECT_PATH.</code> This setting also prevents
+variables from deriving default settings from NDK_PROJECT_PATH. As a result,
+the following variables must now be explicitly specified (with their default
+values if such exist): <code>NDK_OUT, NDK_LIBS_OUT, APP_BUILD_SCRIPT,
+NDK_DEBUG</code> (optional, default to 0), and other <code>APP_*</code>'s
+contained in <code>Application.mk</code>.</li>
+<li><code>APP_ABI</code> can now be enumerated in a comma-delimited list. For
+example:
 <pre>APP_ABI := "armeabi,armeabi-v7a"</pre></li>
-<li>Provided the ability (option <code>-g</code>) to rebuild all of STL with debugging info in an optional, separate package called <code>android-ndk-r9c-cxx-stl-libs-with-debugging-info.zip</code>. This option helps ndk-stack to provide better a stack dump across STL. This change should not affect the code/size of the final, stripped file.</li>
-<li>Enhanced <code>hello-jni</code> samples to report <code>APP_ABI</code> at compilation.</li>
-<li>Used the <code>ar</code> tool in Deterministic mode (option <code>-D</code>) to build static libraries.  For more information, see <a href="http://b.android.com/60705">http://b.android.com/60705</a>.</li>
+<li>Provided the ability to rebuild all of STL with debugging info in an
+optional, separate package called
+<code>android-ndk-r9c-cxx-stl-libs-with-debugging-info.zip</code>, using the
+<code>-g</code> option. This option
+helps the <code>ndk-stack</code> script provide better a stack dump across STL.
+This change should not affect the code/size of the final, stripped file.</li>
+<li>Enhanced <code>hello-jni</code> samples to report <code>APP_ABI</code> at
+compilation.</li>
+<li>Used the <code>ar</code> tool in Deterministic mode (option
+<code>-D</code>) to build static libraries.  (Issue <a
+href="http://b.android.com/60705">60705</a>)</li>
      </ul>
      </dd>
 
@@ -360,7 +596,7 @@
           (Issues <a href="http://b.android.com/47150">47150</a>,
            <a href="http://b.android.com/58528">58528</a>, and
            <a href="http://b.android.com/38423">38423</a>)</li>
-        <li>Added support for API level 19, including Renderscript binding.</li>
+        <li>Added support for Android API level 19, including Renderscript binding.</li>
         <li>Added support for <code>-mhard-float</code> in the existing armeabi-v7a ABI. For more
           information and current restrictions on Clang, see
           {@code tests/device/hard-float/jni/Android.mk}.</li>
@@ -2392,8 +2628,8 @@
     dealing with signed chars.</li>
     <li>Adds missing documentation for the
     "gnustl_static" value for APP_STL, that allows you to link against
-    a static library version of GNU libstdc++. </li>
-    <li>The following <code>ndk-build</code> issues are fixed:
+    a static library version of GNU libstdc++. </li> the
+    <li>Fixed the following <code>ndk-build</code> issues:
       <ul>
         <li>A bug that created inconsistent dependency files when a
         compilation error occured on Windows. This prevented a proper build after
diff --git a/docs/html/tools/sdk/tools-notes.jd b/docs/html/tools/sdk/tools-notes.jd
index c28b946..99f0b38 100644
--- a/docs/html/tools/sdk/tools-notes.jd
+++ b/docs/html/tools/sdk/tools-notes.jd
@@ -26,10 +26,92 @@
 href="http://tools.android.com/knownissues">http://tools.android.com/knownissues</a>.</p>
 
 
-
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>SDK Tools, Revision 22.6</a> <em>(March 2014)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+
+    <dl>
+    <dt>Dependencies:</dt>
+    <dd>
+      <ul>
+        <li>Android SDK Platform-tools revision 18 or later.</li>
+        <li>If you are developing in Eclipse with ADT, note that this version of SDK Tools is
+          designed for use with ADT 22.6.0 and later. If you haven't already, update your
+        <a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin</a> to 22.6.0.</li>
+        <li>If you are developing outside Eclipse, you must have
+          <a href="http://ant.apache.org/">Apache Ant</a> 1.8 or later.</li>
+      </ul>
+    </dd>
+
+    <dt>General Notes:</dt>
+    <dd>
+      <ul>
+        <li><p>The command line <code>lint</code> script (<code>tools\lint.bat</code> on
+            Windows platforms, <code>tools/lint</code> on other platforms) and the
+            <code>lint</code> target on <code>ant</code> builds fail with the following
+            error:</p>
+            <p><code>Exception in thread "main" java.lang.NoClassDefFoundError:
+            lombok/ast/AstVisitor</code></p>
+            <p>As a temporary workaround, rename the file
+              <code>tools\lib\lombok-ast-0.2.2.jar</code> to
+            <code>tools\lib\lombok-ast.jar</code>.
+            We will release an updated version of the tools with a fix for
+            this issue as soon as possible.</p>
+          </li>
+        <li>Added support for Java 7 language features like multi-catch, try-with-resources,
+            and the diamond operator. These features require version 19 or higher
+            of the Build Tools. Try-with-resources requires <code>minSdkVersion</code>
+            19; the rest of the new language features require
+            <code>minSdkVersion</code> 8 or higher.</li>
+        <li>Added new lint checks:
+          <ul>
+            <li>Security:
+              <ul>
+                <li>Look for code potentially affected by a <code>SecureRandom</code>
+                    vulnerability.</li>
+                <li>Check that calls to <code>checkPermission</code> use the return value.</li>
+              </ul>
+            </li>
+            <li>Check that production builds do not use mock location providers.</li>
+            <li>Look for manifest values that are overwritten by values from Gradle build 
+                scripts.</li>
+          </ul>
+        </li>
+        <li>Fixed a number of minor issues in the SDK and build system.</li>
+        <li>Emulator:
+          <ul>
+            <li>Fixed a problem with the emulator shutting down immediately for Android 1.5
+                on the Nexus One and Nexus S devices.
+                (<a href="http://b.android.com/64945">Issue 64945</a>)</li>
+            <li>Fixed a problem with port numbers longer than four digits.
+                (<a href="http://b.android.com/60024">Issue 60024</a>)</li>
+            <li>Fixed battery errors for the Nexus One and Nexus S devices.
+                (<a href="http://b.android.com/39959">Issue 39959</a>)</li>
+            <li>Fixed a problem with paths or arguments that contain
+                spaces on Windows platforms.
+                (<a href="http://b.android.com/18317">Issue 18317</a>)</li>
+            <li>Fixed a problem with long path values on Windows platforms.
+                (<a href="http://b.android.com/33336">Issue 33336</a>)</li>
+            <li>Fixed a problem with the {@code -snapshot-list} command line
+                option on 64-bit systems.
+                (<a href="http://b.android.com/34233">Issue 34233</a>)</li>
+          </ul>
+        </li>
+        <li>Fixed an issue with RenderScript support. Using RenderScript support mode 
+          now requires version 19.0.3 of the Build Tools.</li>
+      </ul>
+    </dd>
+    </dl>
+  </div>
+</div>
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>SDK Tools, Revision 22.3</a> <em>(October 2013)</em>
   </p>
 
diff --git a/docs/html/tools/testing/testing_ui.jd b/docs/html/tools/testing/testing_ui.jd
index 701415e..4318a21 100644
--- a/docs/html/tools/testing/testing_ui.jd
+++ b/docs/html/tools/testing/testing_ui.jd
@@ -90,7 +90,7 @@
          alt="User interface of uiautomatorviewer tool" height="327px" id="figure1"/>
 </a>
 <p class="img-caption">
-    <strong>Figure 1.</strong> The {@code uiautomatorviewer} showing the captured interface of a test deviice.
+    <strong>Figure 1.</strong> The {@code uiautomatorviewer} showing the captured interface of a test device.
 </p>
 
 <p>To analyze the UI components of the application that you want to test:</p>
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index d6b73fd..7676143 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -400,7 +400,7 @@
          * No color information is stored.
          * With this configuration, each pixel requires 1 byte of memory.
          */
-        ALPHA_8     (2),
+        ALPHA_8     (1),
 
         /**
          * Each pixel is stored on 2 bytes and only the RGB channels are
@@ -416,7 +416,7 @@
          * This configuration may be useful when using opaque bitmaps
          * that do not require high color fidelity.
          */
-        RGB_565     (4),
+        RGB_565     (3),
 
         /**
          * Each pixel is stored on 2 bytes. The three RGB color channels
@@ -438,7 +438,7 @@
          *             it is advised to use {@link #ARGB_8888} instead.
          */
         @Deprecated
-        ARGB_4444   (5),
+        ARGB_4444   (4),
 
         /**
          * Each pixel is stored on 4 bytes. Each channel (RGB and alpha
@@ -448,13 +448,13 @@
          * This configuration is very flexible and offers the best
          * quality. It should be used whenever possible.
          */
-        ARGB_8888   (6);
+        ARGB_8888   (5);
 
         final int nativeInt;
 
         @SuppressWarnings({"deprecation"})
         private static Config sConfigs[] = {
-            null, null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888
+            null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888
         };
         
         Config(int ni) {
diff --git a/graphics/java/android/graphics/LayerRasterizer.java b/graphics/java/android/graphics/LayerRasterizer.java
index dc307c6..5b356089 100644
--- a/graphics/java/android/graphics/LayerRasterizer.java
+++ b/graphics/java/android/graphics/LayerRasterizer.java
@@ -21,11 +21,11 @@
         native_instance = nativeConstructor();
     }
     
-	/**	Add a new layer (above any previous layers) to the rasterizer.
-		The layer will extract those fields that affect the mask from
-		the specified paint, but will not retain a reference to the paint
-		object itself, so it may be reused without danger of side-effects.
-	*/
+    /** Add a new layer (above any previous layers) to the rasterizer.
+        The layer will extract those fields that affect the mask from
+        the specified paint, but will not retain a reference to the paint
+        object itself, so it may be reused without danger of side-effects.
+    */
     public void addLayer(Paint paint, float dx, float dy) {
         nativeAddLayer(native_instance, paint.mNativePaint, dx, dy);
     }
diff --git a/graphics/java/android/graphics/LinearGradient.java b/graphics/java/android/graphics/LinearGradient.java
index 9ad3e49..0eae67c 100644
--- a/graphics/java/android/graphics/LinearGradient.java
+++ b/graphics/java/android/graphics/LinearGradient.java
@@ -38,7 +38,7 @@
 
     private TileMode mTileMode;
 
-	/**	Create a shader that draws a linear gradient along a line.
+    /** Create a shader that draws a linear gradient along a line.
         @param x0           The x-coordinate for the start of the gradient line
         @param y0           The y-coordinate for the start of the gradient line
         @param x1           The x-coordinate for the end of the gradient line
@@ -48,8 +48,8 @@
                             each corresponding color in the colors array. If this is null,
                             the the colors are distributed evenly along the gradient line.
         @param  tile        The Shader tiling mode
-	*/
-	public LinearGradient(float x0, float y0, float x1, float y1, int colors[], float positions[],
+    */
+    public LinearGradient(float x0, float y0, float x1, float y1, int colors[], float positions[],
             TileMode tile) {
         if (colors.length < 2) {
             throw new IllegalArgumentException("needs >= 2 number of colors");
@@ -70,7 +70,7 @@
                 tile.nativeInt);
     }
 
-	/**	Create a shader that draws a linear gradient along a line.
+    /** Create a shader that draws a linear gradient along a line.
         @param x0       The x-coordinate for the start of the gradient line
         @param y0       The y-coordinate for the start of the gradient line
         @param x1       The x-coordinate for the end of the gradient line
@@ -78,8 +78,8 @@
         @param  color0  The color at the start of the gradient line.
         @param  color1  The color at the end of the gradient line.
         @param  tile    The Shader tiling mode
-	*/
-	public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1,
+    */
+    public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1,
             TileMode tile) {
         mType = TYPE_COLOR_START_AND_COLOR_END;
         mX0 = x0;
@@ -118,7 +118,7 @@
 
     private native long nativeCreate1(float x0, float y0, float x1, float y1,
             int colors[], float positions[], int tileMode);
-	private native long nativeCreate2(float x0, float y0, float x1, float y1,
+    private native long nativeCreate2(float x0, float y0, float x1, float y1,
             int color0, int color1, int tileMode);
     private native long nativePostCreate1(long native_shader, float x0, float y0, float x1, float y1,
             int colors[], float positions[], int tileMode);
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index 2ce73ac..c07a6da 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -168,6 +168,21 @@
     }
 
     /**
+     * Returns the path's convexity, as defined by the content of the path.
+     * <p>
+     * A path is convex if it has a single contour, and only ever curves in a
+     * single direction.
+     * <p>
+     * This function will calculate the convexity of the path from its control
+     * points, and cache the result.
+     *
+     * @return True if the path is convex.
+     */
+    public boolean isConvex() {
+        return native_isConvex(mNativePath);
+    }
+
+    /**
      * Enum for the ways a path may be filled.
      */
     public enum FillType {
@@ -224,7 +239,7 @@
     public void setFillType(FillType ft) {
         native_setFillType(mNativePath, ft.nativeInt);
     }
-    
+
     /**
      * Returns true if the filltype is one of the INVERSE variants
      *
@@ -232,18 +247,18 @@
      */
     public boolean isInverseFillType() {
         final int ft = native_getFillType(mNativePath);
-        return (ft & 2) != 0;
+        return (ft & FillType.INVERSE_WINDING.nativeInt) != 0;
     }
-    
+
     /**
      * Toggles the INVERSE state of the filltype
      */
     public void toggleInverseFillType() {
         int ft = native_getFillType(mNativePath);
-        ft ^= 2;
+        ft ^= FillType.INVERSE_WINDING.nativeInt;
         native_setFillType(mNativePath, ft);
     }
-    
+
     /**
      * Returns true if the path is empty (contains no lines or curves)
      *
@@ -719,6 +734,7 @@
     private static native void native_reset(long nPath);
     private static native void native_rewind(long nPath);
     private static native void native_set(long native_dst, long native_src);
+    private static native boolean native_isConvex(long nPath);
     private static native int native_getFillType(long nPath);
     private static native void native_setFillType(long nPath, int ft);
     private static native boolean native_isEmpty(long nPath);
diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java
index f10e5d6..c00c612 100644
--- a/graphics/java/android/graphics/RadialGradient.java
+++ b/graphics/java/android/graphics/RadialGradient.java
@@ -37,17 +37,17 @@
 
     private TileMode mTileMode;
 
-	/**	Create a shader that draws a radial gradient given the center and radius.
+    /** Create a shader that draws a radial gradient given the center and radius.
         @param x        The x-coordinate of the center of the radius
         @param y        The y-coordinate of the center of the radius
-		@param radius   Must be positive. The radius of the circle for this gradient
+        @param radius   Must be positive. The radius of the circle for this gradient
         @param colors   The colors to be distributed between the center and edge of the circle
         @param positions May be NULL. The relative position of
                         each corresponding color in the colors array. If this is NULL,
                         the the colors are distributed evenly between the center and edge of the circle.
         @param  tile    The Shader tiling mode
-	*/
-	public RadialGradient(float x, float y, float radius,
+    */
+    public RadialGradient(float x, float y, float radius,
                           int colors[], float positions[], TileMode tile) {
         if (radius <= 0) {
             throw new IllegalArgumentException("radius must be > 0");
@@ -70,15 +70,15 @@
                 tile.nativeInt);
     }
 
-	/**	Create a shader that draws a radial gradient given the center and radius.
+    /** Create a shader that draws a radial gradient given the center and radius.
         @param x        The x-coordinate of the center of the radius
         @param y        The y-coordinate of the center of the radius
-		@param radius   Must be positive. The radius of the circle for this gradient
+        @param radius   Must be positive. The radius of the circle for this gradient
         @param color0   The color at the center of the circle.
         @param color1   The color at the edge of the circle.
         @param tile     The Shader tiling mode
-	*/
-	public RadialGradient(float x, float y, float radius,
+    */
+    public RadialGradient(float x, float y, float radius,
                           int color0, int color1, TileMode tile) {
         if (radius <= 0) {
             throw new IllegalArgumentException("radius must be > 0");
@@ -119,7 +119,7 @@
 
     private static native long nativeCreate1(float x, float y, float radius,
             int colors[], float positions[], int tileMode);
-	private static native long nativeCreate2(float x, float y, float radius,
+    private static native long nativeCreate2(float x, float y, float radius,
             int color0, int color1, int tileMode);
 
     private static native long nativePostCreate1(long native_shader, float x, float y, float radius,
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 9360558..fe08f4b 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -16,6 +16,7 @@
 
 package android.graphics.drawable;
 
+import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
@@ -26,8 +27,8 @@
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
 import android.graphics.PorterDuff.Mode;
+import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
 import android.graphics.Shader;
 import android.graphics.Xfermode;
@@ -49,8 +50,8 @@
  * information, see the guide to <a
  * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
  * <p>
- * Also see the {@link android.graphics.Bitmap} class, which handles the management and 
- * transformation of raw bitmap graphics, and should be used when drawing to a 
+ * Also see the {@link android.graphics.Bitmap} class, which handles the management and
+ * transformation of raw bitmap graphics, and should be used when drawing to a
  * {@link android.graphics.Canvas}.
  * </p>
  *
@@ -68,13 +69,14 @@
             Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG;
     private BitmapState mBitmapState;
     private Bitmap mBitmap;
+    private PorterDuffColorFilter mTintFilter;
     private int mTargetDensity;
 
     private final Rect mDstRect = new Rect();   // Gravity.apply() sets this
 
     private boolean mApplyGravity;
     private boolean mMutated;
-    
+
      // These are scaled to match the target density.
     private int mBitmapWidth;
     private int mBitmapHeight;
@@ -192,7 +194,7 @@
         mBitmapWidth = mBitmap.getScaledWidth(mTargetDensity);
         mBitmapHeight = mBitmap.getScaledHeight(mTargetDensity);
     }
-    
+
     private void setBitmap(Bitmap bitmap) {
         if (bitmap != mBitmap) {
             mBitmap = bitmap;
@@ -277,7 +279,7 @@
      *
      * @param mipMap True if the bitmap should use mipmaps, false otherwise.
      *
-     * @see #hasMipMap() 
+     * @see #hasMipMap()
      */
     public void setMipMap(boolean mipMap) {
         if (mBitmapState.mBitmap != null) {
@@ -292,7 +294,7 @@
      * @return True if the mipmap hint is set, false otherwise. If the bitmap
      *         is null, this method always returns false.
      *
-     * @see #setMipMap(boolean) 
+     * @see #setMipMap(boolean)
      * @attr ref android.R.styleable#BitmapDrawable_mipMap
      */
     public boolean hasMipMap() {
@@ -302,10 +304,10 @@
     /**
      * Enables or disables anti-aliasing for this drawable. Anti-aliasing affects
      * the edges of the bitmap only so it applies only when the drawable is rotated.
-     * 
+     *
      * @param aa True if the bitmap should be anti-aliased, false otherwise.
      *
-     * @see #hasAntiAlias() 
+     * @see #hasAntiAlias()
      */
     public void setAntiAlias(boolean aa) {
         mBitmapState.mPaint.setAntiAlias(aa);
@@ -337,7 +339,7 @@
 
     /**
      * Indicates the repeat behavior of this drawable on the X axis.
-     * 
+     *
      * @return {@link Shader.TileMode#CLAMP} if the bitmap does not repeat,
      *         {@link Shader.TileMode#REPEAT} or {@link Shader.TileMode#MIRROR} otherwise.
      */
@@ -347,10 +349,10 @@
 
     /**
      * Indicates the repeat behavior of this drawable on the Y axis.
-     * 
+     *
      * @return {@link Shader.TileMode#CLAMP} if the bitmap does not repeat,
      *         {@link Shader.TileMode#REPEAT} or {@link Shader.TileMode#MIRROR} otherwise.
-     */    
+     */
     public Shader.TileMode getTileModeY() {
         return mBitmapState.mTileModeY;
     }
@@ -360,11 +362,11 @@
      * does not repeat its bitmap. Using {@link Shader.TileMode#REPEAT} or
      * {@link Shader.TileMode#MIRROR} the bitmap can be repeated (or tiled) if the bitmap
      * is smaller than this drawable.
-     * 
+     *
      * @param mode The repeat mode for this drawable.
-     * 
-     * @see #setTileModeY(android.graphics.Shader.TileMode) 
-     * @see #setTileModeXY(android.graphics.Shader.TileMode, android.graphics.Shader.TileMode) 
+     *
+     * @see #setTileModeY(android.graphics.Shader.TileMode)
+     * @see #setTileModeXY(android.graphics.Shader.TileMode, android.graphics.Shader.TileMode)
      */
     public void setTileModeX(Shader.TileMode mode) {
         setTileModeXY(mode, mBitmapState.mTileModeY);
@@ -375,12 +377,12 @@
      * does not repeat its bitmap. Using {@link Shader.TileMode#REPEAT} or
      * {@link Shader.TileMode#MIRROR} the bitmap can be repeated (or tiled) if the bitmap
      * is smaller than this drawable.
-     * 
+     *
      * @param mode The repeat mode for this drawable.
-     * 
-     * @see #setTileModeX(android.graphics.Shader.TileMode) 
-     * @see #setTileModeXY(android.graphics.Shader.TileMode, android.graphics.Shader.TileMode) 
-     */    
+     *
+     * @see #setTileModeX(android.graphics.Shader.TileMode)
+     * @see #setTileModeXY(android.graphics.Shader.TileMode, android.graphics.Shader.TileMode)
+     */
     public final void setTileModeY(Shader.TileMode mode) {
         setTileModeXY(mBitmapState.mTileModeX, mode);
     }
@@ -390,12 +392,12 @@
      * does not repeat its bitmap. Using {@link Shader.TileMode#REPEAT} or
      * {@link Shader.TileMode#MIRROR} the bitmap can be repeated (or tiled) if the bitmap
      * is smaller than this drawable.
-     * 
+     *
      * @param xmode The X repeat mode for this drawable.
      * @param ymode The Y repeat mode for this drawable.
-     * 
+     *
      * @see #setTileModeX(android.graphics.Shader.TileMode)
-     * @see #setTileModeY(android.graphics.Shader.TileMode) 
+     * @see #setTileModeY(android.graphics.Shader.TileMode)
      */
     public void setTileModeXY(Shader.TileMode xmode, Shader.TileMode ymode) {
         final BitmapState state = mBitmapState;
@@ -457,66 +459,86 @@
 
     @Override
     public void draw(Canvas canvas) {
-        Bitmap bitmap = mBitmap;
-        if (bitmap != null) {
-            final BitmapState state = mBitmapState;
-            if (state.mRebuildShader) {
-                Shader.TileMode tmx = state.mTileModeX;
-                Shader.TileMode tmy = state.mTileModeY;
+        final Bitmap bitmap = mBitmap;
+        if (bitmap == null) {
+            return;
+        }
 
-                if (tmx == null && tmy == null) {
-                    state.mPaint.setShader(null);
-                } else {
-                    state.mPaint.setShader(new BitmapShader(bitmap,
-                            tmx == null ? Shader.TileMode.CLAMP : tmx,
-                            tmy == null ? Shader.TileMode.CLAMP : tmy));
-                }
-                state.mRebuildShader = false;
-                copyBounds(mDstRect);
-            }
-
-            Shader shader = state.mPaint.getShader();
-            final boolean needMirroring = needMirroring();
-            if (shader == null) {
-                if (mApplyGravity) {
-                    final int layoutDirection = getLayoutDirection();
-                    Gravity.apply(state.mGravity, mBitmapWidth, mBitmapHeight,
-                            getBounds(), mDstRect, layoutDirection);
-                    mApplyGravity = false;
-                }
-                if (needMirroring) {
-                    canvas.save();
-                    // Mirror the bitmap
-                    canvas.translate(mDstRect.right - mDstRect.left, 0);
-                    canvas.scale(-1.0f, 1.0f);
-                }
-                canvas.drawBitmap(bitmap, null, mDstRect, state.mPaint);
-                if (needMirroring) {
-                    canvas.restore();
-                }
+        final BitmapState state = mBitmapState;
+        final Paint paint = state.mPaint;
+        if (state.mRebuildShader) {
+            final Shader.TileMode tmx = state.mTileModeX;
+            final Shader.TileMode tmy = state.mTileModeY;
+            if (tmx == null && tmy == null) {
+                paint.setShader(null);
             } else {
-                if (mApplyGravity) {
-                    copyBounds(mDstRect);
-                    mApplyGravity = false;
-                }
-                if (needMirroring) {
-                    // Mirror the bitmap
-                    updateMirrorMatrix(mDstRect.right - mDstRect.left);
-                    shader.setLocalMatrix(mMirrorMatrix);
-                } else {
-                    if (mMirrorMatrix != null) {
-                        mMirrorMatrix = null;
-                        shader.setLocalMatrix(Matrix.IDENTITY_MATRIX);
-                    }
-                }
-                canvas.drawRect(mDstRect, state.mPaint);
+                paint.setShader(new BitmapShader(bitmap,
+                        tmx == null ? Shader.TileMode.CLAMP : tmx,
+                        tmy == null ? Shader.TileMode.CLAMP : tmy));
             }
+
+            state.mRebuildShader = false;
+            copyBounds(mDstRect);
+        }
+
+        final boolean clearColorFilter;
+        if (mTintFilter != null && paint.getColorFilter() == null) {
+            paint.setColorFilter(mTintFilter);
+            clearColorFilter = true;
+        } else {
+            clearColorFilter = false;
+        }
+
+        final Shader shader = paint.getShader();
+        final boolean needMirroring = needMirroring();
+        if (shader == null) {
+            if (mApplyGravity) {
+                final int layoutDirection = getLayoutDirection();
+                Gravity.apply(state.mGravity, mBitmapWidth, mBitmapHeight,
+                        getBounds(), mDstRect, layoutDirection);
+                mApplyGravity = false;
+            }
+
+            if (needMirroring) {
+                canvas.save();
+                // Mirror the bitmap
+                canvas.translate(mDstRect.right - mDstRect.left, 0);
+                canvas.scale(-1.0f, 1.0f);
+            }
+
+            canvas.drawBitmap(bitmap, null, mDstRect, paint);
+
+            if (needMirroring) {
+                canvas.restore();
+            }
+        } else {
+            if (mApplyGravity) {
+                copyBounds(mDstRect);
+                mApplyGravity = false;
+            }
+
+            if (needMirroring) {
+                // Mirror the bitmap
+                updateMirrorMatrix(mDstRect.right - mDstRect.left);
+                shader.setLocalMatrix(mMirrorMatrix);
+            } else {
+                if (mMirrorMatrix != null) {
+                    mMirrorMatrix = null;
+                    shader.setLocalMatrix(Matrix.IDENTITY_MATRIX);
+                }
+            }
+
+            canvas.drawRect(mDstRect, paint);
+        }
+
+        if (clearColorFilter) {
+            paint.setColorFilter(null);
         }
     }
 
     @Override
     public void setAlpha(int alpha) {
-        int oldAlpha = mBitmapState.mPaint.getAlpha();
+        final int oldAlpha = mBitmapState.mPaint.getAlpha();
         if (alpha != oldAlpha) {
             mBitmapState.mPaint.setAlpha(alpha);
             invalidateSelf();
@@ -534,6 +556,80 @@
         invalidateSelf();
     }
 
+    @Override
+    public ColorFilter getColorFilter() {
+        return mBitmapState.mPaint.getColorFilter();
+    }
+
+    /**
+     * Specifies a tint for this drawable.
+     * <p>
+     * Setting a color filter via {@link #setColorFilter(ColorFilter)} overrides
+     * tint.
+     *
+     * @param tint Color state list to use for tinting this drawable, or null to
+     *            clear the tint
+     */
+    public void setTint(ColorStateList tint) {
+        if (mBitmapState.mTint != tint) {
+            mBitmapState.mTint = tint;
+            updateTintFilter();
+            invalidateSelf();
+        }
+    }
+
+    /**
+     * Returns the tint color for this drawable.
+     *
+     * @return Color state list to use for tinting this drawable, or null if
+     *         none set
+     */
+    public ColorStateList getTint() {
+        return mBitmapState.mTint;
+    }
+
+    /**
+     * Specifies the blending mode used to apply tint.
+     *
+     * @param tintMode A Porter-Duff blending mode
+     * @hide Pending finalization of supported Modes
+     */
+    public void setTintMode(Mode tintMode) {
+        if (mBitmapState.mTintMode != tintMode) {
+            mBitmapState.mTintMode = tintMode;
+            updateTintFilter();
+            invalidateSelf();
+        }
+    }
+
+    /**
+     * Returns the tint mode for this drawable, or {@code null} if none set.
+     *
+     * @return the tint mode for this drawable, or {@code null} if none set
+     * @hide
+     */
+    public Mode getTintMode() {
+        return mBitmapState.mTintMode;
+    }
+
+    /**
+     * Ensures the tint filter is consistent with the current tint color and
+     * mode.
+     */
+    private void updateTintFilter() {
+        final ColorStateList tint = mBitmapState.mTint;
+        final Mode tintMode = mBitmapState.mTintMode;
+        if (tint != null && tintMode != null) {
+            if (mTintFilter == null) {
+                mTintFilter = new PorterDuffColorFilter(0, tintMode);
+            } else {
+                mTintFilter.setMode(tintMode);
+            }
+        } else {
+            mTintFilter = null;
+        }
+    }
+
     /**
      * @hide Candidate for future API inclusion
      */
@@ -558,11 +654,34 @@
     }
 
     @Override
+    protected boolean onStateChange(int[] stateSet) {
+        final ColorStateList tint = mBitmapState.mTint;
+        if (tint != null) {
+            final int newColor = tint.getColorForState(stateSet, 0);
+            final int oldColor = mTintFilter.getColor();
+            if (oldColor != newColor) {
+                mTintFilter.setColor(newColor);
+                invalidateSelf();
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean isStateful() {
+        final BitmapState s = mBitmapState;
+        return super.isStateful() || (s.mTint != null && s.mTint.isStateful());
+    }
+
+    @Override
     public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs)
             throws XmlPullParserException, IOException {
         super.inflate(r, parser, attrs);
 
-        TypedArray a = r.obtainAttributes(attrs, com.android.internal.R.styleable.BitmapDrawable);
+        final BitmapState state = mBitmapState;
+        final TypedArray a = r.obtainAttributes(attrs, com.android.internal.R.styleable.BitmapDrawable);
 
         final int id = a.getResourceId(com.android.internal.R.styleable.BitmapDrawable_src, 0);
         if (id == 0) {
@@ -574,7 +693,7 @@
             throw new XmlPullParserException(parser.getPositionDescription() +
                     ": <bitmap> requires a valid src attribute");
         }
-        mBitmapState.mBitmap = bitmap;
+        state.mBitmap = bitmap;
         setBitmap(bitmap);
         setTargetDensity(r.getDisplayMetrics());
         setMipMap(a.getBoolean(com.android.internal.R.styleable.BitmapDrawable_mipMap,
@@ -582,19 +701,16 @@
         setAutoMirrored(a.getBoolean(com.android.internal.R.styleable.BitmapDrawable_autoMirrored,
                 false));
 
-        if (a.hasValue(com.android.internal.R.styleable.BitmapDrawable_colorFilterColor)) {
-            final int colorFilterColor = a.getColor(
-                    com.android.internal.R.styleable.BitmapDrawable_colorFilterColor, 0);
-            final int modeValue = a.getInt(
-                    com.android.internal.R.styleable.BitmapDrawable_colorFilterMode,
-                    Mode.MULTIPLY.ordinal());
-            final Mode mode = Drawable.parseColorFilterMode(modeValue);
-            if (mode != null) {
-                setColorFilter(colorFilterColor, mode);
-            }
+        final int tintModeValue = a.getInt(
+                com.android.internal.R.styleable.BitmapDrawable_tintMode, -1);
+        state.mTintMode = Drawable.parseTintMode(tintModeValue, Mode.SRC_IN);
+        state.mTint = a.getColorStateList(com.android.internal.R.styleable.BitmapDrawable_tint);
+        if (state.mTint != null) {
+            final int color = state.mTint.getColorForState(getState(), 0);
+            mTintFilter = new PorterDuffColorFilter(color, mBitmapState.mTintMode);
         }
 
-        final Paint paint = mBitmapState.mPaint;
+        final Paint paint = state.mPaint;
         paint.setAntiAlias(a.getBoolean(com.android.internal.R.styleable.BitmapDrawable_antialias,
                 paint.isAntiAlias()));
         paint.setFilterBitmap(a.getBoolean(com.android.internal.R.styleable.BitmapDrawable_filter,
@@ -648,6 +764,8 @@
 
     final static class BitmapState extends ConstantState {
         Bitmap mBitmap;
+        ColorStateList mTint;
+        Mode mTintMode = Mode.SRC_IN;
         int mChangingConfigurations;
         int mGravity = Gravity.FILL;
         Paint mPaint = new Paint(DEFAULT_PAINT_FLAGS);
@@ -663,6 +781,8 @@
 
         BitmapState(BitmapState bitmapState) {
             mBitmap = bitmapState.mBitmap;
+            mTint = bitmapState.mTint;
+            mTintMode = bitmapState.mTintMode;
             mChangingConfigurations = bitmapState.mChangingConfigurations;
             mGravity = bitmapState.mGravity;
             mTileModeX = bitmapState.mTileModeX;
@@ -696,11 +816,18 @@
 
     private BitmapDrawable(BitmapState state, Resources res) {
         mBitmapState = state;
+
         if (res != null) {
             mTargetDensity = res.getDisplayMetrics().densityDpi;
         } else {
             mTargetDensity = state.mTargetDensity;
         }
+
+        if (state.mTint != null) {
+            final int color = state.mTint.getColorForState(getState(), 0);
+            mTintFilter = new PorterDuffColorFilter(color, state.mTintMode);
+        }
+
         setBitmap(state != null ? state.mBitmap : null);
     }
 }
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index b81e1c0..84211ef 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -19,6 +19,7 @@
 import android.graphics.Insets;
 import android.graphics.Xfermode;
 import android.os.Trace;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -34,6 +35,7 @@
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
 import android.graphics.Region;
+import android.graphics.PorterDuff.Mode;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.StateSet;
@@ -452,12 +454,6 @@
     }
 
     /**
-     * Specify an optional color filter for the drawable. Pass null to remove
-     * any existing color filter.
-     */
-    public abstract void setColorFilter(ColorFilter cf);
-
-    /**
      * @hide Consider for future API inclusion
      */
     public void setXfermode(Xfermode mode) {
@@ -467,6 +463,15 @@
     }
 
     /**
+     * Specify an optional color filter for the drawable. Pass {@code null} to
+     * remove any existing color filter.
+     *
+     * @param cf the color filter to apply, or {@code null} to remove the
+     *            existing color filter
+     */
+    public abstract void setColorFilter(ColorFilter cf);
+
+    /**
      * Specify a color and Porter-Duff mode to be the color filter for this
      * drawable.
      */
@@ -475,6 +480,15 @@
     }
 
     /**
+     * Returns the current color filter, or {@code null} if none set.
+     *
+     * @return the current color filter, or {@code null} if none set
+     */
+    public ColorFilter getColorFilter() {
+        return null;
+    }
+
+    /**
      * Removes the color filter for this drawable.
      */
     public void clearColorFilter() {
@@ -1137,15 +1151,21 @@
     }
 
     /**
-     * Parses a {@link android.graphics.PorterDuff.Mode} from a colorFilterMode
+     * Parses a {@link android.graphics.PorterDuff.Mode} from a tintMode
      * attribute's enum value.
      */
-    static PorterDuff.Mode parseColorFilterMode(int value) {
-        final PorterDuff.Mode[] modes = PorterDuff.Mode.values();
-        if (value >= 0 && value < modes.length) {
-            return modes[value];
+    static PorterDuff.Mode parseTintMode(int value, Mode defaultMode) {
+        switch (value) {
+            case 0:
+                return Mode.SRC_IN;
+            case 1:
+                return Mode.SRC_ATOP;
+            case 2:
+                return Mode.MULTIPLY;
+            case 3:
+                return Mode.SCREEN;
         }
-        return null;
+        return defaultMode;
     }
 }
 
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 331a34e..46d57ad 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -731,7 +731,7 @@
     }
 
     @Override
-    public boolean onStateChange(int[] stateSet) {
+    protected boolean onStateChange(int[] stateSet) {
         boolean invalidateSelf = false;
 
         final GradientState s = mGradientState;
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 515d3c1..44584a7 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -16,6 +16,7 @@
 
 package android.graphics.drawable;
 
+import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
@@ -26,10 +27,10 @@
 import android.graphics.NinePatch;
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
+import android.graphics.PorterDuff.Mode;
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
 import android.graphics.Region;
-import android.graphics.PorterDuff.Mode;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.LayoutDirection;
@@ -59,6 +60,7 @@
     private static final boolean DEFAULT_DITHER = false;
     private NinePatchState mNinePatchState;
     private NinePatch mNinePatch;
+    private PorterDuffColorFilter mTintFilter;
     private Rect mPadding;
     private Insets mOpticalInsets = Insets.NONE;
     private Paint mPaint;
@@ -136,10 +138,14 @@
             // lazy allocation of a paint
             setDither(state.mDither);
         }
-        if (state.mColorFilter != null) {
-            setColorFilter(state.mColorFilter);
+
+        if (state.mTint != null) {
+            final int color = state.mTint.getColorForState(getState(), 0);
+            mTintFilter = new PorterDuffColorFilter(color, state.mTintMode);
         }
+
         setAutoMirrored(state.mAutoMirrored);
+
         if (mNinePatch != null) {
             computeBitmapSize();
         }
@@ -225,6 +231,15 @@
     @Override
     public void draw(Canvas canvas) {
         final Rect bounds = getBounds();
+
+        final boolean clearColorFilter;
+        if (mTintFilter != null && getPaint().getColorFilter() == null) {
+            mPaint.setColorFilter(mTintFilter);
+            clearColorFilter = true;
+        } else {
+            clearColorFilter = false;
+        }
+
         final boolean needsMirroring = needsMirroring();
         if (needsMirroring) {
             canvas.save();
@@ -232,10 +247,16 @@
             canvas.translate(bounds.right - bounds.left, 0);
             canvas.scale(-1.0f, 1.0f);
         }
+
         mNinePatch.draw(canvas, bounds, mPaint);
+
         if (needsMirroring) {
             canvas.restore();
         }
+
+        if (clearColorFilter) {
+            mPaint.setColorFilter(null);
+        }
     }
 
     @Override
@@ -295,6 +316,65 @@
         invalidateSelf();
     }
 
+    /**
+     * Specifies a tint for this drawable.
+     * <p>
+     * Setting a color filter via {@link #setColorFilter(ColorFilter)} overrides
+     * tint.
+     *
+     * @param tint Color state list to use for tinting this drawable, or null to
+     *            clear the tint
+     */
+    public void setTint(ColorStateList tint) {
+        if (mNinePatchState.mTint != tint) {
+            mNinePatchState.mTint = tint;
+            updateTintFilter();
+            invalidateSelf();
+        }
+    }
+
+    /**
+     * Returns the tint color for this drawable.
+     *
+     * @return Color state list to use for tinting this drawable, or null if
+     *         none set
+     */
+    public ColorStateList getTint() {
+        return mNinePatchState.mTint;
+    }
+
+    /**
+     * Specifies the blending mode used to apply tint.
+     *
+     * @param tintMode A Porter-Duff blending mode
+     * @hide Pending finalization of supported Modes
+     */
+    public void setTintMode(Mode tintMode) {
+        if (mNinePatchState.mTintMode != tintMode) {
+            mNinePatchState.mTintMode = tintMode;
+            updateTintFilter();
+            invalidateSelf();
+        }
+    }
+
+    /**
+     * Ensures the tint filter is consistent with the current tint color and
+     * mode.
+     */
+    private void updateTintFilter() {
+        final ColorStateList tint = mNinePatchState.mTint;
+        final Mode tintMode = mNinePatchState.mTintMode;
+        if (tint != null && tintMode != null) {
+            if (mTintFilter == null) {
+                mTintFilter = new PorterDuffColorFilter(0, tintMode);
+            } else {
+                mTintFilter.setMode(tintMode);
+            }
+        } else {
+            mTintFilter = null;
+        }
+    }
+
     @Override
     public void setDither(boolean dither) {
         //noinspection PointlessBooleanExpression
@@ -302,6 +382,7 @@
             // Fast common case -- leave at default dither.
             return;
         }
+
         getPaint().setDither(dither);
         invalidateSelf();
     }
@@ -376,17 +457,14 @@
                 new NinePatch(bitmap, bitmap.getNinePatchChunk()), padding, opticalInsets, dither,
                 automirrored);
 
-        if (a.hasValue(com.android.internal.R.styleable.NinePatchDrawable_colorFilterColor)) {
-            final int colorFilterColor = a.getColor(
-                    com.android.internal.R.styleable.NinePatchDrawable_colorFilterColor, 0);
-            final int modeValue = a.getInt(
-                    com.android.internal.R.styleable.NinePatchDrawable_colorFilterMode,
-                    Mode.MULTIPLY.ordinal());
-            final Mode mode = Drawable.parseColorFilterMode(modeValue);
-            if (mode != null) {
-                // This will be applied to the paint by setNinePatchState().
-                ninePatchState.mColorFilter = new PorterDuffColorFilter(colorFilterColor, mode);
-            }
+        final int tintModeValue = a.getInt(
+                com.android.internal.R.styleable.NinePatchDrawable_tintMode, -1);
+        ninePatchState.mTintMode = Drawable.parseTintMode(tintModeValue, Mode.SRC_IN);
+        ninePatchState.mTint = a.getColorStateList(
+                com.android.internal.R.styleable.NinePatchDrawable_tint);
+        if (ninePatchState.mTint != null) {
+            final int color = ninePatchState.mTint.getColorForState(getState(), 0);
+            mTintFilter = new PorterDuffColorFilter(color, ninePatchState.mTintMode);
         }
 
         setNinePatchState(ninePatchState, r);
@@ -461,15 +539,38 @@
         return this;
     }
 
+    @Override
+    protected boolean onStateChange(int[] stateSet) {
+        final ColorStateList tint = mNinePatchState.mTint;
+        if (tint != null) {
+            final int newColor = tint.getColorForState(stateSet, 0);
+            final int oldColor = mTintFilter.getColor();
+            if (oldColor != newColor) {
+                mTintFilter.setColor(newColor);
+                invalidateSelf();
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean isStateful() {
+        final NinePatchState s = mNinePatchState;
+        return super.isStateful() || (s.mTint != null && s.mTint.isStateful());
+    }
+
     final static class NinePatchState extends ConstantState {
-        final NinePatch mNinePatch;
-        final Rect mPadding;
-        final Insets mOpticalInsets;
-        final boolean mDither;
+        NinePatch mNinePatch;
+        ColorStateList mTint;
+        Mode mTintMode = Mode.SRC_IN;
+        Rect mPadding;
+        Insets mOpticalInsets;
+        boolean mDither;
         int mChangingConfigurations;
         int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
         boolean mAutoMirrored;
-        ColorFilter mColorFilter;
 
         NinePatchState(NinePatch ninePatch, Rect padding) {
             this(ninePatch, padding, new Rect(), DEFAULT_DITHER, false);
@@ -491,16 +592,16 @@
         // Copy constructor
 
         NinePatchState(NinePatchState state) {
-            // Note we don't copy the nine patch because it is immutable.
+            // We don't deep-copy any fields because they are all immutable.
             mNinePatch = state.mNinePatch;
-            // Note we don't copy the padding because it is immutable.
+            mTint = state.mTint;
+            mTintMode = state.mTintMode;
             mPadding = state.mPadding;
             mOpticalInsets = state.mOpticalInsets;
             mDither = state.mDither;
             mChangingConfigurations = state.mChangingConfigurations;
             mTargetDensity = state.mTargetDensity;
             mAutoMirrored = state.mAutoMirrored;
-            mColorFilter = state.mColorFilter;
         }
 
         @Override
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index 93f2dc60..16de9f3 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -16,10 +16,18 @@
 
 package android.graphics.drawable;
 
-import android.graphics.*;
-import android.graphics.drawable.shapes.Shape;
+import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.Rect;
+import android.graphics.Shader;
+import android.graphics.drawable.shapes.Shape;
 import android.util.AttributeSet;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -28,22 +36,24 @@
 import java.io.IOException;
 
 /**
- * A Drawable object that draws primitive shapes. 
- * A ShapeDrawable takes a {@link android.graphics.drawable.shapes.Shape}
- * object and manages its presence on the screen. If no Shape is given, then
- * the ShapeDrawable will default to a 
- * {@link android.graphics.drawable.shapes.RectShape}.
- *
- * <p>This object can be defined in an XML file with the <code>&lt;shape></code> element.</p>
- *
- * <div class="special reference">
- * <h3>Developer Guides</h3>
- * <p>For more information about how to use ShapeDrawable, read the
- * <a href="{@docRoot}guide/topics/graphics/2d-graphics.html#shape-drawable">
- * Canvas and Drawables</a> document. For more information about defining a ShapeDrawable in
- * XML, read the
- * <a href="{@docRoot}guide/topics/resources/drawable-resource.html#Shape">Drawable Resources</a>
- * document.</p></div>
+ * A Drawable object that draws primitive shapes. A ShapeDrawable takes a
+ * {@link android.graphics.drawable.shapes.Shape} object and manages its
+ * presence on the screen. If no Shape is given, then the ShapeDrawable will
+ * default to a {@link android.graphics.drawable.shapes.RectShape}.
+ * <p>
+ * This object can be defined in an XML file with the <code>&lt;shape></code>
+ * element.
+ * </p>
+ * <div class="special reference"> <h3>Developer Guides</h3>
+ * <p>
+ * For more information about how to use ShapeDrawable, read the <a
+ * href="{@docRoot}guide/topics/graphics/2d-graphics.html#shape-drawable">
+ * Canvas and Drawables</a> document. For more information about defining a
+ * ShapeDrawable in XML, read the <a href="{@docRoot}
+ * guide/topics/resources/drawable-resource.html#Shape">Drawable Resources</a>
+ * document.
+ * </p>
+ * </div>
  *
  * @attr ref android.R.styleable#ShapeDrawablePadding_left
  * @attr ref android.R.styleable#ShapeDrawablePadding_top
@@ -55,6 +65,7 @@
  */
 public class ShapeDrawable extends Drawable {
     private ShapeState mShapeState;
+    private PorterDuffColorFilter mTintFilter;
     private boolean mMutated;
 
     /**
@@ -63,20 +74,25 @@
     public ShapeDrawable() {
         this((ShapeState) null);
     }
-    
+
     /**
      * Creates a ShapeDrawable with a specified Shape.
-     * 
+     *
      * @param s the Shape that this ShapeDrawable should be
      */
     public ShapeDrawable(Shape s) {
         this((ShapeState) null);
-        
+
         mShapeState.mShape = s;
     }
-    
+
     private ShapeDrawable(ShapeState state) {
         mShapeState = new ShapeState(state);
+
+        if (state != null && state.mTint != null) {
+            final int color = state.mTint.getColorForState(getState(), 0);
+            mTintFilter = new PorterDuffColorFilter(color, state.mTintMode);
+        }
     }
 
     /**
@@ -85,7 +101,7 @@
     public Shape getShape() {
         return mShapeState.mShape;
     }
-    
+
     /**
      * Sets the Shape of this ShapeDrawable.
      */
@@ -93,19 +109,19 @@
         mShapeState.mShape = s;
         updateShape();
     }
-    
+
     /**
-     * Sets a ShaderFactory to which requests for a 
+     * Sets a ShaderFactory to which requests for a
      * {@link android.graphics.Shader} object will be made.
-     * 
+     *
      * @param fact an instance of your ShaderFactory implementation
      */
     public void setShaderFactory(ShaderFactory fact) {
         mShapeState.mShaderFactory = fact;
     }
-    
+
     /**
-     * Returns the ShaderFactory used by this ShapeDrawable for requesting a 
+     * Returns the ShaderFactory used by this ShapeDrawable for requesting a
      * {@link android.graphics.Shader}.
      */
     public ShaderFactory getShaderFactory() {
@@ -118,14 +134,14 @@
     public Paint getPaint() {
         return mShapeState.mPaint;
     }
-    
+
     /**
      * Sets padding for the shape.
-     * 
-     * @param left    padding for the left side (in pixels)
-     * @param top     padding for the top (in pixels)
-     * @param right   padding for the right side (in pixels)
-     * @param bottom  padding for the bottom (in pixels)
+     *
+     * @param left padding for the left side (in pixels)
+     * @param top padding for the top (in pixels)
+     * @param right padding for the right side (in pixels)
+     * @param bottom padding for the bottom (in pixels)
      */
     public void setPadding(int left, int top, int right, int bottom) {
         if ((left | top | right | bottom) == 0) {
@@ -138,10 +154,10 @@
         }
         invalidateSelf();
     }
-    
+
     /**
-     * Sets padding for this shape, defined by a Rect object.
-     * Define the padding in the Rect object as: left, top, right, bottom.
+     * Sets padding for this shape, defined by a Rect object. Define the padding
+     * in the Rect object as: left, top, right, bottom.
      */
     public void setPadding(Rect padding) {
         if (padding == null) {
@@ -154,37 +170,37 @@
         }
         invalidateSelf();
     }
-    
+
     /**
      * Sets the intrinsic (default) width for this shape.
-     * 
+     *
      * @param width the intrinsic width (in pixels)
      */
     public void setIntrinsicWidth(int width) {
         mShapeState.mIntrinsicWidth = width;
         invalidateSelf();
     }
-    
+
     /**
      * Sets the intrinsic (default) height for this shape.
-     * 
+     *
      * @param height the intrinsic height (in pixels)
      */
     public void setIntrinsicHeight(int height) {
         mShapeState.mIntrinsicHeight = height;
         invalidateSelf();
     }
-    
+
     @Override
     public int getIntrinsicWidth() {
         return mShapeState.mIntrinsicWidth;
     }
-    
+
     @Override
     public int getIntrinsicHeight() {
         return mShapeState.mIntrinsicHeight;
     }
-    
+
     @Override
     public boolean getPadding(Rect padding) {
         if (mShapeState.mPadding != null) {
@@ -196,14 +212,14 @@
     }
 
     private static int modulateAlpha(int paintAlpha, int alpha) {
-        int scale = alpha + (alpha >>> 7);  // convert to 0..256
+        int scale = alpha + (alpha >>> 7); // convert to 0..256
         return paintAlpha * scale >>> 8;
     }
 
     /**
-     * Called from the drawable's draw() method after the canvas has been set
-     * to draw the shape at (0,0). Subclasses can override for special effects
-     * such as multiple layers, stroking, etc.
+     * Called from the drawable's draw() method after the canvas has been set to
+     * draw the shape at (0,0). Subclasses can override for special effects such
+     * as multiple layers, stroking, etc.
      */
     protected void onDraw(Shape shape, Canvas canvas, Paint paint) {
         shape.draw(canvas, paint);
@@ -211,23 +227,37 @@
 
     @Override
     public void draw(Canvas canvas) {
-        Rect r = getBounds();
-        Paint paint = mShapeState.mPaint;
+        final Rect r = getBounds();
+        final ShapeState state = mShapeState;
+        final Paint paint = state.mPaint;
 
-        int prevAlpha = paint.getAlpha();
-        paint.setAlpha(modulateAlpha(prevAlpha, mShapeState.mAlpha));
+        final int prevAlpha = paint.getAlpha();
+        paint.setAlpha(modulateAlpha(prevAlpha, state.mAlpha));
 
         // only draw shape if it may affect output
         if (paint.getAlpha() != 0 || paint.getXfermode() != null || paint.hasShadow) {
-            if (mShapeState.mShape != null) {
-                // need the save both for the translate, and for the (unknown) Shape
-                int count = canvas.save();
+            final boolean clearColorFilter;
+            if (mTintFilter != null && paint.getColorFilter() == null) {
+                paint.setColorFilter(mTintFilter);
+                clearColorFilter = true;
+            } else {
+                clearColorFilter = false;
+            }
+
+            if (state.mShape != null) {
+                // need the save both for the translate, and for the (unknown)
+                // Shape
+                final int count = canvas.save();
                 canvas.translate(r.left, r.top);
-                onDraw(mShapeState.mShape, canvas, paint);
+                onDraw(state.mShape, canvas, paint);
                 canvas.restoreToCount(count);
             } else {
                 canvas.drawRect(r, paint);
             }
+
+            if (clearColorFilter) {
+                paint.setColorFilter(null);
+            }
         }
 
         // restore
@@ -239,16 +269,17 @@
         return super.getChangingConfigurations()
                 | mShapeState.mChangingConfigurations;
     }
-    
+
     /**
      * Set the alpha level for this drawable [0..255]. Note that this drawable
      * also has a color in its paint, which has an alpha as well. These two
      * values are automatically combined during drawing. Thus if the color's
      * alpha is 75% (i.e. 192) and the drawable's alpha is 50% (i.e. 128), then
-     * the combined alpha that will be used during drawing will be 37.5%
-     * (i.e. 96).
+     * the combined alpha that will be used during drawing will be 37.5% (i.e.
+     * 96).
      */
-    @Override public void setAlpha(int alpha) {
+    @Override
+    public void setAlpha(int alpha) {
         mShapeState.mAlpha = alpha;
         invalidateSelf();
     }
@@ -258,12 +289,81 @@
         return mShapeState.mAlpha;
     }
 
+    /**
+     * Specifies a tint for this drawable.
+     * <p>
+     * Setting a color filter via {@link #setColorFilter(ColorFilter)} overrides
+     * tint.
+     *
+     * @param tint Color state list to use for tinting this drawable, or null to
+     *            clear the tint
+     */
+    public void setTint(ColorStateList tint) {
+        if (mShapeState.mTint != tint) {
+            mShapeState.mTint = tint;
+            updateTintFilter();
+            invalidateSelf();
+        }
+    }
+
+    /**
+     * Returns the tint color for this drawable.
+     *
+     * @return Color state list to use for tinting this drawable, or null if
+     *         none set
+     */
+    public ColorStateList getTint() {
+        return mShapeState.mTint;
+    }
+
+    /**
+     * Specifies the blending mode used to apply tint.
+     *
+     * @param tintMode A Porter-Duff blending mode
+     * @hide Pending finalization of supported Modes
+     */
+    public void setTintMode(Mode tintMode) {
+        if (mShapeState.mTintMode != tintMode) {
+            mShapeState.mTintMode = tintMode;
+            updateTintFilter();
+            invalidateSelf();
+        }
+    }
+
+    /**
+     * Ensures the tint filter is consistent with the current tint color and
+     * mode.
+     */
+    private void updateTintFilter() {
+        final ColorStateList tint = mShapeState.mTint;
+        final Mode tintMode = mShapeState.mTintMode;
+        if (tint != null && tintMode != null) {
+            if (mTintFilter == null) {
+                mTintFilter = new PorterDuffColorFilter(0, tintMode);
+            } else {
+                mTintFilter.setMode(tintMode);
+            }
+        } else {
+            mTintFilter = null;
+        }
+    }
+
+    /**
+     * Returns the blending mode used to apply tint.
+     *
+     * @return The Porter-Duff blending mode used to apply tint.
+     * @hide Pending finalization of supported Modes
+     */
+    public Mode getTintMode() {
+        return mShapeState.mTintMode;
+    }
+
     @Override
     public void setColorFilter(ColorFilter cf) {
         mShapeState.mPaint.setColorFilter(cf);
         invalidateSelf();
     }
-    
+
     @Override
     public int getOpacity() {
         if (mShapeState.mShape == null) {
@@ -294,9 +394,31 @@
         updateShape();
     }
 
+    @Override
+    protected boolean onStateChange(int[] stateSet) {
+        final ColorStateList tint = mShapeState.mTint;
+        if (tint != null) {
+            final int newColor = tint.getColorForState(stateSet, 0);
+            final int oldColor = mTintFilter.getColor();
+            if (oldColor != newColor) {
+                mTintFilter.setColor(newColor);
+                invalidateSelf();
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean isStateful() {
+        final ShapeState s = mShapeState;
+        return super.isStateful() || (s.mTint != null && s.mTint.isStateful());
+    }
+
     /**
-     * Subclasses override this to parse custom subelements.
-     * If you handle it, return true, else return <em>super.inflateTag(...)</em>.
+     * Subclasses override this to parse custom subelements. If you handle it,
+     * return true, else return <em>super.inflateTag(...)</em>.
      */
     protected boolean inflateTag(String name, Resources r, XmlPullParser parser,
             AttributeSet attrs) {
@@ -322,7 +444,7 @@
 
     @Override
     public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs)
-                        throws XmlPullParserException, IOException {
+            throws XmlPullParserException, IOException {
         super.inflate(r, parser, attrs);
 
         TypedArray a = r.obtainAttributes(attrs, com.android.internal.R.styleable.ShapeDrawable);
@@ -343,12 +465,12 @@
 
         int type;
         final int outerDepth = parser.getDepth();
-        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
-               && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
             if (type != XmlPullParser.START_TAG) {
                 continue;
             }
-            
+
             final String name = parser.getName();
             // call our subclass
             if (!inflateTag(name, r, parser, attrs)) {
@@ -371,7 +493,7 @@
         }
         invalidateSelf();
     }
-    
+
     @Override
     public ConstantState getConstantState() {
         mShapeState.mChangingConfigurations = getChangingConfigurations();
@@ -408,16 +530,20 @@
         int mChangingConfigurations;
         Paint mPaint;
         Shape mShape;
+        ColorStateList mTint;
+        Mode mTintMode = Mode.SRC_IN;
         Rect mPadding;
         int mIntrinsicWidth;
         int mIntrinsicHeight;
         int mAlpha = 255;
         ShaderFactory mShaderFactory;
-        
+
         ShapeState(ShapeState orig) {
             if (orig != null) {
                 mPaint = orig.mPaint;
                 mShape = orig.mShape;
+                mTint = orig.mTint;
+                mTintMode = orig.mTintMode;
                 mPadding = orig.mPadding;
                 mIntrinsicWidth = orig.mIntrinsicWidth;
                 mIntrinsicHeight = orig.mIntrinsicHeight;
@@ -427,48 +553,45 @@
                 mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
             }
         }
-        
+
         @Override
         public Drawable newDrawable() {
             return new ShapeDrawable(this);
         }
-        
+
         @Override
         public Drawable newDrawable(Resources res) {
             return new ShapeDrawable(this);
         }
-        
+
         @Override
         public int getChangingConfigurations() {
             return mChangingConfigurations;
         }
     }
-    
+
     /**
      * Base class defines a factory object that is called each time the drawable
      * is resized (has a new width or height). Its resize() method returns a
-     * corresponding shader, or null.
-     * Implement this class if you'd like your ShapeDrawable to use a special
-     * {@link android.graphics.Shader}, such as a 
-     * {@link android.graphics.LinearGradient}. 
-     * 
+     * corresponding shader, or null. Implement this class if you'd like your
+     * ShapeDrawable to use a special {@link android.graphics.Shader}, such as a
+     * {@link android.graphics.LinearGradient}.
      */
     public static abstract class ShaderFactory {
         /**
-         * Returns the Shader to be drawn when a Drawable is drawn.
-         * The dimensions of the Drawable are passed because they may be needed
-         * to adjust how the Shader is configured for drawing.
-         * This is called by ShapeDrawable.setShape().
-         * 
-         * @param width  the width of the Drawable being drawn
+         * Returns the Shader to be drawn when a Drawable is drawn. The
+         * dimensions of the Drawable are passed because they may be needed to
+         * adjust how the Shader is configured for drawing. This is called by
+         * ShapeDrawable.setShape().
+         *
+         * @param width the width of the Drawable being drawn
          * @param height the heigh of the Drawable being drawn
-         * @return       the Shader to be drawn
+         * @return the Shader to be drawn
          */
         public abstract Shader resize(int width, int height);
     }
-    
+
     // other subclass could wack the Shader's localmatrix based on the
     // resize params (e.g. scaletofit, etc.). This could be used to scale
     // a bitmap to fill the bounds without needing any other special casing.
 }
-
diff --git a/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java b/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
index a21f1e0..6fbcb53 100644
--- a/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
+++ b/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
@@ -112,7 +112,7 @@
     }
 
     @Override
-    public boolean onStateChange(int[] stateSet) {
+    protected boolean onStateChange(int[] stateSet) {
         final ColorStateList stateList = mState.mColorStateList;
         if (stateList != null && mRipplePaint != null) {
             final int newColor = stateList.getColorForState(stateSet, 0);
diff --git a/include/android_runtime/AndroidRuntime.h b/include/android_runtime/AndroidRuntime.h
index 0b3ce9a..649f4c3 100644
--- a/include/android_runtime/AndroidRuntime.h
+++ b/include/android_runtime/AndroidRuntime.h
@@ -115,7 +115,7 @@
 
 private:
     static int startReg(JNIEnv* env);
-    void parseExtraOpts(char* extraOptsBuf);
+    void parseExtraOpts(char* extraOptsBuf, const char* quotingArg);
     int startVm(JavaVM** pJavaVM, JNIEnv** pEnv);
 
     Vector<JavaVMOption> mOptions;
diff --git a/libs/androidfw/BackupData.cpp b/libs/androidfw/BackupData.cpp
index 4e3b522..1a5c55c 100644
--- a/libs/androidfw/BackupData.cpp
+++ b/libs/androidfw/BackupData.cpp
@@ -59,9 +59,10 @@
 BackupDataWriter::BackupDataWriter(int fd)
     :m_fd(fd),
      m_status(NO_ERROR),
-     m_pos(0),
      m_entityCount(0)
 {
+    m_pos = (ssize_t) lseek(fd, 0, SEEK_CUR);
+    if (DEBUG) ALOGI("BackupDataWriter(%d) @ %ld", fd, (long)m_pos);
 }
 
 BackupDataWriter::~BackupDataWriter()
@@ -184,10 +185,11 @@
     :m_fd(fd),
      m_done(false),
      m_status(NO_ERROR),
-     m_pos(0),
      m_entityCount(0)
 {
     memset(&m_header, 0, sizeof(m_header));
+    m_pos = (ssize_t) lseek(fd, 0, SEEK_CUR);
+    if (DEBUG) ALOGI("BackupDataReader(%d) @ %ld", fd, (long)m_pos);
 }
 
 BackupDataReader::~BackupDataReader()
diff --git a/libs/androidfw/BackupHelpers.cpp b/libs/androidfw/BackupHelpers.cpp
index b8d3f48..302fbf6 100644
--- a/libs/androidfw/BackupHelpers.cpp
+++ b/libs/androidfw/BackupHelpers.cpp
@@ -1083,7 +1083,7 @@
     }
 
     if (readSnapshot.size() != 4) {
-        fprintf(stderr, "readSnapshot should be length 4 is %d\n", readSnapshot.size());
+        fprintf(stderr, "readSnapshot should be length 4 is %zu\n", readSnapshot.size());
         return 1;
     }
 
@@ -1095,8 +1095,8 @@
         if (name != filenames[i] || states[i].modTime_sec != state.modTime_sec
                 || states[i].modTime_nsec != state.modTime_nsec || states[i].mode != state.mode
                 || states[i].size != state.size || states[i].crc32 != states[i].crc32) {
-            fprintf(stderr, "state %d expected={%d/%d, 0x%08x, %04o, 0x%08x, %3d} '%s'\n"
-                            "          actual={%d/%d, 0x%08x, %04o, 0x%08x, %3d} '%s'\n", i,
+            fprintf(stderr, "state %zu expected={%d/%d, 0x%08x, %04o, 0x%08x, %3d} '%s'\n"
+                            "          actual={%d/%d, 0x%08x, %04o, 0x%08x, %3zu} '%s'\n", i,
                     states[i].modTime_sec, states[i].modTime_nsec, states[i].mode, states[i].size,
                     states[i].crc32, name.length(), filenames[i].string(),
                     state.modTime_sec, state.modTime_nsec, state.mode, state.size, state.crc32,
@@ -1230,7 +1230,7 @@
         goto finished;
     }
     if ((int)actualSize != bufSize) {
-        fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08x\n", bufSize,
+        fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08zx\n", bufSize,
                 actualSize);
         err = EINVAL;
         goto finished;
diff --git a/libs/hwui/AmbientShadow.cpp b/libs/hwui/AmbientShadow.cpp
index 1f5d26c..4935b34 100644
--- a/libs/hwui/AmbientShadow.cpp
+++ b/libs/hwui/AmbientShadow.cpp
@@ -21,6 +21,7 @@
 #include <utils/Vector.h>
 
 #include "AmbientShadow.h"
+#include "ShadowTessellator.h"
 #include "Vertex.h"
 
 namespace android {
@@ -34,9 +35,7 @@
  *                  array.
  * @param vertexCount The length of caster's polygon in terms of number of
  *                    vertices.
- * @param rays The number of rays shooting out from the centroid.
- * @param layers The number of rings outside the polygon.
- * @param strength The darkness of the shadow, the higher, the darker.
+ * @param centroid3d The centroid of the shadow caster.
  * @param heightFactor The factor showing the higher the object, the lighter the
  *                     shadow.
  * @param geomFactor The factor scaling the geometry expansion along the normal.
@@ -45,21 +44,18 @@
  *               triangle strips mode.
  */
 void AmbientShadow::createAmbientShadow(const Vector3* vertices, int vertexCount,
-        int rays, int layers, float strength, float heightFactor, float geomFactor,
+        const Vector3& centroid3d, float heightFactor, float geomFactor,
         VertexBuffer& shadowVertexBuffer) {
-
+    const int rays = SHADOW_RAY_COUNT;
+    const int layers = SHADOW_LAYER_COUNT;
     // Validate the inputs.
-    if (strength <= 0 || heightFactor <= 0 || layers <= 0 || rays <= 0
+    if (vertexCount < 3 || heightFactor <= 0 || layers <= 0 || rays <= 0
         || geomFactor <= 0) {
 #if DEBUG_SHADOW
         ALOGE("Invalid input for createAmbientShadow(), early return!");
 #endif
         return;
     }
-    int rings = layers + 1;
-    int size = rays * rings;
-    Vector2 centroid;
-    calculatePolygonCentroid(vertices, vertexCount, centroid);
 
     Vector<Vector2> dir; // TODO: use C++11 unique_ptr
     dir.setCapacity(rays);
@@ -75,7 +71,7 @@
         int edgeIndex;
         float edgeFraction;
         float rayDistance;
-        calculateIntersection(vertices, vertexCount, centroid, dir[i], edgeIndex,
+        calculateIntersection(vertices, vertexCount, centroid3d, dir[i], edgeIndex,
                 edgeFraction, rayDistance);
         rayDist[i] = rayDistance;
         if (edgeIndex < 0 || edgeIndex >= vertexCount) {
@@ -91,8 +87,7 @@
 
     // The output buffer length basically is roughly rays * layers, but since we
     // need triangle strips, so we need to duplicate vertices to accomplish that.
-    const int shadowVertexCount = (2 + rays + ((layers) * 2 * (rays + 1)));
-    AlphaVertex* shadowVertices = shadowVertexBuffer.alloc<AlphaVertex>(shadowVertexCount);
+    AlphaVertex* shadowVertices = shadowVertexBuffer.alloc<AlphaVertex>(SHADOW_VERTEX_COUNT);
 
     // Calculate the vertex of the shadows.
     //
@@ -101,110 +96,45 @@
     // calculate the normal N, which should be perpendicular to the edge of the
     // polygon (represented by the neighbor intersection points) .
     // Shadow's vertices will be generated as : P + N * scale.
-    int currentIndex = 0;
-    for (int r = 0; r < layers; r++) {
-        int firstInLayer = currentIndex;
-        for (int i = 0; i < rays; i++) {
+    int currentVertexIndex = 0;
+    for (int layerIndex = 0; layerIndex <= layers; layerIndex++) {
+        for (int rayIndex = 0; rayIndex < rays; rayIndex++) {
 
             Vector2 normal(1.0f, 0.0f);
-            calculateNormal(rays, i, dir.array(), rayDist, normal);
+            calculateNormal(rays, rayIndex, dir.array(), rayDist, normal);
 
-            float opacity = strength * (0.5f) / (1 + rayHeight[i] / heightFactor);
+            float opacity = 1.0 / (1 + rayHeight[rayIndex] / heightFactor);
 
             // The vertex should be start from rayDist[i] then scale the
             // normalizeNormal!
-            Vector2 intersection = dir[i] * rayDist[i] + centroid;
+            Vector2 intersection = dir[rayIndex] * rayDist[rayIndex] +
+                    Vector2(centroid3d.x, centroid3d.y);
 
-            // Use 2 rings' vertices to complete one layer's strip
-            for (int j = r; j < (r + 2); j++) {
-                float jf = j / (float)(rings - 1);
-
-                float expansionDist = rayHeight[i] / heightFactor * geomFactor * jf;
-                AlphaVertex::set(&shadowVertices[currentIndex],
-                        intersection.x + normal.x * expansionDist,
-                        intersection.y + normal.y * expansionDist,
-                        (1 - jf) * opacity);
-                currentIndex++;
-            }
+            float layerRatio = layerIndex / (float)(layers);
+            // The higher the intersection is, the further the ambient shadow expanded.
+            float expansionDist = rayHeight[rayIndex] / heightFactor *
+                    geomFactor * (1 - layerRatio);
+            AlphaVertex::set(&shadowVertices[currentVertexIndex++],
+                    intersection.x + normal.x * expansionDist,
+                    intersection.y + normal.y * expansionDist,
+                    layerRatio * opacity);
         }
 
-        // From one layer to the next, we need to duplicate the vertex to
-        // continue as a single strip.
-        shadowVertices[currentIndex] = shadowVertices[firstInLayer];
-        currentIndex++;
-        shadowVertices[currentIndex] = shadowVertices[firstInLayer + 1];
-        currentIndex++;
     }
+    float centroidAlpha = 1.0 / (1 + centroid3d.z / heightFactor);
+    AlphaVertex::set(&shadowVertices[currentVertexIndex++],
+            centroid3d.x, centroid3d.y, centroidAlpha);
 
-    // After all rings are done, we need to jump into the polygon.
-    // In order to keep everything in a strip, we need to duplicate the last one
-    // of the rings and the first one inside the polygon.
-    int lastInRings = currentIndex - 1;
-    shadowVertices[currentIndex] = shadowVertices[lastInRings];
-    currentIndex++;
-
-    // We skip one and fill it back after we finish the internal triangles.
-    currentIndex++;
-    int firstInternal = currentIndex;
-
-    // Combine the internal area of the polygon into a triangle strip, too.
-    // The basic idea is zig zag between the intersection points.
-    // 0 -> (n - 1) -> 1 -> (n - 2) ...
-    for (int k = 0; k < rays; k++) {
-        int  i = k / 2;
-        if ((k & 1) == 1) { // traverse the inside in a zig zag pattern for strips
-            i = rays - i - 1;
-        }
-        float cast = rayDist[i] * (1 + rayHeight[i] / heightFactor);
-        float opacity = strength * (0.5f) / (1 + rayHeight[i] / heightFactor);
-        float t = rayDist[i];
-
-        AlphaVertex::set(&shadowVertices[currentIndex], dir[i].x * t + centroid.x,
-                dir[i].y * t + centroid.y, opacity);
-        currentIndex++;
-    }
-
-    currentIndex = firstInternal - 1;
-    shadowVertices[currentIndex] = shadowVertices[firstInternal];
-}
-
-/**
- * Calculate the centroid of a given polygon.
- *
- * @param vertices The shadow caster's polygon, which is represented in a
- *                 straight Vector3 array.
- * @param vertexCount The length of caster's polygon in terms of number of vertices.
- *
- * @param centroid Return the centroid of the polygon.
- */
-void AmbientShadow::calculatePolygonCentroid(const Vector3* vertices, int vertexCount,
-        Vector2& centroid) {
-    float sumx = 0;
-    float sumy = 0;
-    int p1 = vertexCount - 1;
-    float area = 0;
-    for (int p2 = 0; p2 < vertexCount; p2++) {
-        float x1 = vertices[p1].x;
-        float y1 = vertices[p1].y;
-        float x2 = vertices[p2].x;
-        float y2 = vertices[p2].y;
-        float a = (x1 * y2 - x2 * y1);
-        sumx += (x1 + x2) * a;
-        sumy += (y1 + y2) * a;
-        area += a;
-        p1 = p2;
-    }
-
-    if (area == 0) {
 #if DEBUG_SHADOW
-        ALOGE("Area is 0!");
-#endif
-        centroid.x = vertices[0].x;
-        centroid.y = vertices[0].y;
-    } else {
-        centroid.x = sumx / (3 * area);
-        centroid.y = sumy / (3 * area);
+    if (currentVertexIndex != SHADOW_VERTEX_COUNT) {
+        ALOGE("number of vertex generated for ambient shadow is wrong! "
+              "current: %d , expected: %d", currentVertexIndex, SHADOW_VERTEX_COUNT);
     }
+    for (int i = 0; i < SHADOW_VERTEX_COUNT; i++) {
+        ALOGD("ambient shadow value: i %d, (x:%f, y:%f, a:%f)", i, shadowVertices[i].x,
+                shadowVertices[i].y, shadowVertices[i].alpha);
+    }
+#endif
 }
 
 /**
@@ -238,7 +168,7 @@
  * @param outRayDist Return the ray distance from centroid to the intersection.
  */
 void AmbientShadow::calculateIntersection(const Vector3* vertices, int vertexCount,
-        const Vector2& start, const Vector2& dir, int& outEdgeIndex,
+        const Vector3& start, const Vector2& dir, int& outEdgeIndex,
         float& outEdgeFraction, float& outRayDist) {
     float startX = start.x;
     float startY = start.y;
diff --git a/libs/hwui/AmbientShadow.h b/libs/hwui/AmbientShadow.h
index 079bdb7..20d1384 100644
--- a/libs/hwui/AmbientShadow.h
+++ b/libs/hwui/AmbientShadow.h
@@ -34,17 +34,15 @@
  */
 class AmbientShadow {
 public:
-    static void createAmbientShadow(const Vector3* poly, int polyLength, int rays,
-            int layers, float strength, float heightFactor, float geomFactor,
+    static void createAmbientShadow(const Vector3* poly, int polyLength,
+            const Vector3& centroid3d, float heightFactor, float geomFactor,
             VertexBuffer& shadowVertexBuffer);
 
 private:
-    static void calculatePolygonCentroid(const Vector3* poly, int len, Vector2& centroid);
-
     static void calculateRayDirections(int rays, Vector2* dir);
 
     static void calculateIntersection(const Vector3* poly, int nbVertices,
-            const Vector2& start, const Vector2& dir, int& outEdgeIndex,
+            const Vector3& start, const Vector2& dir, int& outEdgeIndex,
             float& outEdgeFraction, float& outRayDist);
 
     static void calculateNormal(int rays, int currentRayIndex, const Vector2* dir,
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 495ad19..2cc7a84 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -61,12 +61,7 @@
 	LOCAL_C_INCLUDES += \
 		$(JNI_H_INCLUDE) \
 		$(LOCAL_PATH)/../../include/utils \
-		external/skia/include/core \
-		external/skia/include/effects \
-		external/skia/include/images \
-		external/skia/src/core \
-		external/skia/src/ports \
-		external/skia/include/utils
+		external/skia/src/core
 
 	LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER -DEGL_EGLEXT_PROTOTYPES -DGL_GLEXT_PROTOTYPES
 	LOCAL_CFLAGS += -Wno-unused-parameter
diff --git a/libs/hwui/AssetAtlas.cpp b/libs/hwui/AssetAtlas.cpp
index fddfe90..fc86e4f 100644
--- a/libs/hwui/AssetAtlas.cpp
+++ b/libs/hwui/AssetAtlas.cpp
@@ -28,7 +28,7 @@
 // Lifecycle
 ///////////////////////////////////////////////////////////////////////////////
 
-void AssetAtlas::init(sp<GraphicBuffer> buffer, int* map, int count) {
+void AssetAtlas::init(sp<GraphicBuffer> buffer, int64_t* map, int count) {
     if (mImage) {
         return;
     }
@@ -108,14 +108,19 @@
 /**
  * TODO: This method does not take the rotation flag into account
  */
-void AssetAtlas::createEntries(Caches& caches, int* map, int count) {
+void AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) {
     const float width = float(mTexture->width);
     const float height = float(mTexture->height);
 
     for (int i = 0; i < count; ) {
-        SkBitmap* bitmap = (SkBitmap*) map[i++];
-        int x = map[i++];
-        int y = map[i++];
+        SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(map[i++]);
+        // NOTE: We're converting from 64 bit signed values to 32 bit
+        // signed values. This is guaranteed to be safe because the "x"
+        // and "y" coordinate values are guaranteed to be representable
+        // with 32 bits. The array is 64 bits wide so that it can carry
+        // pointers on 64 bit architectures.
+        const int x = static_cast<int>(map[i++]);
+        const int y = static_cast<int>(map[i++]);
         bool rotated = map[i++] > 0;
 
         // Bitmaps should never be null, we're just extra paranoid
diff --git a/libs/hwui/AssetAtlas.h b/libs/hwui/AssetAtlas.h
index 57c8a60..2ec556e 100644
--- a/libs/hwui/AssetAtlas.h
+++ b/libs/hwui/AssetAtlas.h
@@ -121,7 +121,7 @@
      * initialized. To re-initialize the atlas, you must
      * first call terminate().
      */
-    ANDROID_API void init(sp<GraphicBuffer> buffer, int* map, int count);
+    ANDROID_API void init(sp<GraphicBuffer> buffer, int64_t* map, int count);
 
     /**
      * Destroys the atlas texture. This object can be
@@ -176,7 +176,7 @@
     }
 
 private:
-    void createEntries(Caches& caches, int* map, int count);
+    void createEntries(Caches& caches, int64_t* map, int count);
 
     Texture* mTexture;
     Image* mImage;
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 21cf658..1d58d96 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -23,6 +23,7 @@
 #include "DisplayListRenderer.h"
 #include "Properties.h"
 #include "LayerRenderer.h"
+#include "ShadowTessellator.h"
 
 namespace android {
 
@@ -86,7 +87,7 @@
 
     mRegionMesh = NULL;
     mMeshIndices = 0;
-
+    mShadowStripsIndices = 0;
     blend = false;
     lastSrcMode = GL_ZERO;
     lastDstMode = GL_ZERO;
@@ -223,6 +224,9 @@
     mMeshIndices = 0;
     mRegionMesh = NULL;
 
+    glDeleteBuffers(1, &mShadowStripsIndices);
+    mShadowStripsIndices = 0;
+
     fboCache.clear();
 
     programCache.clear();
@@ -404,7 +408,7 @@
     return false;
 }
 
-bool Caches::bindIndicesBuffer(const GLuint buffer) {
+bool Caches::bindIndicesBufferInternal(const GLuint buffer) {
     if (mCurrentIndicesBuffer != buffer) {
         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
         mCurrentIndicesBuffer = buffer;
@@ -413,7 +417,7 @@
     return false;
 }
 
-bool Caches::bindIndicesBuffer() {
+bool Caches::bindQuadIndicesBuffer() {
     if (!mMeshIndices) {
         uint16_t* regionIndices = new uint16_t[gMaxNumberOfQuads * 6];
         for (uint32_t i = 0; i < gMaxNumberOfQuads; i++) {
@@ -428,7 +432,7 @@
         }
 
         glGenBuffers(1, &mMeshIndices);
-        bool force = bindIndicesBuffer(mMeshIndices);
+        bool force = bindIndicesBufferInternal(mMeshIndices);
         glBufferData(GL_ELEMENT_ARRAY_BUFFER, gMaxNumberOfQuads * 6 * sizeof(uint16_t),
                 regionIndices, GL_STATIC_DRAW);
 
@@ -436,7 +440,23 @@
         return force;
     }
 
-    return bindIndicesBuffer(mMeshIndices);
+    return bindIndicesBufferInternal(mMeshIndices);
+}
+
+bool Caches::bindShadowIndicesBuffer() {
+    if (!mShadowStripsIndices) {
+        uint16_t* shadowIndices = new uint16_t[SHADOW_INDEX_COUNT];
+        ShadowTessellator::generateShadowIndices(shadowIndices);
+        glGenBuffers(1, &mShadowStripsIndices);
+        bool force = bindIndicesBufferInternal(mShadowStripsIndices);
+        glBufferData(GL_ELEMENT_ARRAY_BUFFER, SHADOW_INDEX_COUNT * sizeof(uint16_t),
+            shadowIndices, GL_STATIC_DRAW);
+
+        delete[] shadowIndices;
+        return force;
+    }
+
+    return bindIndicesBufferInternal(mShadowStripsIndices);
 }
 
 bool Caches::unbindIndicesBuffer() {
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 2cc15cc..8c0c508 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -190,8 +190,8 @@
      * Binds a global indices buffer that can draw up to
      * gMaxNumberOfQuads quads.
      */
-    bool bindIndicesBuffer();
-    bool bindIndicesBuffer(const GLuint buffer);
+    bool bindQuadIndicesBuffer();
+    bool bindShadowIndicesBuffer();
     bool unbindIndicesBuffer();
 
     /**
@@ -381,6 +381,8 @@
     void initConstraints();
     void initStaticProperties();
 
+    bool bindIndicesBufferInternal(const GLuint buffer);
+
     static void eventMarkNull(GLsizei length, const GLchar* marker) { }
     static void startMarkNull(GLsizei length, const GLchar* marker) { }
     static void endMarkNull() { }
@@ -417,6 +419,7 @@
 
     // Global index buffer
     GLuint mMeshIndices;
+    GLuint mShadowStripsIndices;
 
     mutable Mutex mGarbageLock;
     Vector<Layer*> mLayerGarbage;
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index efb1298..7a2e288 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -34,21 +34,23 @@
     mWidth = mLayer->layer.getWidth();
     mHeight = mLayer->layer.getHeight();
     mBlend = mLayer->isBlend();
-    mColorFilter = mLayer->getColorFilter();
+    mColorFilter = SkSafeRef(mLayer->getColorFilter());
     mAlpha = mLayer->getAlpha();
     mMode = mLayer->getMode();
     mDirtyRect.setEmpty();
 }
 
 DeferredLayerUpdater::~DeferredLayerUpdater() {
-    setColorFilter(NULL);
+    SkSafeUnref(mColorFilter);
     if (mLayer) {
         mCaches.resourceCache.decrementRefcount(mLayer);
     }
     delete mRenderer;
 }
 
-void DeferredLayerUpdater::setColorFilter(SkColorFilter* colorFilter) {
+void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
+    OpenGLRenderer::getAlphaAndModeDirect(paint, &mAlpha, &mMode);
+    SkColorFilter* colorFilter = (paint) ? paint->getColorFilter() : NULL;
     SkRefCnt_SafeAssign(mColorFilter, colorFilter);
 }
 
@@ -110,6 +112,15 @@
             frameNumber = newFrameNumber;
             dropCounter++;
         }
+
+        bool forceFilter = false;
+        sp<GraphicBuffer> buffer = mSurfaceTexture->getCurrentBuffer();
+        if (buffer != NULL) {
+            // force filtration if buffer size != layer size
+            forceFilter = mWidth != buffer->getWidth()
+                    || mHeight != buffer->getHeight();
+        }
+
         #if DEBUG_RENDERER
         if (dropCounter > 0) {
             RENDERER_LOGD("Dropped %d frames on texture layer update", dropCounter);
@@ -118,8 +129,8 @@
         mSurfaceTexture->getTransformMatrix(transform);
         GLenum renderTarget = mSurfaceTexture->getCurrentTextureTarget();
 
-        LayerRenderer::updateTextureLayer(mLayer, mWidth, mHeight, !mBlend,
-                renderTarget, transform);
+        LayerRenderer::updateTextureLayer(mLayer, mWidth, mHeight,
+                !mBlend, forceFilter, renderTarget, transform);
     }
 }
 
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 624db2c..65f225c 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -75,11 +75,7 @@
     ANDROID_API void setDisplayList(DisplayList* displayList,
                 int left, int top, int right, int bottom);
 
-    ANDROID_API void setPaint(const SkPaint* paint) {
-        OpenGLRenderer::getAlphaAndModeDirect(paint, &mAlpha, &mMode);
-    }
-
-    ANDROID_API void setColorFilter(SkColorFilter* colorFilter);
+    ANDROID_API void setPaint(const SkPaint* paint);
 
     ANDROID_API bool apply();
 
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 6144f3d..0f76486 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -48,179 +48,10 @@
     fflush(file);
 }
 
-DisplayList::DisplayList(const DisplayListRenderer& recorder) :
-    mDestroyed(false), mTransformMatrix(NULL), mTransformCamera(NULL), mTransformMatrix3D(NULL),
-    mStaticMatrix(NULL), mAnimationMatrix(NULL) {
+DisplayList::DisplayList() :
+        mDisplayListData(0), mDestroyed(false), mTransformMatrix(NULL), mTransformCamera(NULL),
+        mTransformMatrix3D(NULL), mStaticMatrix(NULL), mAnimationMatrix(NULL) {
 
-    initFromDisplayListRenderer(recorder);
-}
-
-DisplayList::~DisplayList() {
-    mDestroyed = true;
-    clearResources();
-}
-
-void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) {
-    if (displayList) {
-        DISPLAY_LIST_LOGD("Deferring display list destruction");
-        Caches::getInstance().deleteDisplayListDeferred(displayList);
-    }
-}
-
-void DisplayList::clearResources() {
-    mDisplayListData = NULL;
-
-    delete mTransformMatrix;
-    delete mTransformCamera;
-    delete mTransformMatrix3D;
-    delete mStaticMatrix;
-    delete mAnimationMatrix;
-
-    mTransformMatrix = NULL;
-    mTransformCamera = NULL;
-    mTransformMatrix3D = NULL;
-    mStaticMatrix = NULL;
-    mAnimationMatrix = NULL;
-
-    Caches& caches = Caches::getInstance();
-    caches.unregisterFunctors(mFunctorCount);
-    caches.resourceCache.lock();
-
-    for (size_t i = 0; i < mBitmapResources.size(); i++) {
-        caches.resourceCache.decrementRefcountLocked(mBitmapResources.itemAt(i));
-    }
-
-    for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) {
-        const SkBitmap* bitmap = mOwnedBitmapResources.itemAt(i);
-        caches.resourceCache.decrementRefcountLocked(bitmap);
-        caches.resourceCache.destructorLocked(bitmap);
-    }
-
-    for (size_t i = 0; i < mPatchResources.size(); i++) {
-        caches.resourceCache.decrementRefcountLocked(mPatchResources.itemAt(i));
-    }
-
-    for (size_t i = 0; i < mShaders.size(); i++) {
-        caches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i));
-        caches.resourceCache.destructorLocked(mShaders.itemAt(i));
-    }
-
-    for (size_t i = 0; i < mSourcePaths.size(); i++) {
-        caches.resourceCache.decrementRefcountLocked(mSourcePaths.itemAt(i));
-    }
-
-    for (size_t i = 0; i < mLayers.size(); i++) {
-        caches.resourceCache.decrementRefcountLocked(mLayers.itemAt(i));
-    }
-
-    caches.resourceCache.unlock();
-
-    for (size_t i = 0; i < mPaints.size(); i++) {
-        delete mPaints.itemAt(i);
-    }
-
-    for (size_t i = 0; i < mRegions.size(); i++) {
-        delete mRegions.itemAt(i);
-    }
-
-    for (size_t i = 0; i < mPaths.size(); i++) {
-        delete mPaths.itemAt(i);
-    }
-
-    for (size_t i = 0; i < mMatrices.size(); i++) {
-        delete mMatrices.itemAt(i);
-    }
-
-    mBitmapResources.clear();
-    mOwnedBitmapResources.clear();
-    mPatchResources.clear();
-    mShaders.clear();
-    mSourcePaths.clear();
-    mPaints.clear();
-    mRegions.clear();
-    mPaths.clear();
-    mMatrices.clear();
-    mLayers.clear();
-}
-
-void DisplayList::reset() {
-    clearResources();
-    init();
-}
-
-void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing) {
-    if (reusing) {
-        // re-using display list - clear out previous allocations
-        clearResources();
-    }
-
-    init();
-
-    mDisplayListData = recorder.getDisplayListData();
-    mSize = mDisplayListData->allocator.usedSize();
-
-    if (mSize == 0) {
-        return;
-    }
-
-    mFunctorCount = recorder.getFunctorCount();
-
-    Caches& caches = Caches::getInstance();
-    caches.registerFunctors(mFunctorCount);
-    caches.resourceCache.lock();
-
-    const Vector<const SkBitmap*>& bitmapResources = recorder.getBitmapResources();
-    for (size_t i = 0; i < bitmapResources.size(); i++) {
-        const SkBitmap* resource = bitmapResources.itemAt(i);
-        mBitmapResources.add(resource);
-        caches.resourceCache.incrementRefcountLocked(resource);
-    }
-
-    const Vector<const SkBitmap*>& ownedBitmapResources = recorder.getOwnedBitmapResources();
-    for (size_t i = 0; i < ownedBitmapResources.size(); i++) {
-        const SkBitmap* resource = ownedBitmapResources.itemAt(i);
-        mOwnedBitmapResources.add(resource);
-        caches.resourceCache.incrementRefcountLocked(resource);
-    }
-
-    const Vector<const Res_png_9patch*>& patchResources = recorder.getPatchResources();
-    for (size_t i = 0; i < patchResources.size(); i++) {
-        const Res_png_9patch* resource = patchResources.itemAt(i);
-        mPatchResources.add(resource);
-        caches.resourceCache.incrementRefcountLocked(resource);
-    }
-
-    const Vector<SkiaShader*>& shaders = recorder.getShaders();
-    for (size_t i = 0; i < shaders.size(); i++) {
-        SkiaShader* resource = shaders.itemAt(i);
-        mShaders.add(resource);
-        caches.resourceCache.incrementRefcountLocked(resource);
-    }
-
-    const SortedVector<const SkPath*>& sourcePaths = recorder.getSourcePaths();
-    for (size_t i = 0; i < sourcePaths.size(); i++) {
-        mSourcePaths.add(sourcePaths.itemAt(i));
-        caches.resourceCache.incrementRefcountLocked(sourcePaths.itemAt(i));
-    }
-
-    const Vector<Layer*>& layers = recorder.getLayers();
-    for (size_t i = 0; i < layers.size(); i++) {
-        mLayers.add(layers.itemAt(i));
-        caches.resourceCache.incrementRefcountLocked(layers.itemAt(i));
-    }
-
-    caches.resourceCache.unlock();
-
-    mPaints.appendVector(recorder.getPaints());
-    mRegions.appendVector(recorder.getRegions());
-    mPaths.appendVector(recorder.getPaths());
-    mMatrices.appendVector(recorder.getMatrices());
-}
-
-void DisplayList::init() {
-    mSize = 0;
-    mIsRenderable = true;
-    mFunctorCount = 0;
     mLeft = 0;
     mTop = 0;
     mRight = 0;
@@ -256,8 +87,31 @@
     mCaching = false;
 }
 
-size_t DisplayList::getSize() {
-    return mSize;
+DisplayList::~DisplayList() {
+    LOG_ALWAYS_FATAL_IF(mDestroyed, "Double destroyed DisplayList %p", this);
+
+    mDestroyed = true;
+    delete mDisplayListData;
+    delete mTransformMatrix;
+    delete mTransformCamera;
+    delete mTransformMatrix3D;
+    delete mStaticMatrix;
+    delete mAnimationMatrix;
+}
+
+void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) {
+    if (displayList) {
+        DISPLAY_LIST_LOGD("Deferring display list destruction");
+        Caches::getInstance().deleteDisplayListDeferred(displayList);
+    }
+}
+
+void DisplayList::setData(DisplayListData* data) {
+    delete mDisplayListData;
+    mDisplayListData = data;
+    if (mDisplayListData) {
+        Caches::getInstance().registerFunctors(mDisplayListData->functorCount);
+    }
 }
 
 /**
@@ -518,7 +372,7 @@
         const mat4* transformFromProjectionSurface) {
     m3dNodes.clear();
     mProjectedNodes.clear();
-    if (mDisplayListData == NULL || mSize == 0) return;
+    if (mDisplayListData == NULL || mDisplayListData->isEmpty()) return;
 
     // TODO: should avoid this calculation in most cases
     // TODO: just calculate single matrix, down to all leaf composited elements
@@ -637,6 +491,8 @@
             replayStruct.mDrawGlStatus);
 }
 
+#define SHADOW_DELTA 2.0f
+
 template <class T>
 void DisplayList::iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& renderer,
         T& handler, const int level) {
@@ -650,33 +506,66 @@
     int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
     LinearAllocator& alloc = handler.allocator();
     ClipRectOp* clipOp = new (alloc) ClipRectOp(0, 0, mWidth, mHeight,
-            SkRegion::kIntersect_Op); // clip to 3d root bounds for now
+            SkRegion::kIntersect_Op); // clip to 3d root bounds
     handler(clipOp, PROPERTY_SAVECOUNT, mClipToBounds);
 
-    for (size_t i = 0; i < m3dNodes.size(); i++) {
-        const float zValue = m3dNodes[i].key;
-        DrawDisplayListOp* childOp = m3dNodes[i].value;
+    /**
+     * Draw shadows and (potential) casters mostly in order, but allow the shadows of casters
+     * with very similar Z heights to draw together.
+     *
+     * This way, if Views A & B have the same Z height and are both casting shadows, the shadows are
+     * underneath both, and neither's shadow is drawn on top of the other.
+     */
+    const size_t nonNegativeIndex = findNonNegativeIndex(m3dNodes);
+    size_t drawIndex, shadowIndex, endIndex;
+    if (mode == kNegativeZChildren) {
+        drawIndex = 0;
+        endIndex = nonNegativeIndex;
+        shadowIndex = endIndex; // draw no shadows
+    } else {
+        drawIndex = nonNegativeIndex;
+        endIndex = m3dNodes.size();
+        shadowIndex = drawIndex; // potentially draw shadow for each pos Z child
+    }
+    float lastCasterZ = 0.0f;
+    while (shadowIndex < endIndex || drawIndex < endIndex) {
+        if (shadowIndex < endIndex) {
+            DrawDisplayListOp* casterOp = m3dNodes[shadowIndex].value;
+            DisplayList* caster = casterOp->mDisplayList;
+            const float casterZ = m3dNodes[shadowIndex].key;
+            // attempt to render the shadow if the caster about to be drawn is its caster,
+            // OR if its caster's Z value is similar to the previous potential caster
+            if (shadowIndex == drawIndex || casterZ - lastCasterZ < SHADOW_DELTA) {
 
-        if (mode == kPositiveZChildren && zValue < 0.0f) continue;
-        if (mode == kNegativeZChildren && zValue > 0.0f) break;
+                if (caster->mCastsShadow && caster->mAlpha > 0.0f) {
+                    mat4 shadowMatrix(casterOp->mTransformFromCompositingAncestor);
+                    caster->applyViewPropertyTransforms(shadowMatrix);
 
-        DisplayList* child = childOp->mDisplayList;
-        if (mode == kPositiveZChildren && zValue > 0.0f && child->mCastsShadow) {
-            /* draw shadow with parent matrix applied, passing in the child's total matrix
-             * TODO: consider depth in more complex scenarios (neg z, added shadow depth)
-             */
-            mat4 shadowMatrix(childOp->mTransformFromCompositingAncestor);
-            child->applyViewPropertyTransforms(shadowMatrix);
+                    DisplayListOp* shadowOp  = new (alloc) DrawShadowOp(shadowMatrix,
+                            caster->mAlpha, &(caster->mOutline), caster->mWidth, caster->mHeight);
+                    handler(shadowOp, PROPERTY_SAVECOUNT, mClipToBounds);
+                }
 
-            DisplayListOp* shadowOp  = new (alloc) DrawShadowOp(shadowMatrix,
-                    child->mAlpha, &(child->mOutline), child->mWidth, child->mHeight);
-            handler(shadowOp, PROPERTY_SAVECOUNT, mClipToBounds);
+                lastCasterZ = casterZ; // must do this even if current caster not casting a shadow
+                shadowIndex++;
+                continue;
+            }
         }
 
+        // only the actual child DL draw needs to be in save/restore,
+        // since it modifies the renderer's matrix
+        int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag);
+
+        DrawDisplayListOp* childOp = m3dNodes[drawIndex].value;
+        DisplayList* child = childOp->mDisplayList;
+
         renderer.concatMatrix(childOp->mTransformFromCompositingAncestor);
         childOp->mSkipInOrderDraw = false; // this is horrible, I'm so sorry everyone
         handler(childOp, renderer.getSaveCount() - 1, mClipToBounds);
         childOp->mSkipInOrderDraw = true;
+
+        renderer.restoreToCount(restoreTo);
+        drawIndex++;
     }
     handler(new (alloc) RestoreToCountOp(rootRestoreTo), PROPERTY_SAVECOUNT, mClipToBounds);
 }
@@ -715,10 +604,10 @@
 template <class T>
 void DisplayList::iterate(OpenGLRenderer& renderer, T& handler, const int level) {
     if (CC_UNLIKELY(mDestroyed)) { // temporary debug logging
-        ALOGW("Error: %s is drawing after destruction, size %d", getName(), mSize);
+        ALOGW("Error: %s is drawing after destruction", getName());
         CRASH();
     }
-    if (mSize == 0 || mAlpha <= 0) {
+    if (mDisplayListData->isEmpty() || mAlpha <= 0) {
         DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", level * 2, "", this, mName.string());
         return;
     }
@@ -776,5 +665,67 @@
     renderer.setOverrideLayerAlpha(1.0f);
 }
 
+void DisplayListData::cleanupResources() {
+    Caches& caches = Caches::getInstance();
+    caches.unregisterFunctors(functorCount);
+    caches.resourceCache.lock();
+
+    for (size_t i = 0; i < bitmapResources.size(); i++) {
+        caches.resourceCache.decrementRefcountLocked(bitmapResources.itemAt(i));
+    }
+
+    for (size_t i = 0; i < ownedBitmapResources.size(); i++) {
+        const SkBitmap* bitmap = ownedBitmapResources.itemAt(i);
+        caches.resourceCache.decrementRefcountLocked(bitmap);
+        caches.resourceCache.destructorLocked(bitmap);
+    }
+
+    for (size_t i = 0; i < patchResources.size(); i++) {
+        caches.resourceCache.decrementRefcountLocked(patchResources.itemAt(i));
+    }
+
+    for (size_t i = 0; i < shaders.size(); i++) {
+        caches.resourceCache.decrementRefcountLocked(shaders.itemAt(i));
+        caches.resourceCache.destructorLocked(shaders.itemAt(i));
+    }
+
+    for (size_t i = 0; i < sourcePaths.size(); i++) {
+        caches.resourceCache.decrementRefcountLocked(sourcePaths.itemAt(i));
+    }
+
+    for (size_t i = 0; i < layers.size(); i++) {
+        caches.resourceCache.decrementRefcountLocked(layers.itemAt(i));
+    }
+
+    caches.resourceCache.unlock();
+
+    for (size_t i = 0; i < paints.size(); i++) {
+        delete paints.itemAt(i);
+    }
+
+    for (size_t i = 0; i < regions.size(); i++) {
+        delete regions.itemAt(i);
+    }
+
+    for (size_t i = 0; i < paths.size(); i++) {
+        delete paths.itemAt(i);
+    }
+
+    for (size_t i = 0; i < matrices.size(); i++) {
+        delete matrices.itemAt(i);
+    }
+
+    bitmapResources.clear();
+    ownedBitmapResources.clear();
+    patchResources.clear();
+    shaders.clear();
+    sourcePaths.clear();
+    paints.clear();
+    regions.clear();
+    paths.clear();
+    matrices.clear();
+    layers.clear();
+}
+
 }; // namespace uirenderer
 }; // namespace android
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 9487fae..a3577d4 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -107,11 +107,13 @@
 };
 
 /**
- * Refcounted structure that holds the list of commands used in display list stream.
+ * Data structure that holds the list of commands used in display list stream
  */
-class DisplayListData : public LightRefBase<DisplayListData> {
+class DisplayListData {
 public:
-    DisplayListData() : projectionReceiveIndex(-1) {}
+    DisplayListData() : projectionReceiveIndex(-1), functorCount(0), hasDrawOps(false) {}
+    virtual ~DisplayListData() { cleanupResources(); }
+
     // allocator into which all ops were allocated
     LinearAllocator allocator;
 
@@ -123,6 +125,27 @@
 
     // index of DisplayListOp restore, after which projected descendents should be drawn
     int projectionReceiveIndex;
+
+    Vector<const SkBitmap*> bitmapResources;
+    Vector<const SkBitmap*> ownedBitmapResources;
+    Vector<const Res_png_9patch*> patchResources;
+
+    Vector<const SkPaint*> paints;
+    Vector<const SkPath*> paths;
+    SortedVector<const SkPath*> sourcePaths;
+    Vector<const SkRegion*> regions;
+    Vector<const SkMatrix*> matrices;
+    Vector<SkiaShader*> shaders;
+    Vector<Layer*> layers;
+    uint32_t functorCount;
+    bool hasDrawOps;
+
+    bool isEmpty() {
+        return !displayListOps.size();
+    }
+
+private:
+    void cleanupResources();
 };
 
 /**
@@ -139,7 +162,7 @@
  */
 class DisplayList {
 public:
-    DisplayList(const DisplayListRenderer& recorder);
+    ANDROID_API DisplayList();
     ANDROID_API ~DisplayList();
 
     // See flags defined in DisplayList.java
@@ -147,11 +170,10 @@
         kReplayFlag_ClipChildren = 0x1
     };
 
-    ANDROID_API size_t getSize();
     ANDROID_API static void destroyDisplayListDeferred(DisplayList* displayList);
     ANDROID_API static void outputLogBuffer(int fd);
 
-    void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false);
+    ANDROID_API void setData(DisplayListData* newData);
 
     void computeOrdering();
     void defer(DeferStateStruct& deferStruct, const int level);
@@ -159,14 +181,8 @@
 
     ANDROID_API void output(uint32_t level = 1);
 
-    ANDROID_API void reset();
-
-    void setRenderable(bool renderable) {
-        mIsRenderable = renderable;
-    }
-
     bool isRenderable() const {
-        return mIsRenderable;
+        return mDisplayListData && mDisplayListData->hasDrawOps;
     }
 
     void setName(const char* name) {
@@ -534,6 +550,13 @@
 private:
     typedef key_value_pair_t<float, DrawDisplayListOp*> ZDrawDisplayListOpPair;
 
+    static size_t findNonNegativeIndex(const Vector<ZDrawDisplayListOpPair>& nodes) {
+        for (size_t i = 0; i < nodes.size(); i++) {
+            if (nodes[i].key >= 0.0f) return i;
+        }
+        return nodes.size();
+    }
+
     enum ChildrenSelectMode {
         kNegativeZChildren,
         kPositiveZChildren
@@ -571,10 +594,6 @@
     template <class T>
     inline void iterate(OpenGLRenderer& renderer, T& handler, const int level);
 
-    void init();
-
-    void clearResources();
-
     void updateMatrix();
 
     class TextContainer {
@@ -591,24 +610,7 @@
         const char* mText;
     };
 
-    Vector<const SkBitmap*> mBitmapResources;
-    Vector<const SkBitmap*> mOwnedBitmapResources;
-    Vector<const Res_png_9patch*> mPatchResources;
-
-    Vector<const SkPaint*> mPaints;
-    Vector<const SkPath*> mPaths;
-    SortedVector<const SkPath*> mSourcePaths;
-    Vector<const SkRegion*> mRegions;
-    Vector<const SkMatrix*> mMatrices;
-    Vector<SkiaShader*> mShaders;
-    Vector<Layer*> mLayers;
-
-    sp<DisplayListData> mDisplayListData;
-
-    size_t mSize;
-
-    bool mIsRenderable;
-    uint32_t mFunctorCount;
+    DisplayListData* mDisplayListData;
 
     String8 mName;
     bool mDestroyed; // used for debugging crash, TODO: remove once invalid state crash fixed
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 0589a022..65eda29 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -788,7 +788,7 @@
         deferInfo.mergeable = state.mMatrix.isSimple() && state.mMatrix.positiveScale() &&
                 !state.mClipSideFlags &&
                 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode &&
-                (mBitmap->getConfig() != SkBitmap::kA8_Config);
+                (mBitmap->config() != SkBitmap::kA8_Config);
     }
 
     const SkBitmap* bitmap() { return mBitmap; }
@@ -1410,7 +1410,7 @@
                 DeferredDisplayList::kOpBatch_Text :
                 DeferredDisplayList::kOpBatch_ColorText;
 
-        deferInfo.mergeId = (mergeid_t)mPaint->getColor();
+        deferInfo.mergeId = reinterpret_cast<mergeid_t>(mPaint->getColor());
 
         // don't merge decorated text - the decorations won't draw in order
         bool noDecorations = !(mPaint->getFlags() & (SkPaint::kUnderlineText_Flag |
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 0cbf088..3b1d567 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -32,83 +32,28 @@
 namespace uirenderer {
 
 DisplayListRenderer::DisplayListRenderer():
-        mCaches(Caches::getInstance()), mDisplayListData(new DisplayListData),
+        mCaches(Caches::getInstance()), mDisplayListData(0),
         mTranslateX(0.0f), mTranslateY(0.0f), mHasTranslate(false),
-        mHasDrawOps(false), mFunctorCount(0) {
+        mRestoreSaveCount(-1) {
 }
 
 DisplayListRenderer::~DisplayListRenderer() {
-    reset();
-}
-
-void DisplayListRenderer::reset() {
-    mDisplayListData = new DisplayListData();
-    mCaches.resourceCache.lock();
-
-    for (size_t i = 0; i < mBitmapResources.size(); i++) {
-        mCaches.resourceCache.decrementRefcountLocked(mBitmapResources.itemAt(i));
-    }
-
-    for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) {
-        mCaches.resourceCache.decrementRefcountLocked(mOwnedBitmapResources.itemAt(i));
-    }
-
-    for (size_t i = 0; i < mPatchResources.size(); i++) {
-        mCaches.resourceCache.decrementRefcountLocked(mPatchResources.itemAt(i));
-    }
-
-    for (size_t i = 0; i < mShaders.size(); i++) {
-        mCaches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i));
-    }
-
-    for (size_t i = 0; i < mSourcePaths.size(); i++) {
-        mCaches.resourceCache.decrementRefcountLocked(mSourcePaths.itemAt(i));
-    }
-
-    for (size_t i = 0; i < mLayers.size(); i++) {
-        mCaches.resourceCache.decrementRefcountLocked(mLayers.itemAt(i));
-    }
-
-    mCaches.resourceCache.unlock();
-
-    mBitmapResources.clear();
-    mOwnedBitmapResources.clear();
-    mPatchResources.clear();
-    mSourcePaths.clear();
-
-    mShaders.clear();
-    mShaderMap.clear();
-
-    mPaints.clear();
-    mPaintMap.clear();
-
-    mRegions.clear();
-    mRegionMap.clear();
-
-    mPaths.clear();
-    mPathMap.clear();
-
-    mMatrices.clear();
-
-    mLayers.clear();
-
-    mHasDrawOps = false;
-    mFunctorCount = 0;
+    LOG_ALWAYS_FATAL_IF(mDisplayListData,
+            "Destroyed a DisplayListRenderer during a record!");
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 // Operations
 ///////////////////////////////////////////////////////////////////////////////
 
-DisplayList* DisplayListRenderer::getDisplayList(DisplayList* displayList) {
-    if (!displayList) {
-        displayList = new DisplayList(*this);
-    } else {
-        displayList->initFromDisplayListRenderer(*this, true);
-    }
-    // TODO: should just avoid setting the DisplayList's DisplayListData
-    displayList->setRenderable(mHasDrawOps);
-    return displayList;
+DisplayListData* DisplayListRenderer::finishRecording() {
+    mShaderMap.clear();
+    mPaintMap.clear();
+    mRegionMap.clear();
+    mPathMap.clear();
+    DisplayListData* data = mDisplayListData;
+    mDisplayListData = 0;
+    return data;
 }
 
 void DisplayListRenderer::setViewport(int width, int height) {
@@ -120,6 +65,11 @@
 
 status_t DisplayListRenderer::prepareDirty(float left, float top,
         float right, float bottom, bool opaque) {
+
+    LOG_ALWAYS_FATAL_IF(mDisplayListData,
+            "prepareDirty called a second time during a recording!");
+    mDisplayListData = new DisplayListData();
+
     initializeSaveStack(0, 0, getWidth(), getHeight());
 
     mDirtyClip = opaque;
@@ -142,7 +92,7 @@
 status_t DisplayListRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
     // Ignore dirty during recording, it matters only when we replay
     addDrawOp(new (alloc()) DrawFunctorOp(functor));
-    mFunctorCount++;
+    mDisplayListData->functorCount++;
     return DrawGlInfo::kStatusDone; // No invalidate needed at record-time
 }
 
@@ -501,7 +451,7 @@
         op->setQuickRejected(rejected);
     }
 
-    mHasDrawOps = true;
+    mDisplayListData->hasDrawOps = true;
     addOpInternal(op);
 }
 
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 7e62c5d..1fb72ce 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -61,7 +61,7 @@
     ANDROID_API DisplayListRenderer();
     virtual ~DisplayListRenderer();
 
-    ANDROID_API DisplayList* getDisplayList(DisplayList* displayList);
+    ANDROID_API DisplayListData* finishRecording();
 
     virtual bool isRecording() const { return true; }
 
@@ -162,59 +162,6 @@
     // TODO: rename for consistency
     virtual status_t callDrawGLFunction(Functor* functor, Rect& dirty);
 
-// ----------------------------------------------------------------------------
-// DisplayList / resource management
-// ----------------------------------------------------------------------------
-    ANDROID_API void reset();
-
-    sp<DisplayListData> getDisplayListData() const {
-        return mDisplayListData;
-    }
-
-    const Vector<const SkBitmap*>& getBitmapResources() const {
-        return mBitmapResources;
-    }
-
-    const Vector<const SkBitmap*>& getOwnedBitmapResources() const {
-        return mOwnedBitmapResources;
-    }
-
-    const Vector<const Res_png_9patch*>& getPatchResources() const {
-        return mPatchResources;
-    }
-
-    const Vector<SkiaShader*>& getShaders() const {
-        return mShaders;
-    }
-
-    const Vector<const SkPaint*>& getPaints() const {
-        return mPaints;
-    }
-
-    const Vector<const SkPath*>& getPaths() const {
-        return mPaths;
-    }
-
-    const SortedVector<const SkPath*>& getSourcePaths() const {
-        return mSourcePaths;
-    }
-
-    const Vector<const SkRegion*>& getRegions() const {
-        return mRegions;
-    }
-
-    const Vector<Layer*>& getLayers() const {
-        return mLayers;
-    }
-
-    const Vector<const SkMatrix*>& getMatrices() const {
-        return mMatrices;
-    }
-
-    uint32_t getFunctorCount() const {
-        return mFunctorCount;
-    }
-
 private:
     void insertRestoreToCount();
     void insertTranslate();
@@ -252,11 +199,11 @@
             pathCopy = newPathCopy;
             // replaceValueFor() performs an add if the entry doesn't exist
             mPathMap.replaceValueFor(path, pathCopy);
-            mPaths.add(pathCopy);
+            mDisplayListData->paths.add(pathCopy);
         }
-        if (mSourcePaths.indexOf(path) < 0) {
+        if (mDisplayListData->sourcePaths.indexOf(path) < 0) {
             mCaches.resourceCache.incrementRefcount(path);
-            mSourcePaths.add(path);
+            mDisplayListData->sourcePaths.add(path);
         }
         return pathCopy;
     }
@@ -271,7 +218,7 @@
             paintCopy = new SkPaint(*paint);
             // replaceValueFor() performs an add if the entry doesn't exist
             mPaintMap.replaceValueFor(paint, paintCopy);
-            mPaints.add(paintCopy);
+            mDisplayListData->paints.add(paintCopy);
         }
 
         return paintCopy;
@@ -288,7 +235,7 @@
             regionCopy = new SkRegion(*region);
             // replaceValueFor() performs an add if the entry doesn't exist
             mRegionMap.replaceValueFor(region, regionCopy);
-            mRegions.add(regionCopy);
+            mDisplayListData->regions.add(regionCopy);
         }
 
         return regionCopy;
@@ -299,14 +246,14 @@
             // Copying the matrix is cheap and prevents against the user changing
             // the original matrix before the operation that uses it
             const SkMatrix* copy = new SkMatrix(*matrix);
-            mMatrices.add(copy);
+            mDisplayListData->matrices.add(copy);
             return copy;
         }
         return matrix;
     }
 
     inline Layer* refLayer(Layer* layer) {
-        mLayers.add(layer);
+        mDisplayListData->layers.add(layer);
         mCaches.resourceCache.incrementRefcount(layer);
         return layer;
     }
@@ -316,13 +263,13 @@
         // correctly, such as creating the bitmap from scratch, drawing with it, changing its
         // contents, and drawing again. The only fix would be to always copy it the first time,
         // which doesn't seem worth the extra cycles for this unlikely case.
-        mBitmapResources.add(bitmap);
+        mDisplayListData->bitmapResources.add(bitmap);
         mCaches.resourceCache.incrementRefcount(bitmap);
         return bitmap;
     }
 
     inline const SkBitmap* refBitmapData(const SkBitmap* bitmap) {
-        mOwnedBitmapResources.add(bitmap);
+        mDisplayListData->ownedBitmapResources.add(bitmap);
         mCaches.resourceCache.incrementRefcount(bitmap);
         return bitmap;
     }
@@ -336,52 +283,31 @@
             shaderCopy = shader->copy();
             // replaceValueFor() performs an add if the entry doesn't exist
             mShaderMap.replaceValueFor(shader, shaderCopy);
-            mShaders.add(shaderCopy);
+            mDisplayListData->shaders.add(shaderCopy);
             mCaches.resourceCache.incrementRefcount(shaderCopy);
         }
         return shaderCopy;
     }
 
     inline const Res_png_9patch* refPatch(const Res_png_9patch* patch) {
-        mPatchResources.add(patch);
+        mDisplayListData->patchResources.add(patch);
         mCaches.resourceCache.incrementRefcount(patch);
         return patch;
     }
 
-    // TODO: move these to DisplayListData
-    Vector<const SkBitmap*> mBitmapResources;
-    Vector<const SkBitmap*> mOwnedBitmapResources;
-    Vector<const Res_png_9patch*> mPatchResources;
-
-    Vector<const SkPaint*> mPaints;
     DefaultKeyedVector<const SkPaint*, const SkPaint*> mPaintMap;
-
-    Vector<const SkPath*> mPaths;
     DefaultKeyedVector<const SkPath*, const SkPath*> mPathMap;
-
-    SortedVector<const SkPath*> mSourcePaths;
-
-    Vector<const SkRegion*> mRegions;
     DefaultKeyedVector<const SkRegion*, const SkRegion*> mRegionMap;
-
-    Vector<SkiaShader*> mShaders;
     DefaultKeyedVector<SkiaShader*, SkiaShader*> mShaderMap;
 
-    Vector<const SkMatrix*> mMatrices;
-
-    Vector<Layer*> mLayers;
-
-    int mRestoreSaveCount;
-
     Caches& mCaches;
-    sp<DisplayListData> mDisplayListData;
+    DisplayListData* mDisplayListData;
 
     float mTranslateX;
     float mTranslateY;
     bool mHasTranslate;
-    bool mHasDrawOps;
 
-    uint32_t mFunctorCount;
+    int mRestoreSaveCount;
 
     friend class DisplayList;
 
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index b79a3b0..b52003c 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -498,7 +498,7 @@
                 }
 
                 checkTextureUpdate();
-                caches.bindIndicesBuffer();
+                caches.bindQuadIndicesBuffer();
 
                 if (!mDrawn) {
                     // If returns true, a VBO was bound and we must
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 70eeb39..8992a13 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -46,6 +46,7 @@
     stencil = NULL;
     debugDrawUpdate = false;
     hasDrawnSinceUpdate = false;
+    forceFilter = false;
     deferredList = NULL;
     caches.resourceCache.incrementRefcount(this);
 }
@@ -131,8 +132,9 @@
     }
 }
 
-void Layer::setPaint(SkPaint* paint) {
+void Layer::setPaint(const SkPaint* paint) {
     OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode);
+    setColorFilter((paint) ? paint->getColorFilter() : NULL);
 }
 
 void Layer::setColorFilter(SkColorFilter* filter) {
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index ec80e9c..f6538f2 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -117,7 +117,7 @@
         texture.height = height;
     }
 
-    ANDROID_API void setPaint(SkPaint* paint);
+    ANDROID_API void setPaint(const SkPaint* paint);
 
     inline void setBlend(bool blend) {
         texture.blend = blend;
@@ -127,6 +127,14 @@
         return texture.blend;
     }
 
+    inline void setForceFilter(bool forceFilter) {
+        this->forceFilter = forceFilter;
+    }
+
+    inline bool getForceFilter() const {
+        return forceFilter;
+    }
+
     inline void setAlpha(int alpha) {
         this->alpha = alpha;
     }
@@ -343,9 +351,15 @@
     SkColorFilter* colorFilter;
 
     /**
+     * Indicates raster data backing the layer is scaled, requiring filtration.
+     */
+    bool forceFilter;
+
+    /**
      * Opacity of the layer.
      */
     int alpha;
+
     /**
      * Blending mode of the layer.
      */
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index ea8eb31..e0ac2ba 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -290,14 +290,15 @@
 }
 
 void LayerRenderer::updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
-        bool isOpaque, GLenum renderTarget, float* transform) {
+        bool isOpaque, bool forceFilter, GLenum renderTarget, float* textureTransform) {
     if (layer) {
         layer->setBlend(!isOpaque);
+        layer->setForceFilter(forceFilter);
         layer->setSize(width, 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->getTexTransform().load(transform);
+        layer->getTexTransform().load(textureTransform);
 
         if (renderTarget != layer->getRenderTarget()) {
             layer->setRenderTarget(renderTarget);
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index 84acd44..40e461a 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -56,7 +56,7 @@
     ANDROID_API static Layer* createRenderLayer(uint32_t width, uint32_t height);
     ANDROID_API static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height);
     ANDROID_API static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
-            bool isOpaque, GLenum renderTarget, float* transform);
+            bool isOpaque, bool forceFilter, GLenum renderTarget, float* textureTransform);
     ANDROID_API static void destroyLayer(Layer* layer);
     ANDROID_API static void destroyLayerDeferred(Layer* layer);
     ANDROID_API static bool copyLayer(Layer* layer, SkBitmap* bitmap);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 9b253a6..b620b80 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -52,7 +52,12 @@
 
 #define ALPHA_THRESHOLD 0
 
-#define FILTER(paint) (!paint || paint->isFilterBitmap() ? GL_LINEAR : GL_NEAREST)
+static GLenum getFilter(const SkPaint* paint) {
+    if (!paint || paint->getFilterLevel() != SkPaint::kNone_FilterLevel) {
+        return GL_LINEAR;
+    }
+    return GL_NEAREST;
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 // Globals
@@ -868,14 +873,11 @@
 
     const bool fboLayer = flags & SkCanvas::kClipToLayer_SaveFlag;
 
-    SkXfermode::Mode mode = getXfermodeDirect(paint);
-    int alpha = getAlphaDirect(paint);
-
     // Window coordinates of the layer
     Rect clip;
     Rect bounds(left, top, right, bottom);
     calculateLayerBoundsAndClip(bounds, clip, fboLayer);
-    updateSnapshotIgnoreForLayer(bounds, clip, fboLayer, alpha);
+    updateSnapshotIgnoreForLayer(bounds, clip, fboLayer, getAlphaDirect(paint));
 
     // Bail out if we won't draw in this snapshot
     if (currentSnapshot()->isIgnored()) {
@@ -888,12 +890,11 @@
         return false;
     }
 
-    layer->setAlpha(alpha, mode);
+    layer->setPaint(paint);
     layer->layer.set(bounds);
     layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->getHeight()),
             bounds.getWidth() / float(layer->getWidth()), 0.0f);
 
-    layer->setColorFilter(getColorFilter(paint));
     layer->setBlend(true);
     layer->setDirty(false);
 
@@ -1011,7 +1012,6 @@
     }
 
     if (!fboLayer && layer->getAlpha() < 255) {
-        // TODO: this seems to point to the fact that the layer should store the paint
         SkPaint layerPaint;
         layerPaint.setAlpha(layer->getAlpha());
         layerPaint.setXfermodeMode(SkXfermode::kDstIn_Mode);
@@ -1073,6 +1073,7 @@
         setupDrawExternalTexture(layer->getTexture());
     }
     if (currentTransform()->isPureTranslate() &&
+            !layer->getForceFilter() &&
             layer->getWidth() == (uint32_t) rect.getWidth() &&
             layer->getHeight() == (uint32_t) rect.getHeight()) {
         const float x = (int) floorf(rect.left + currentTransform()->getTranslateX() + 0.5f);
@@ -1907,7 +1908,7 @@
     } else {
         force = mCaches.unbindMeshBuffer();
     }
-    mCaches.bindIndicesBuffer();
+    mCaches.bindQuadIndicesBuffer();
 
     mCaches.bindPositionVertexPointer(force, vertices);
     if (mCaches.currentProgram->texCoords >= 0) {
@@ -1917,7 +1918,7 @@
 
 void OpenGLRenderer::setupDrawIndexedVertices(GLvoid* vertices) {
     bool force = mCaches.unbindMeshBuffer();
-    mCaches.bindIndicesBuffer();
+    mCaches.bindQuadIndicesBuffer();
     mCaches.bindPositionVertexPointer(force, vertices, gVertexStride);
 }
 
@@ -1977,7 +1978,7 @@
 
         texture->setFilter(GL_NEAREST, true);
     } else {
-        texture->setFilter(FILTER(paint), true);
+        texture->setFilter(getFilter(paint), true);
     }
 
     // No need to check for a UV mapper on the texture object, only ARGB_8888
@@ -2002,7 +2003,7 @@
     const AutoTexture autoCleanup(texture);
 
     texture->setWrap(GL_CLAMP_TO_EDGE, true);
-    texture->setFilter(pureTranslate ? GL_NEAREST : FILTER(paint), true);
+    texture->setFilter(pureTranslate ? GL_NEAREST : getFilter(paint), true);
 
     const float x = (int) floorf(bounds.left + 0.5f);
     const float y = (int) floorf(bounds.top + 0.5f);
@@ -2178,7 +2179,7 @@
     const AutoTexture autoCleanup(texture);
 
     texture->setWrap(GL_CLAMP_TO_EDGE, true);
-    texture->setFilter(FILTER(paint), true);
+    texture->setFilter(getFilter(paint), true);
 
     int alpha;
     SkXfermode::Mode mode;
@@ -2263,10 +2264,10 @@
         dstLeft = x;
         dstTop = y;
 
-        texture->setFilter(scaled ? FILTER(paint) : GL_NEAREST, true);
+        texture->setFilter(scaled ? getFilter(paint) : GL_NEAREST, true);
         ignoreTransform = true;
     } else {
-        texture->setFilter(FILTER(paint), true);
+        texture->setFilter(getFilter(paint), true);
     }
 
     if (CC_UNLIKELY(useScaleTransform)) {
@@ -2392,10 +2393,9 @@
     return DrawGlInfo::kStatusDrew;
 }
 
-status_t OpenGLRenderer::drawVertexBuffer(const VertexBuffer& vertexBuffer, const SkPaint* paint,
-        bool useOffset) {
+status_t OpenGLRenderer::drawVertexBuffer(VertexBufferMode mode,
+        const VertexBuffer& vertexBuffer, const SkPaint* paint, bool useOffset) {
     // not missing call to quickReject/dirtyLayer, always done at a higher level
-
     if (!vertexBuffer.getVertexCount()) {
         // no vertices to draw
         return DrawGlInfo::kStatusDone;
@@ -2421,19 +2421,24 @@
     bool force = mCaches.unbindMeshBuffer();
     mCaches.bindPositionVertexPointer(true, vertices, isAA ? gAlphaVertexStride : gVertexStride);
     mCaches.resetTexCoordsVertexPointer();
-    mCaches.unbindIndicesBuffer();
+
 
     int alphaSlot = -1;
     if (isAA) {
         void* alphaCoords = ((GLbyte*) vertices) + gVertexAlphaOffset;
         alphaSlot = mCaches.currentProgram->getAttrib("vtxAlpha");
-
         // TODO: avoid enable/disable in back to back uses of the alpha attribute
         glEnableVertexAttribArray(alphaSlot);
         glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, gAlphaVertexStride, alphaCoords);
     }
 
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexBuffer.getVertexCount());
+    if (mode == kVertexBufferMode_Standard) {
+        mCaches.unbindIndicesBuffer();
+        glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexBuffer.getVertexCount());
+    } else {
+        mCaches.bindShadowIndicesBuffer();
+        glDrawElements(GL_TRIANGLE_STRIP, SHADOW_INDEX_COUNT, GL_UNSIGNED_SHORT, 0);
+    }
 
     if (isAA) {
         glDisableVertexAttribArray(alphaSlot);
@@ -2462,7 +2467,7 @@
         dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, *currentTransform());
     }
 
-    return drawVertexBuffer(vertexBuffer, paint);
+    return drawVertexBuffer(kVertexBufferMode_Standard, vertexBuffer, paint);
 }
 
 /**
@@ -2493,7 +2498,7 @@
     dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, *currentTransform());
 
     bool useOffset = !paint->isAntiAlias();
-    return drawVertexBuffer(buffer, paint, useOffset);
+    return drawVertexBuffer(kVertexBufferMode_Standard, buffer, paint, useOffset);
 }
 
 status_t OpenGLRenderer::drawPoints(const float* points, int count, const SkPaint* paint) {
@@ -2513,7 +2518,7 @@
     dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, *currentTransform());
 
     bool useOffset = !paint->isAntiAlias();
-    return drawVertexBuffer(buffer, paint, useOffset);
+    return drawVertexBuffer(kVertexBufferMode_Standard, buffer, paint, useOffset);
 }
 
 status_t OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
@@ -3236,17 +3241,24 @@
         casterTransform.mapPoint3d(casterPolygon[i]);
     }
 
+    // map the centroid of the caster into 3d
+    Vector2 centroid =  ShadowTessellator::centroid2d(
+            reinterpret_cast<const Vector2*>(casterVertices2d.array()),
+            casterVertexCount);
+    Vector3 centroid3d(centroid.x, centroid.y, 0);
+    casterTransform.mapPoint3d(centroid3d);
+
     // draw caster's shadows
     if (mCaches.propertyAmbientShadowStrength > 0) {
-        paint.setARGB(mCaches.propertyAmbientShadowStrength, 0, 0, 0);
+        paint.setARGB(casterAlpha * mCaches.propertyAmbientShadowStrength, 0, 0, 0);
         VertexBuffer ambientShadowVertexBuffer;
         ShadowTessellator::tessellateAmbientShadow(casterPolygon, casterVertexCount,
-                ambientShadowVertexBuffer);
-        drawVertexBuffer(ambientShadowVertexBuffer, &paint);
+                centroid3d, ambientShadowVertexBuffer);
+        drawVertexBuffer(kVertexBufferMode_Shadow, ambientShadowVertexBuffer, &paint);
     }
 
     if (mCaches.propertySpotShadowStrength > 0) {
-        paint.setARGB(mCaches.propertySpotShadowStrength, 0, 0, 0);
+        paint.setARGB(casterAlpha * mCaches.propertySpotShadowStrength, 0, 0, 0);
         VertexBuffer spotShadowVertexBuffer;
         Vector3 lightPosScale(mCaches.propertyLightPosXScale,
                 mCaches.propertyLightPosYScale, mCaches.propertyLightPosZScale);
@@ -3254,7 +3266,7 @@
                 lightPosScale, *currentTransform(), getWidth(), getHeight(),
                 spotShadowVertexBuffer);
 
-        drawVertexBuffer(spotShadowVertexBuffer, &paint);
+        drawVertexBuffer(kVertexBufferMode_Shadow, spotShadowVertexBuffer, &paint);
     }
 
     return DrawGlInfo::kStatusDrew;
@@ -3375,7 +3387,7 @@
                 paint, texture->blend, vertices, texCoords,
                 GL_TRIANGLE_STRIP, gMeshCount, false, true);
     } else {
-        texture->setFilter(FILTER(paint), true);
+        texture->setFilter(getFilter(paint), true);
         drawTextureMesh(left, top, right, bottom, texture->id, paint,
                 texture->blend, vertices, texCoords, GL_TRIANGLE_STRIP, gMeshCount);
     }
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index e4d133d..03beae3 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -117,6 +117,11 @@
     kModelViewMode_TranslateAndScale = 1,
 };
 
+enum VertexBufferMode {
+    kVertexBufferMode_Standard = 0,
+    kVertexBufferMode_Shadow = 1
+};
+
 ///////////////////////////////////////////////////////////////////////////////
 // Renderer
 ///////////////////////////////////////////////////////////////////////////////
@@ -629,8 +634,8 @@
      * @param paint The paint to render with
      * @param useOffset Offset the vertexBuffer (used in drawing non-AA lines)
      */
-    status_t drawVertexBuffer(const VertexBuffer& vertexBuffer, const SkPaint* paint,
-            bool useOffset = false);
+    status_t drawVertexBuffer(VertexBufferMode mode, const VertexBuffer& vertexBuffer,
+            const SkPaint* paint, bool useOffset = false);
 
     /**
      * Renders the convex hull defined by the specified path as a strip of polygons.
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
index dc0d98c..8a44604 100644
--- a/libs/hwui/PatchCache.cpp
+++ b/libs/hwui/PatchCache.cpp
@@ -129,7 +129,11 @@
         Mutex::Autolock _l(mLock);
         size_t count = mGarbage.size();
         for (size_t i = 0; i < count; i++) {
-            remove(patchesToRemove, mGarbage[i]);
+            Res_png_9patch* patch = mGarbage[i];
+            remove(patchesToRemove, patch);
+            // A Res_png_9patch is actually an array of byte that's larger
+            // than sizeof(Res_png_9patch). It must be freed as an array.
+            delete[] (int8_t*) patch;
         }
         mGarbage.clear();
     }
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 9459885..5a49f38 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -395,7 +395,9 @@
         Mutex::Autolock l(mLock);
         size_t count = mGarbage.size();
         for (size_t i = 0; i < count; i++) {
-            remove(pathsToRemove, mGarbage.itemAt(i));
+            const path_pair_t& pair = mGarbage.itemAt(i);
+            remove(pathsToRemove, pair);
+            delete pair.getFirst();
         }
         mGarbage.clear();
     }
diff --git a/libs/hwui/PathTessellator.cpp b/libs/hwui/PathTessellator.cpp
index cc56333..4ef2158 100644
--- a/libs/hwui/PathTessellator.cpp
+++ b/libs/hwui/PathTessellator.cpp
@@ -16,7 +16,7 @@
 
 #define LOG_TAG "OpenGLRenderer"
 #define LOG_NDEBUG 1
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#define ATRACE_TAG ATRACE_TAG_VIEW
 
 #define VERTEX_DEBUG 0
 
diff --git a/libs/hwui/PixelBuffer.cpp b/libs/hwui/PixelBuffer.cpp
index 36e89c6..5b642b9 100644
--- a/libs/hwui/PixelBuffer.cpp
+++ b/libs/hwui/PixelBuffer.cpp
@@ -151,7 +151,7 @@
     mCaches.bindPixelBuffer(mBuffer);
     unmap();
     glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, mFormat,
-            GL_UNSIGNED_BYTE, (void*) offset);
+            GL_UNSIGNED_BYTE, reinterpret_cast<void*>(offset));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 457cfa9..5562f34 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -193,8 +193,9 @@
         // If we're not tracking this resource, just delete it
         if (Caches::hasInstance()) {
             Caches::getInstance().pathCache.removeDeferred(resource);
+        } else {
+            delete resource;
         }
-        delete resource;
         return;
     }
     ref->destroyed = true;
@@ -215,8 +216,9 @@
         // If we're not tracking this resource, just delete it
         if (Caches::hasInstance()) {
             Caches::getInstance().textureCache.removeDeferred(resource);
+        } else {
+            delete resource;
         }
-        delete resource;
         return;
     }
     ref->destroyed = true;
@@ -253,13 +255,14 @@
     ssize_t index = mCache->indexOfKey(resource);
     ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
     if (ref == NULL) {
+        // If we're not tracking this resource, just delete it
         if (Caches::hasInstance()) {
             Caches::getInstance().patchCache.removeDeferred(resource);
+        } else {
+            // A Res_png_9patch is actually an array of byte that's larger
+            // than sizeof(Res_png_9patch). It must be freed as an array.
+            delete[] (int8_t*) resource;
         }
-        // If we're not tracking this resource, just delete it
-        // A Res_png_9patch is actually an array of byte that's larger
-        // than sizeof(Res_png_9patch). It must be freed as an array.
-        delete[] (int8_t*) resource;
         return;
     }
     ref->destroyed = true;
@@ -316,16 +319,18 @@
                 SkBitmap* bitmap = (SkBitmap*) resource;
                 if (Caches::hasInstance()) {
                     Caches::getInstance().textureCache.removeDeferred(bitmap);
+                } else {
+                    delete bitmap;
                 }
-                delete bitmap;
             }
             break;
             case kPath: {
                 SkPath* path = (SkPath*) resource;
                 if (Caches::hasInstance()) {
                     Caches::getInstance().pathCache.removeDeferred(path);
+                } else {
+                    delete path;
                 }
-                delete path;
             }
             break;
             case kShader: {
@@ -336,11 +341,12 @@
             case kNinePatch: {
                 if (Caches::hasInstance()) {
                     Caches::getInstance().patchCache.removeDeferred((Res_png_9patch*) resource);
+                } else {
+                    // A Res_png_9patch is actually an array of byte that's larger
+                    // than sizeof(Res_png_9patch). It must be freed as an array.
+                    int8_t* patch = (int8_t*) resource;
+                    delete[] patch;
                 }
-                // A Res_png_9patch is actually an array of byte that's larger
-                // than sizeof(Res_png_9patch). It must be freed as an array.
-                int8_t* patch = (int8_t*) resource;
-                delete[] patch;
             }
             break;
             case kLayer: {
diff --git a/libs/hwui/ShadowTessellator.cpp b/libs/hwui/ShadowTessellator.cpp
index 7700ea0..5469aad 100644
--- a/libs/hwui/ShadowTessellator.cpp
+++ b/libs/hwui/ShadowTessellator.cpp
@@ -15,9 +15,11 @@
  */
 
 #define LOG_TAG "OpenGLRenderer"
+#define ATRACE_TAG ATRACE_TAG_VIEW
 
 #include <math.h>
 #include <utils/Log.h>
+#include <utils/Trace.h>
 
 #include "AmbientShadow.h"
 #include "ShadowTessellator.h"
@@ -31,29 +33,28 @@
     return a > b ? a : b;
 }
 
-void ShadowTessellator::tessellateAmbientShadow(const Vector3* casterPolygon, int casterVertexCount,
+void ShadowTessellator::tessellateAmbientShadow(const Vector3* casterPolygon,
+        int casterVertexCount, const Vector3& centroid3d,
         VertexBuffer& shadowVertexBuffer) {
+    ATRACE_CALL();
+
     // A bunch of parameters to tweak the shadow.
     // TODO: Allow some of these changable by debug settings or APIs.
-    const int rays = 128;
-    const int layers = 2;
-    const float strength = 0.5;
     const float heightFactor = 128;
     const float geomFactor = 64;
 
-    AmbientShadow::createAmbientShadow(casterPolygon, casterVertexCount, rays, layers, strength,
-            heightFactor, geomFactor, shadowVertexBuffer);
+    AmbientShadow::createAmbientShadow(casterPolygon, casterVertexCount,
+            centroid3d, heightFactor, geomFactor, shadowVertexBuffer);
 
 }
 
 void ShadowTessellator::tessellateSpotShadow(const Vector3* casterPolygon, int casterVertexCount,
         const Vector3& lightPosScale, const mat4& receiverTransform,
         int screenWidth, int screenHeight, VertexBuffer& shadowVertexBuffer) {
+    ATRACE_CALL();
+
     // A bunch of parameters to tweak the shadow.
     // TODO: Allow some of these changable by debug settings or APIs.
-    const int rays = 256;
-    const int layers = 2;
-    const float strength = 0.5;
     int maximal = max(screenWidth, screenHeight);
     Vector3 lightCenter(screenWidth * lightPosScale.x, screenHeight * lightPosScale.y,
             maximal * lightPosScale.z);
@@ -70,9 +71,77 @@
     const float lightSize = maximal / 4;
     const int lightVertexCount = 16;
 
-    SpotShadow::createSpotShadow(casterPolygon, casterVertexCount, lightCenter, lightSize,
-            lightVertexCount, rays, layers, strength, shadowVertexBuffer);
+    SpotShadow::createSpotShadow(casterPolygon, casterVertexCount, lightCenter,
+            lightSize, lightVertexCount, shadowVertexBuffer);
 
 }
+
+void ShadowTessellator::generateShadowIndices(uint16_t* shadowIndices) {
+    int currentIndex = 0;
+    const int layers = SHADOW_LAYER_COUNT;
+    const int rays = SHADOW_RAY_COUNT;
+    // For the penumbra area.
+    for (int i = 0; i < layers; i++) {
+        for (int j = 0; j < rays; j++) {
+            shadowIndices[currentIndex++] = i * rays + j;
+            shadowIndices[currentIndex++] = (i + 1) * rays + j;
+        }
+        // To close the loop, back to the ray 0.
+        shadowIndices[currentIndex++] = i * rays;
+        shadowIndices[currentIndex++] = (i + 1) * rays;
+    }
+    uint16_t base = layers * rays;
+    uint16_t centroidIndex = (layers + 1) * rays;
+    // For the umbra area, using strips to simulate the fans.
+    for (int k = 0; k < rays; k++) {
+        shadowIndices[currentIndex++] = base + k;
+        shadowIndices[currentIndex++] = centroidIndex;
+    }
+    shadowIndices[currentIndex++] = base;
+
+#if DEBUG_SHADOW
+    if (currentIndex != SHADOW_INDEX_COUNT) {
+        ALOGE("vertex index count is wrong. current %d, expected %d",
+                currentIndex, SHADOW_INDEX_COUNT);
+    }
+    for (int i = 0; i < SHADOW_INDEX_COUNT; i++) {
+        ALOGD("vertex index is (%d, %d)", i, shadowIndices[i]);
+    }
+#endif
+}
+
+/**
+ * Calculate the centroid of a 2d polygon.
+ *
+ * @param poly The polygon, which is represented in a Vector2 array.
+ * @param polyLength The length of the polygon in terms of number of vertices.
+ * @return the centroid of the polygon.
+ */
+Vector2 ShadowTessellator::centroid2d(const Vector2* poly, int polyLength) {
+    double sumx = 0;
+    double sumy = 0;
+    int p1 = polyLength - 1;
+    double area = 0;
+    for (int p2 = 0; p2 < polyLength; p2++) {
+        double x1 = poly[p1].x;
+        double y1 = poly[p1].y;
+        double x2 = poly[p2].x;
+        double y2 = poly[p2].y;
+        double a = (x1 * y2 - x2 * y1);
+        sumx += (x1 + x2) * a;
+        sumy += (y1 + y2) * a;
+        area += a;
+        p1 = p2;
+    }
+
+    Vector2 centroid = poly[0];
+    if (area != 0) {
+        centroid = Vector2(sumx / (3 * area), sumy / (3 * area));
+    } else {
+        ALOGE("Area is 0 while computing centroid!");
+    }
+    return centroid;
+}
+
 }; // namespace uirenderer
 }; // namespace android
diff --git a/libs/hwui/ShadowTessellator.h b/libs/hwui/ShadowTessellator.h
index ef95609..c49fdcb1 100644
--- a/libs/hwui/ShadowTessellator.h
+++ b/libs/hwui/ShadowTessellator.h
@@ -20,18 +20,57 @@
 
 #include "Debug.h"
 #include "Matrix.h"
+#include "VertexBuffer.h"
 
 namespace android {
 namespace uirenderer {
 
+// All SHADOW_* are used to define all the geometry property of shadows.
+// Use a simplified example to illustrate the geometry setup here.
+// Assuming we use 6 rays and only 1 layer, Then we will have 2 hexagons, which
+// are 0 to 5 and 6 to 11. The area between them will be the penumbra area, and
+// the area inside the 2nd hexagon is the umbra.
+// Also, we need to add the centroid "12" to draw the umbra area as triangle fans.
+//
+// Triange strip indices for penumbra area: (0, 6, 1, 7, 2, 8, 3, 9, 4, 10, 5, 11, 0, 6)
+// Triange strip indices for numbra area: (6, 12, 7, 12, 8, 12, 9, 12, 10, 12, 11, 12, 6)
+//                 0
+//
+//      5          6         1
+//           11         7
+//                12
+//           10         8
+//      4          9         2
+//
+//                 3
+
+// The total number of rays starting from the centroid of shadow area, in order
+// to generate the shadow geometry.
+#define SHADOW_RAY_COUNT 256
+
+// The total number of layers in the outer shadow area, 1 being the minimum.
+#define SHADOW_LAYER_COUNT 2
+
+// The total number of all the vertices representing the shadow.
+#define SHADOW_VERTEX_COUNT ((SHADOW_LAYER_COUNT + 1) * SHADOW_RAY_COUNT + 1)
+
+// The total number of indices used for drawing the shadow geometry as triangle strips.
+#define SHADOW_INDEX_COUNT (2 * SHADOW_RAY_COUNT + 1 + 2 * (SHADOW_RAY_COUNT + 1) * \
+        SHADOW_LAYER_COUNT)
+
 class ShadowTessellator {
 public:
-    static void tessellateAmbientShadow(const Vector3* casterPolygon, int casterVertexCount,
+    static void tessellateAmbientShadow(const Vector3* casterPolygon,
+            int casterVertexCount, const Vector3& centroid3d,
             VertexBuffer& shadowVertexBuffer);
 
     static void tessellateSpotShadow(const Vector3* casterPolygon, int casterVertexCount,
             const Vector3& lightPosScale, const mat4& receiverTransform,
             int screenWidth, int screenHeight, VertexBuffer& shadowVertexBuffer);
+
+    static void generateShadowIndices(uint16_t*  shadowIndices);
+
+    static Vector2 centroid2d(const Vector2* poly, int polyLength);
 }; // ShadowTessellator
 
 }; // namespace uirenderer
diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp
index 4c2299e..22d735b 100644
--- a/libs/hwui/SpotShadow.cpp
+++ b/libs/hwui/SpotShadow.cpp
@@ -22,6 +22,7 @@
 #include <stdlib.h>
 #include <utils/Log.h>
 
+#include "ShadowTessellator.h"
 #include "SpotShadow.h"
 #include "Vertex.h"
 
@@ -70,35 +71,6 @@
 }
 
 /**
- * Calculate the centroid of a 2d polygon.
- *
- * @param poly The polygon, which is represented in a Vector2 array.
- * @param polyLength The length of the polygon in terms of number of vertices.
- * @return the centroid of the polygon.
- */
-Vector2 SpotShadow::centroid2d(const Vector2* poly, int polyLength) {
-    double sumx = 0;
-    double sumy = 0;
-    int p1 = polyLength - 1;
-    double area = 0;
-    for (int p2 = 0; p2 < polyLength; p2++) {
-        double x1 = poly[p1].x;
-        double y1 = poly[p1].y;
-        double x2 = poly[p2].x;
-        double y2 = poly[p2].y;
-        double a = (x1 * y2 - x2 * y1);
-        sumx += (x1 + x2) * a;
-        sumy += (y1 + y2) * a;
-        area += a;
-        p1 = p2;
-    }
-
-    double centroidx = sumx / (3 * area);
-    double centroidy = sumy / (3 * area);
-    return Vector2((float)centroidx, (float)centroidy);
-}
-
-/**
  * Sort points by their X coordinates
  *
  * @param points the points as a Vector2 array.
@@ -550,20 +522,17 @@
 * @param lightCenter the center of the light
 * @param lightSize the radius of the light source
 * @param lightVertexCount the vertex counter for the light polygon
-* @param rays the number of vertexes to create along the edges of the shadow
-* @param layers the number of layers of triangles strips to create
-* @param strength the "darkness" of the shadow
 * @param shadowTriangleStrip return an (x,y,alpha) triangle strip representing the shadow. Return
 *                            empty strip if error.
 *
 */
 void SpotShadow::createSpotShadow(const Vector3* poly, int polyLength,
         const Vector3& lightCenter, float lightSize, int lightVertexCount,
-        int rays, int layers, float strength, VertexBuffer& retStrips) {
+        VertexBuffer& retStrips) {
     Vector3 light[lightVertexCount * 3];
     computeLightPolygon(lightVertexCount, lightCenter, lightSize, light);
-    computeSpotShadow(light, lightVertexCount, lightCenter,
-            poly, polyLength, rays, layers, strength, retStrips);
+    computeSpotShadow(light, lightVertexCount, lightCenter, poly, polyLength,
+            retStrips);
 }
 
 /**
@@ -573,15 +542,12 @@
  * @param lightPolyLength number of vertexes of the light source polygon
  * @param poly x,y,z vertexes of a convex polygon that occludes the light source
  * @param polyLength number of vertexes of the occluding polygon
- * @param rays the number of vertexes to create along the edges of the shadow
- * @param layers the number of layers of triangles strips to create
- * @param strength the "darkness" of the shadow
  * @param shadowTriangleStrip return an (x,y,alpha) triangle strip representing the shadow. Return
  *                            empty strip if error.
  */
 void SpotShadow::computeSpotShadow(const Vector3* lightPoly, int lightPolyLength,
         const Vector3& lightCenter, const Vector3* poly, int polyLength,
-        int rays, int layers, float strength, VertexBuffer& shadowTriangleStrip) {
+        VertexBuffer& shadowTriangleStrip) {
     // Point clouds for all the shadowed vertices
     Vector2 shadowRegion[lightPolyLength * polyLength];
     // Shadow polygon from one point light.
@@ -671,7 +637,8 @@
 
         // Shrink the centroid's shadow by 10%.
         // TODO: Study the magic number of 10%.
-        Vector2 shadowCentroid = centroid2d(fakeUmbra, polyLength);
+        Vector2 shadowCentroid =
+                ShadowTessellator::centroid2d(fakeUmbra, polyLength);
         for (int i = 0; i < polyLength; i++) {
             fakeUmbra[i] = shadowCentroid * (1.0f - SHADOW_SHRINK_SCALE) +
                     fakeUmbra[i] * SHADOW_SHRINK_SCALE;
@@ -686,7 +653,7 @@
     }
 
     generateTriangleStrip(penumbra, penumbraLength, umbra, umbraLength,
-            rays, layers, strength, shadowTriangleStrip);
+            shadowTriangleStrip);
 }
 
 /**
@@ -696,22 +663,18 @@
  * @param penumbraLength The number of vertexes in the outer polygon
  * @param umbra The inner outer polygon x,y vertexes
  * @param umbraLength The number of vertexes in the inner polygon
- * @param rays The number of points along the polygons to create
- * @param layers The number of layers of triangle strips between the umbra and penumbra
- * @param strength The max alpha of the umbra
  * @param shadowTriangleStrip return an (x,y,alpha) triangle strip representing the shadow. Return
  *                            empty strip if error.
 **/
 void SpotShadow::generateTriangleStrip(const Vector2* penumbra, int penumbraLength,
-        const Vector2* umbra, int umbraLength, int rays, int layers,
-        float strength, VertexBuffer& shadowTriangleStrip) {
+        const Vector2* umbra, int umbraLength, VertexBuffer& shadowTriangleStrip) {
+    const int rays = SHADOW_RAY_COUNT;
+    const int layers = SHADOW_LAYER_COUNT;
 
-    int rings = layers + 1;
-    int size = rays * rings;
-
+    int size = rays * (layers + 1);
     float step = M_PI * 2 / rays;
     // Centroid of the umbra.
-    Vector2 centroid = centroid2d(umbra, umbraLength);
+    Vector2 centroid = ShadowTessellator::centroid2d(umbra, umbraLength);
 #if DEBUG_SHADOW
     ALOGD("centroid2d =  %f , %f", centroid.x, centroid.y);
 #endif
@@ -741,57 +704,29 @@
     int stripSize = getStripSize(rays, layers);
     AlphaVertex* shadowVertices = shadowTriangleStrip.alloc<AlphaVertex>(stripSize);
     int currentIndex = 0;
-    int firstInLayer = 0;
-    // Calculate the vertex values in the penumbra area.
-    for (int r = 0; r < layers; r++) {
-        firstInLayer = currentIndex;
-        for (int i = 0; i < rays; i++) {
-            float dx = sinf(step * i);
-            float dy = cosf(step * i);
 
-            for (int j = r; j < (r + 2); j++) {
-                float layerRatio = j / (float)(rings - 1);
-                float deltaDist = layerRatio * (umbraDistPerRay[i] - penumbraDistPerRay[i]);
-                float currentDist = penumbraDistPerRay[i] + deltaDist;
-                float op = calculateOpacity(layerRatio, deltaDist);
+    // Calculate the vertices (x, y, alpha) in the shadow area.
+    for (int layerIndex = 0; layerIndex <= layers; layerIndex++) {
+        for (int rayIndex = 0; rayIndex < rays; rayIndex++) {
+            float dx = sinf(step * rayIndex);
+            float dy = cosf(step * rayIndex);
+                float layerRatio = layerIndex / (float) layers;
+                float deltaDist = layerRatio *
+                        (umbraDistPerRay[rayIndex] - penumbraDistPerRay[rayIndex]);
+                float currentDist = penumbraDistPerRay[rayIndex] + deltaDist;
+                float op = calculateOpacity(layerRatio);
                 AlphaVertex::set(&shadowVertices[currentIndex++],
-                        dx * currentDist + centroid.x,
-                        dy * currentDist + centroid.y,
-                        layerRatio * op * strength);
-            }
+                        dx * currentDist + centroid.x, dy * currentDist + centroid.y, op);
         }
-
-        // Duplicate the vertices from one layer to another one to make triangle
-        // strip.
-        shadowVertices[currentIndex++] = shadowVertices[firstInLayer + 0];
-        shadowVertices[currentIndex++] = shadowVertices[firstInLayer + 1];
     }
-
-    int lastInPenumbra = currentIndex - 1;
-    shadowVertices[currentIndex++] = shadowVertices[lastInPenumbra];
-
-    // Preallocate the vertices (index as [firstInUmbra - 1]) for jumping from
-    // the penumbra to umbra.
-    currentIndex++;
-    int firstInUmbra = currentIndex;
-
-    // traverse the umbra area in a zig zag pattern for strips.
-    const int innerRingStartIndex = firstInLayer + 1;
-    for (int k = 0; k < rays; k++) {
-        int i = k / 2;
-        if ((k & 1) == 1) {
-            i = rays - i - 1;
-        }
-        // copy already computed values for umbra vertices
-        shadowVertices[currentIndex++] = shadowVertices[innerRingStartIndex + i * 2];
-    }
-
-    // Back fill the one vertex for jumping from penumbra to umbra.
-    shadowVertices[firstInUmbra - 1] = shadowVertices[firstInUmbra];
-
+    // The centroid is in the umbra area, so the opacity is considered as 1.0.
+    AlphaVertex::set(&shadowVertices[currentIndex++], centroid.x, centroid.y, 1.0);
 #if DEBUG_SHADOW
+    if (currentIndex != SHADOW_VERTEX_COUNT) {
+        ALOGE("number of vertex generated for spot shadow is wrong!");
+    }
     for (int i = 0; i < currentIndex; i++) {
-        ALOGD("shadow value: i %d, (x:%f, y:%f, a:%f)", i, shadowVertices[i].x,
+        ALOGD("spot shadow value: i %d, (x:%f, y:%f, a:%f)", i, shadowVertices[i].x,
                 shadowVertices[i].y, shadowVertices[i].alpha);
     }
 #endif
@@ -819,17 +754,15 @@
 }
 
 /**
- * Calculate the opacity according to the distance and falloff ratio.
+ * Calculate the opacity according to the distance. Ideally, the opacity is 1.0
+ * in the umbra area, and fall off to 0.0 till the edge of penumbra area.
  *
- * @param distRatio The distance ratio of current sample between umbra and
- *                  penumbra area.
- * @param deltaDist The distance between current sample to the penumbra area.
+ * @param layerRatio The distance ratio of current sample between umbra and penumbra area.
+ *                   Penumbra edge is 0 and umbra edge is 1.
  * @return The opacity according to the distance between umbra and penumbra.
  */
-float SpotShadow::calculateOpacity(float distRatio, float deltaDist) {
-    // TODO: Experiment on the opacity calculation.
-    float falloffRatio = 1 + deltaDist * deltaDist;
-    return (distRatio + 1 - 1 / falloffRatio) / 2;
+float SpotShadow::calculateOpacity(float layerRatio) {
+    return (layerRatio * layerRatio + layerRatio) / 2.0;
 }
 
 /**
diff --git a/libs/hwui/SpotShadow.h b/libs/hwui/SpotShadow.h
index a50d110..6727eac 100644
--- a/libs/hwui/SpotShadow.h
+++ b/libs/hwui/SpotShadow.h
@@ -28,24 +28,22 @@
 public:
     static void createSpotShadow(const Vector3* poly, int polyLength,
             const Vector3& lightCenter, float lightSize, int lightVertexCount,
-            int rays, int layers, float strength, VertexBuffer& retStrips);
+            VertexBuffer& retStrips);
 
 private:
     static void computeSpotShadow(const Vector3* lightPoly, int lightPolyLength,
             const Vector3& lightCenter, const Vector3* poly, int polyLength,
-            int rays, int layers, float strength, VertexBuffer& retstrips);
+            VertexBuffer& retstrips);
 
     static void computeLightPolygon(int points, const Vector3& lightCenter,
             float size, Vector3* ret);
 
     static int  getStripSize(int rays, int layers);
     static void smoothPolygon(int level, int rays, float* rayDist);
-    static float calculateOpacity(float jf, float deltaDist);
+    static float calculateOpacity(float jf);
     static float rayIntersectPoly(const Vector2* poly, int polyLength,
             const Vector2& point, float dx, float dy);
 
-    static Vector2 centroid2d(const Vector2* poly, int polyLength);
-
     static void xsort(Vector2* points, int pointsLength);
     static int hull(Vector2* points, int pointsLength, Vector2* retPoly);
     static bool ccw(double ax, double ay, double bx, double by, double cx, double cy);
@@ -65,8 +63,7 @@
             double x3, double y3, double x4, double y4, Vector2& ret);
 
     static void generateTriangleStrip(const Vector2* penumbra, int penumbraLength,
-            const Vector2* umbra, int umbraLength, int rays, int layers,
-            float strength, VertexBuffer& retstrips);
+            const Vector2* umbra, int umbraLength, VertexBuffer& retstrips);
 
     static const double EPSILON = 1e-7;
 
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 467f6ca..01d72d1 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -184,7 +184,9 @@
     Mutex::Autolock _l(mLock);
     size_t count = mGarbage.size();
     for (size_t i = 0; i < count; i++) {
-        mCache.remove(mGarbage.itemAt(i));
+        const SkBitmap* bitmap = mGarbage.itemAt(i);
+        mCache.remove(bitmap);
+        delete bitmap;
     }
     mGarbage.clear();
 }
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index fe781bd..0568851 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -373,6 +373,10 @@
     mCanvas->setViewport(width, height);
 }
 
+void CanvasContext::swapDisplayListData(DisplayList* displayList, DisplayListData* newData) {
+    displayList->setData(newData);
+}
+
 void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters) {
     mGlobalContext->makeCurrent(mEglSurface);
     for (size_t i = 0; i < layerUpdaters->size(); i++) {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 5fac582..2c9348c 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -32,6 +32,7 @@
 
 class DeferredLayerUpdater;
 class DisplayList;
+class DisplayListData;
 class OpenGLRenderer;
 class Rect;
 
@@ -62,6 +63,7 @@
     bool initialize(EGLNativeWindowType window);
     void updateSurface(EGLNativeWindowType window);
     void setup(int width, int height);
+    void swapDisplayListData(DisplayList* displayList, DisplayListData* newData);
     void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters);
     void drawDisplayList(DisplayList* displayList, Rect* dirty);
     void destroyCanvas();
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 0c667fd..c3bf404 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -117,6 +117,20 @@
     post(task);
 }
 
+CREATE_BRIDGE3(swapDisplayListData, CanvasContext* context, DisplayList* displayList,
+        DisplayListData* newData) {
+    args->context->swapDisplayListData(args->displayList, args->newData);
+    return NULL;
+}
+
+void RenderProxy::swapDisplayListData(DisplayList* displayList, DisplayListData* newData) {
+    SETUP_TASK(swapDisplayListData);
+    args->context = mContext;
+    args->displayList = displayList;
+    args->newData = newData;
+    post(task);
+}
+
 CREATE_BRIDGE4(drawDisplayList, CanvasContext* context, DisplayList* displayList,
         Rect dirty, const Vector<DeferredLayerUpdater*>* layerUpdates) {
     Rect* dirty = &args->dirty;
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 8ff3d63..0934b98 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -33,6 +33,7 @@
 
 class DeferredLayerUpdater;
 class DisplayList;
+class DisplayListData;
 class Layer;
 class Rect;
 
@@ -59,6 +60,7 @@
     ANDROID_API bool initialize(EGLNativeWindowType window);
     ANDROID_API void updateSurface(EGLNativeWindowType window);
     ANDROID_API void setup(int width, int height);
+    ANDROID_API void swapDisplayListData(DisplayList* displayList, DisplayListData* newData);
     ANDROID_API void drawDisplayList(DisplayList* displayList,
             int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
     ANDROID_API void destroyCanvas();
diff --git a/libs/input/Android.mk b/libs/input/Android.mk
index 6011ff0..a7fb0e2 100644
--- a/libs/input/Android.mk
+++ b/libs/input/Android.mk
@@ -31,7 +31,6 @@
 	libinputflinger
 
 LOCAL_C_INCLUDES := \
-    external/skia/include/core \
     frameworks/native/services
 
 
diff --git a/libs/usb/tests/AccessoryChat/accessorychat/Android.mk b/libs/usb/tests/AccessoryChat/accessorychat/Android.mk
index 300224a..3e07155 100644
--- a/libs/usb/tests/AccessoryChat/accessorychat/Android.mk
+++ b/libs/usb/tests/AccessoryChat/accessorychat/Android.mk
@@ -11,7 +11,6 @@
 
 LOCAL_MODULE := accessorychat
 
-LOCAL_C_INCLUDES += bionic/libc/kernel/common
 LOCAL_STATIC_LIBRARIES := libusbhost libcutils
 LOCAL_LDLIBS += -lpthread
 LOCAL_CFLAGS := -g -O0
diff --git a/libs/usb/tests/AccessoryChat/accessorychat/linux/usb/f_accessory.h b/libs/usb/tests/AccessoryChat/accessorychat/linux/usb/f_accessory.h
new file mode 100644
index 0000000..75e017c
--- /dev/null
+++ b/libs/usb/tests/AccessoryChat/accessorychat/linux/usb/f_accessory.h
@@ -0,0 +1,53 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_LINUX_USB_F_ACCESSORY_H
+#define _UAPI_LINUX_USB_F_ACCESSORY_H
+#define USB_ACCESSORY_VENDOR_ID 0x18D1
+#define USB_ACCESSORY_PRODUCT_ID 0x2D00
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define USB_ACCESSORY_ADB_PRODUCT_ID 0x2D01
+#define ACCESSORY_STRING_MANUFACTURER 0
+#define ACCESSORY_STRING_MODEL 1
+#define ACCESSORY_STRING_DESCRIPTION 2
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ACCESSORY_STRING_VERSION 3
+#define ACCESSORY_STRING_URI 4
+#define ACCESSORY_STRING_SERIAL 5
+#define ACCESSORY_GET_PROTOCOL 51
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ACCESSORY_SEND_STRING 52
+#define ACCESSORY_START 53
+#define ACCESSORY_REGISTER_HID 54
+#define ACCESSORY_UNREGISTER_HID 55
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ACCESSORY_SET_HID_REPORT_DESC 56
+#define ACCESSORY_SEND_HID_EVENT 57
+#define ACCESSORY_SET_AUDIO_MODE 58
+#define ACCESSORY_GET_STRING_MANUFACTURER _IOW('M', 1, char[256])
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ACCESSORY_GET_STRING_MODEL _IOW('M', 2, char[256])
+#define ACCESSORY_GET_STRING_DESCRIPTION _IOW('M', 3, char[256])
+#define ACCESSORY_GET_STRING_VERSION _IOW('M', 4, char[256])
+#define ACCESSORY_GET_STRING_URI _IOW('M', 5, char[256])
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define ACCESSORY_GET_STRING_SERIAL _IOW('M', 6, char[256])
+#define ACCESSORY_IS_START_REQUESTED _IO('M', 7)
+#define ACCESSORY_GET_AUDIO_MODE _IO('M', 8)
+#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index ccb4304..36778aa 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -28,6 +28,7 @@
 import android.util.Log;
 
 
+import java.lang.SecurityException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -1104,13 +1105,18 @@
      * unless they depend on provider-specific APIs such as
      * {@link #requestLocationUpdates(String, long, float, LocationListener)}.
      *
+     * <p>
+     * Before API version 20, this method would throw {@link SecurityException}
+     * if the location permissions were not sufficient to use the specified
+     * provider.
+     *
      * @param provider the name of the provider
      * @return true if the provider exists and is enabled
      *
      * @throws IllegalArgumentException if provider is null
-     * @throws SecurityException if no suitable permission is present
      */
     public boolean isProviderEnabled(String provider) {
+        // STOPSHIP: finalize API version number in javadoc
         checkProvider(provider);
 
         try {
@@ -1610,7 +1616,7 @@
      * @hide
      */
     public boolean sendNiResponse(int notifId, int userResponse) {
-    	try {
+        try {
             return mService.sendNiResponse(notifId, userResponse);
         } catch (RemoteException e) {
             Log.e(TAG, "RemoteException in sendNiResponse: ", e);
diff --git a/location/java/android/location/SettingInjectorService.java b/location/java/android/location/SettingInjectorService.java
index 9f321f3..98c7864 100644
--- a/location/java/android/location/SettingInjectorService.java
+++ b/location/java/android/location/SettingInjectorService.java
@@ -26,7 +26,7 @@
 import android.util.Log;
 
 /**
- * Dynamically specifies the summary (subtitle) and enabled status of a preference injected into
+ * Dynamically specifies the enabled status of a preference injected into
  * the list of app settings displayed by the system settings app
  * <p/>
  * For use only by apps that are included in the system image, for preferences that affect multiple
@@ -71,13 +71,12 @@
  * </ul>
  *
  * To ensure a good user experience, your {@link android.app.Application#onCreate()},
- * {@link #onGetSummary()}, and {@link #onGetEnabled()} methods must all be fast. If any are slow,
- * it can delay the display of settings values for other apps as well. Note further that all are
- * called on your app's UI thread.
+ * and {@link #onGetEnabled()} methods must all be fast. If either is slow,
+ * it can delay the display of settings values for other apps as well. Note further that these
+ * methods are called on your app's UI thread.
  * <p/>
  * For compactness, only one copy of a given setting should be injected. If each account has a
- * distinct value for the setting, then the {@link #onGetSummary()} value should represent a summary
- * of the state across all of the accounts and {@code settingsActivity} should display the value for
+ * distinct value for the setting, then only {@code settingsActivity} should display the value for
  * each account.
  */
 public abstract class SettingInjectorService extends Service {
@@ -109,14 +108,6 @@
             "android.location.InjectedSettingChanged";
 
     /**
-     * Name of the bundle key for the string specifying the summary for the setting (e.g., "ON" or
-     * "OFF").
-     *
-     * @hide
-     */
-    public static final String SUMMARY_KEY = "summary";
-
-    /**
      * Name of the bundle key for the string specifying whether the setting is currently enabled.
      *
      * @hide
@@ -160,42 +151,31 @@
 
     private void onHandleIntent(Intent intent) {
 
-        String summary;
-        try {
-            summary = onGetSummary();
-        } catch (RuntimeException e) {
-            // Exception. Send status anyway, so that settings injector can immediately start
-            // loading the status of the next setting.
-            sendStatus(intent, null, true);
-            throw e;
-        }
-
         boolean enabled;
         try {
             enabled = onGetEnabled();
         } catch (RuntimeException e) {
             // Exception. Send status anyway, so that settings injector can immediately start
             // loading the status of the next setting.
-            sendStatus(intent, summary, true);
+            sendStatus(intent, true);
             throw e;
         }
 
-        sendStatus(intent, summary, enabled);
+        sendStatus(intent, enabled);
     }
 
     /**
-     * Send the summary and enabled values back to the caller via the messenger encoded in the
+     * Send the enabled values back to the caller via the messenger encoded in the
      * intent.
      */
-    private void sendStatus(Intent intent, String summary, boolean enabled) {
+    private void sendStatus(Intent intent, boolean enabled) {
         Message message = Message.obtain();
         Bundle bundle = new Bundle();
-        bundle.putString(SUMMARY_KEY, summary);
         bundle.putBoolean(ENABLED_KEY, enabled);
         message.setData(bundle);
 
         if (Log.isLoggable(TAG, Log.DEBUG)) {
-            Log.d(TAG, mName + ": received " + intent + ", summary=" + summary
+            Log.d(TAG, mName + ": received " + intent
                     + ", enabled=" + enabled + ", sending message: " + message);
         }
 
@@ -208,13 +188,18 @@
     }
 
     /**
-     * Returns the {@link android.preference.Preference#getSummary()} value (allowed to be null or
-     * empty). Should not perform unpredictably-long operations such as network access--see the
-     * running-time comments in the class-level javadoc.
+     * This method is no longer called, because status values are no longer shown for any injected
+     * setting.
      *
-     * @return the {@link android.preference.Preference#getSummary()} value
+     * @return ignored
+     *
+     * @deprecated not called any more
      */
-    protected abstract String onGetSummary();
+    @Deprecated
+    protected String onGetSummary() {
+        // Do not delete until no callers have @Override annotations for this method
+        return null;
+    }
 
     /**
      * Returns the {@link android.preference.Preference#isEnabled()} value. Should not perform
diff --git a/media/java/android/media/IMediaController.aidl b/media/java/android/media/IMediaController.aidl
deleted file mode 100644
index fc3525a..0000000
--- a/media/java/android/media/IMediaController.aidl
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Copyright (C) 2014 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.content.Intent;
-import android.media.IMediaControllerCallback;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.view.KeyEvent;
-
-/**
- * Interface to a MediaSession in the system.
- * @hide
- */
-interface IMediaController {
-    void sendCommand(String command, in Bundle extras);
-    void sendMediaButton(in KeyEvent mediaButton);
-    void registerCallbackListener(in IMediaControllerCallback cb);
-    void unregisterCallbackListener(in IMediaControllerCallback cb);
-    int getPlaybackState();
-}
\ No newline at end of file
diff --git a/media/java/android/media/IMediaControllerCallback.aidl b/media/java/android/media/IMediaControllerCallback.aidl
deleted file mode 100644
index b54d0cf..0000000
--- a/media/java/android/media/IMediaControllerCallback.aidl
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Copyright (C) 2014 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.Bundle;
-
-/**
- * @hide
- */
-oneway interface IMediaControllerCallback {
-    void onEvent(String event, in Bundle extras);
-    void onMetadataUpdate(in Bundle metadata);
-    void onPlaybackUpdate(int newState);
-    void onRouteChanged(in Bundle route);
-}
\ No newline at end of file
diff --git a/media/java/android/media/IMediaHTTPConnection.aidl b/media/java/android/media/IMediaHTTPConnection.aidl
index 300211b..55ffc2e 100644
--- a/media/java/android/media/IMediaHTTPConnection.aidl
+++ b/media/java/android/media/IMediaHTTPConnection.aidl
@@ -29,5 +29,6 @@
     int readAt(long offset, int size);
     long getSize();
     String getMIMEType();
+    String getUri();
 }
 
diff --git a/media/java/android/media/IMediaSession.aidl b/media/java/android/media/IMediaSession.aidl
deleted file mode 100644
index ed71d78..0000000
--- a/media/java/android/media/IMediaSession.aidl
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Copyright (C) 2014 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.media.IMediaController;
-import android.os.Bundle;
-
-/**
- * Interface to a MediaSession in the system.
- * @hide
- */
-interface IMediaSession {
-    void sendEvent(in Bundle data);
-    IMediaController getMediaSessionToken();
-    void setPlaybackState(int state);
-    void setMetadata(in Bundle metadata);
-    void setRouteState(in Bundle routeState);
-    void setRoute(in Bundle mediaRouteDescriptor);
-    void destroy();
-}
\ No newline at end of file
diff --git a/media/java/android/media/IMediaSessionCallback.aidl b/media/java/android/media/IMediaSessionCallback.aidl
deleted file mode 100644
index 3aaf925..0000000
--- a/media/java/android/media/IMediaSessionCallback.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Copyright (C) 2014 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.content.Intent;
-import android.os.Bundle;
-import android.os.IBinder;
-
-/**
- * @hide
- */
-oneway interface IMediaSessionCallback {
-    void onCommand(String command, in Bundle extras);
-    void onMediaButton(in Intent mediaRequestIntent);
-    void onRequestRouteChange(in Bundle route);
-}
\ No newline at end of file
diff --git a/media/java/android/media/IMediaSessionManager.aidl b/media/java/android/media/IMediaSessionManager.aidl
deleted file mode 100644
index 8bc0c3b..0000000
--- a/media/java/android/media/IMediaSessionManager.aidl
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Copyright (C) 2014 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.media.IMediaSession;
-import android.media.IMediaSessionCallback;
-import android.os.Bundle;
-
-/**
- * Interface to the MediaSessionManagerService
- * @hide
- */
-interface IMediaSessionManager {
-    IMediaSession createSession(String packageName, in IMediaSessionCallback cb, String tag);
-}
\ No newline at end of file
diff --git a/media/java/android/media/MediaController.java b/media/java/android/media/MediaController.java
deleted file mode 100644
index 1e99942..0000000
--- a/media/java/android/media/MediaController.java
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * Copyright (C) 2014 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.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.KeyEvent;
-
-import java.util.ArrayList;
-
-/**
- * Allows an app to interact with an ongoing media session. Media buttons and
- * other commands can be sent to the session. A callback may be registered to
- * receive updates from the session, such as metadata and play state changes.
- * <p>
- * A MediaController can be created through {@link MediaSessionManager} if you
- * hold the "android.permission.MEDIA_CONTENT_CONTROL" permission or directly if
- * you have a {@link MediaSessionToken} from the session owner.
- * <p>
- * MediaController objects are thread-safe.
- */
-public final class MediaController {
-    private static final String TAG = "MediaController";
-
-    private static final int MESSAGE_EVENT = 1;
-    private static final int MESSAGE_PLAYBACK_STATE = 2;
-    private static final int MESSAGE_METADATA = 3;
-    private static final int MESSAGE_ROUTE = 4;
-
-    private static final String KEY_EVENT = "event";
-    private static final String KEY_EXTRAS = "extras";
-
-    private final IMediaController mSessionBinder;
-
-    private final CallbackStub mCbStub = new CallbackStub();
-    private final ArrayList<Callback> mCbs = new ArrayList<Callback>();
-    private final Object mLock = new Object();
-
-    private boolean mCbRegistered = false;
-
-    /**
-     * If you have a {@link MediaSessionToken} from the owner of the session a
-     * controller can be created directly. It is up to the session creator to
-     * handle token distribution if desired.
-     *
-     * @see MediaSession#getSessionToken()
-     * @param token A token from the creator of the session
-     */
-    public MediaController(MediaSessionToken token) {
-        mSessionBinder = token.getBinder();
-    }
-
-    /**
-     * @hide
-     */
-    public MediaController(IMediaController sessionBinder) {
-        mSessionBinder = sessionBinder;
-    }
-
-    /**
-     * Sends a generic command to the session. It is up to the session creator
-     * to decide what commands and parameters they will support. As such,
-     * commands should only be sent to sessions that the controller owns.
-     *
-     * @param command The command to send
-     * @param params Any parameters to include with the command
-     */
-    public void sendCommand(String command, Bundle params) {
-        if (TextUtils.isEmpty(command)) {
-            throw new IllegalArgumentException("command cannot be null or empty");
-        }
-        try {
-            mSessionBinder.sendCommand(command, params);
-        } catch (RemoteException e) {
-            Log.d(TAG, "Dead object in sendCommand.", e);
-        }
-    }
-
-    /**
-     * Send the specified media button to the session. Only media keys can be
-     * sent using this method.
-     *
-     * @param keycode The media button keycode, such as
-     *            {@link KeyEvent#KEYCODE_MEDIA_PLAY}.
-     */
-    public void sendMediaButton(int keycode) {
-        if (!KeyEvent.isMediaKey(keycode)) {
-            throw new IllegalArgumentException("May only send media buttons through "
-                    + "sendMediaButton");
-        }
-        // TODO do something better than key down/up events
-        KeyEvent event = new KeyEvent(KeyEvent.ACTION_UP, keycode);
-        try {
-            mSessionBinder.sendMediaButton(event);
-        } catch (RemoteException e) {
-            Log.d(TAG, "Dead object in sendMediaButton", e);
-        }
-    }
-
-    /**
-     * Adds a callback to receive updates from the Session. Updates will be
-     * posted on the caller's thread.
-     *
-     * @param cb The callback object, must not be null
-     */
-    public void addCallback(Callback cb) {
-        addCallback(cb, null);
-    }
-
-    /**
-     * Adds a callback to receive updates from the session. Updates will be
-     * posted on the specified handler.
-     *
-     * @param cb Cannot be null.
-     * @param handler The handler to post updates on, if null the callers thread
-     *            will be used
-     */
-    public void addCallback(Callback cb, Handler handler) {
-        if (handler == null) {
-            handler = new Handler();
-        }
-        synchronized (mLock) {
-            addCallbackLocked(cb, handler);
-        }
-    }
-
-    /**
-     * Stop receiving updates on the specified callback. If an update has
-     * already been posted you may still receive it after calling this method.
-     *
-     * @param cb The callback to remove
-     */
-    public void removeCallback(Callback cb) {
-        synchronized (mLock) {
-            removeCallbackLocked(cb);
-        }
-    }
-
-    /*
-     * @hide
-     */
-    IMediaController getSessionBinder() {
-        return mSessionBinder;
-    }
-
-    private void addCallbackLocked(Callback cb, Handler handler) {
-        if (cb == null) {
-            throw new IllegalArgumentException("Callback cannot be null");
-        }
-        if (handler == null) {
-            throw new IllegalArgumentException("Handler cannot be null");
-        }
-        if (mCbs.contains(cb)) {
-            Log.w(TAG, "Callback is already added, ignoring");
-            return;
-        }
-        cb.setHandler(handler);
-        mCbs.add(cb);
-
-        // Only register one cb binder, track callbacks internally and notify
-        if (!mCbRegistered) {
-            try {
-                mSessionBinder.registerCallbackListener(mCbStub);
-                mCbRegistered = true;
-            } catch (RemoteException e) {
-                Log.d(TAG, "Dead object in registerCallback", e);
-            }
-        }
-    }
-
-    private void removeCallbackLocked(Callback cb) {
-        if (cb == null) {
-            throw new IllegalArgumentException("Callback cannot be null");
-        }
-        mCbs.remove(cb);
-
-        if (mCbs.size() == 0 && mCbRegistered) {
-            try {
-                mSessionBinder.unregisterCallbackListener(mCbStub);
-            } catch (RemoteException e) {
-                Log.d(TAG, "Dead object in unregisterCallback", e);
-            }
-            mCbRegistered = false;
-        }
-    }
-
-    private void pushOnEventLocked(String event, Bundle extras) {
-        for (int i = mCbs.size() - 1; i >= 0; i--) {
-            mCbs.get(i).postEvent(event, extras);
-        }
-    }
-
-    private void pushOnMetadataUpdateLocked(Bundle metadata) {
-        for (int i = mCbs.size() - 1; i >= 0; i--) {
-            mCbs.get(i).postMetadataUpdate(metadata);
-        }
-    }
-
-    private void pushOnPlaybackUpdateLocked(int newState) {
-        for (int i = mCbs.size() - 1; i >= 0; i--) {
-            mCbs.get(i).postPlaybackStateChange(newState);
-        }
-    }
-
-    private void pushOnRouteChangedLocked(Bundle routeDescriptor) {
-        for (int i = mCbs.size() - 1; i >= 0; i--) {
-            mCbs.get(i).postRouteChanged(routeDescriptor);
-        }
-    }
-
-    /**
-     * MediaSession callbacks will be posted on the thread that created the
-     * Callback object.
-     */
-    public static abstract class Callback {
-        private Handler mHandler;
-
-        /**
-         * Override to handle custom events sent by the session owner.
-         * Controllers should only handle these for sessions they own.
-         *
-         * @param event
-         */
-        public void onEvent(String event, Bundle extras) {
-        }
-
-        /**
-         * Override to handle updates to the playback state. Valid values are in
-         * {@link RemoteControlClient}. TODO put playstate values somewhere more
-         * generic.
-         *
-         * @param state
-         */
-        public void onPlaybackStateChange(int state) {
-        }
-
-        /**
-         * Override to handle metadata changes for this session's media. The
-         * default supported fields are those in {@link MediaMetadataRetriever}.
-         *
-         * @param metadata
-         */
-        public void onMetadataUpdate(Bundle metadata) {
-        }
-
-        /**
-         * Override to handle route changes for this session.
-         *
-         * @param route
-         */
-        public void onRouteChanged(Bundle route) {
-        }
-
-        private void setHandler(Handler handler) {
-            mHandler = new MessageHandler(handler.getLooper(), this);
-        }
-
-        private void postEvent(String event, Bundle extras) {
-            Bundle eventBundle = new Bundle();
-            eventBundle.putString(KEY_EVENT, event);
-            eventBundle.putBundle(KEY_EXTRAS, extras);
-            Message msg = mHandler.obtainMessage(MESSAGE_EVENT, eventBundle);
-            mHandler.sendMessage(msg);
-        }
-
-        private void postPlaybackStateChange(final int state) {
-            Message msg = mHandler.obtainMessage(MESSAGE_PLAYBACK_STATE, state, 0);
-            mHandler.sendMessage(msg);
-        }
-
-        private void postMetadataUpdate(final Bundle metadata) {
-            Message msg = mHandler.obtainMessage(MESSAGE_METADATA, metadata);
-            mHandler.sendMessage(msg);
-        }
-
-        private void postRouteChanged(final Bundle descriptor) {
-            Message msg = mHandler.obtainMessage(MESSAGE_ROUTE, descriptor);
-            mHandler.sendMessage(msg);
-        }
-    }
-
-    private final class CallbackStub extends IMediaControllerCallback.Stub {
-
-        @Override
-        public void onEvent(String event, Bundle extras) throws RemoteException {
-            synchronized (mLock) {
-                pushOnEventLocked(event, extras);
-            }
-        }
-
-        @Override
-        public void onMetadataUpdate(Bundle metadata) throws RemoteException {
-            synchronized (mLock) {
-                pushOnMetadataUpdateLocked(metadata);
-            }
-        }
-
-        @Override
-        public void onPlaybackUpdate(final int newState) throws RemoteException {
-            synchronized (mLock) {
-                pushOnPlaybackUpdateLocked(newState);
-            }
-        }
-
-        @Override
-        public void onRouteChanged(Bundle mediaRouteDescriptor) throws RemoteException {
-            synchronized (mLock) {
-                pushOnRouteChangedLocked(mediaRouteDescriptor);
-            }
-        }
-
-    }
-
-    private final static class MessageHandler extends Handler {
-        private final MediaController.Callback mCb;
-
-        public MessageHandler(Looper looper, MediaController.Callback cb) {
-            super(looper);
-            mCb = cb;
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MESSAGE_EVENT:
-                    Bundle eventBundle = (Bundle) msg.obj;
-                    String event = eventBundle.getString(KEY_EVENT);
-                    Bundle extras = eventBundle.getBundle(KEY_EXTRAS);
-                    mCb.onEvent(event, extras);
-                    break;
-                case MESSAGE_PLAYBACK_STATE:
-                    mCb.onPlaybackStateChange(msg.arg1);
-                    break;
-                case MESSAGE_METADATA:
-                    mCb.onMetadataUpdate((Bundle) msg.obj);
-                    break;
-                case MESSAGE_ROUTE:
-                    mCb.onRouteChanged((Bundle) msg.obj);
-            }
-        }
-    }
-
-}
diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java
index 2732fbc..67680a8 100644
--- a/media/java/android/media/MediaHTTPConnection.java
+++ b/media/java/android/media/MediaHTTPConnection.java
@@ -16,7 +16,6 @@
 
 package android.media;
 
-import android.net.Uri;
 import android.os.IBinder;
 import android.os.StrictMode;
 import android.util.Log;
@@ -52,6 +51,7 @@
         native_setup();
     }
 
+    @Override
     public IBinder connect(String uri, String headers) {
         if (VERBOSE) {
             Log.d(TAG, "connect: uri=" + uri + ", headers=" + headers);
@@ -85,6 +85,7 @@
         return map;
     }
 
+    @Override
     public void disconnect() {
         teardownConnection();
         mHeaders = null;
@@ -120,7 +121,11 @@
                         "Range", "bytes=" + offset + "-");
             }
 
-            if (mConnection.getResponseCode() == HttpURLConnection.HTTP_PARTIAL) {
+            int response = mConnection.getResponseCode();
+            // remember the current, possibly redirected URL
+            mURL = mConnection.getURL();
+
+            if (response == HttpURLConnection.HTTP_PARTIAL) {
                 // Partial content, we cannot just use getContentLength
                 // because what we want is not just the length of the range
                 // returned but the size of the full content if available.
@@ -145,16 +150,13 @@
                         }
                     }
                 }
-            } else if (mConnection.getResponseCode()
-                    != HttpURLConnection.HTTP_OK) {
+            } else if (response != HttpURLConnection.HTTP_OK) {
                 throw new IOException();
             } else {
                 mTotalSize = mConnection.getContentLength();
             }
 
-            if (offset > 0
-                    && mConnection.getResponseCode()
-                            != HttpURLConnection.HTTP_PARTIAL) {
+            if (offset > 0 && response != HttpURLConnection.HTTP_PARTIAL) {
                 // Some servers simply ignore "Range" requests and serve
                 // data from the start of the content.
                 throw new IOException();
@@ -174,6 +176,7 @@
         }
     }
 
+    @Override
     public int readAt(long offset, int size) {
         return native_readAt(offset, size);
     }
@@ -218,6 +221,7 @@
         }
     }
 
+    @Override
     public long getSize() {
         if (mConnection == null) {
             try {
@@ -230,6 +234,7 @@
         return mTotalSize;
     }
 
+    @Override
     public String getMIMEType() {
         if (mConnection == null) {
             try {
@@ -243,6 +248,11 @@
     }
 
     @Override
+    public String getUri() {
+        return mURL.toString();
+    }
+
+    @Override
     protected void finalize() {
         native_finalize();
     }
@@ -260,4 +270,5 @@
     }
 
     private int mNativeContext;
+
 }
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index f8a7bb6..21e2f4b 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -417,8 +417,8 @@
         setParameter("time-lapse-enable=1");
 
         double timeBetweenFrameCapture = 1 / fps;
-        int timeBetweenFrameCaptureMs = (int) (1000 * timeBetweenFrameCapture);
-        setParameter("time-between-time-lapse-frame-capture=" + timeBetweenFrameCaptureMs);
+        long timeBetweenFrameCaptureUs = (long) (1000000 * timeBetweenFrameCapture);
+        setParameter("time-between-time-lapse-frame-capture=" + timeBetweenFrameCaptureUs);
     }
 
     /**
diff --git a/media/java/android/media/MediaSession.java b/media/java/android/media/MediaSession.java
deleted file mode 100644
index 5e5c9fa..0000000
--- a/media/java/android/media/MediaSession.java
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright (C) 2014 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.content.Intent;
-import android.media.IMediaSession;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.ArrayList;
-
-/**
- * Allows interaction with media controllers, media routes, volume keys, media
- * buttons, and transport controls.
- * <p>
- * A MediaSession should be created when an app wants to publish media playback
- * information or negotiate with a media route. In general an app only needs one
- * session for all playback, though multiple sessions can be created for sending
- * media to multiple routes or to provide finer grain controls of media.
- * <p>
- * A MediaSession is created by calling
- * {@link MediaSessionManager#createSession(String)}. Once a session is created
- * apps that have the MEDIA_CONTENT_CONTROL permission can interact with the
- * session through {@link MediaSessionManager#getActiveSessions()}. The owner of
- * the session may also use {@link #getSessionToken()} to allow apps without
- * this permission to create a {@link MediaController} to interact with this
- * session.
- * <p>
- * To receive commands, media keys, and other events a Callback must be set with
- * {@link #addCallback(Callback)}.
- * <p>
- * When an app is finished performing playback it must call {@link #release()}
- * to clean up the session and notify any controllers.
- * <p>
- * MediaSession objects are thread safe
- */
-public final class MediaSession {
-    private static final String TAG = "MediaSession";
-
-    private static final int MESSAGE_MEDIA_BUTTON = 1;
-    private static final int MESSAGE_COMMAND = 2;
-    private static final int MESSAGE_ROUTE_CHANGE = 3;
-
-    private static final String KEY_COMMAND = "command";
-    private static final String KEY_EXTRAS = "extras";
-
-    private final Object mLock = new Object();
-
-    private final MediaSessionToken mSessionToken;
-    private final IMediaSession mBinder;
-    private final CallbackStub mCbStub;
-
-    private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
-
-    /**
-     * @hide
-     */
-    public MediaSession(IMediaSession binder, CallbackStub cbStub) {
-        mBinder = binder;
-        mCbStub = cbStub;
-        IMediaController controllerBinder = null;
-        try {
-            controllerBinder = mBinder.getMediaSessionToken();
-        } catch (RemoteException e) {
-            throw new RuntimeException("Dead object in MediaSessionController constructor: ", e);
-        }
-        mSessionToken = new MediaSessionToken(controllerBinder);
-    }
-
-    /**
-     * Set the callback to receive updates on.
-     *
-     * @param callback The callback object
-     */
-    public void addCallback(Callback callback) {
-        addCallback(callback, null);
-    }
-
-    public void addCallback(Callback callback, Handler handler) {
-        if (callback == null) {
-            throw new IllegalArgumentException("Callback cannot be null");
-        }
-        synchronized (mLock) {
-            if (mCallbacks.contains(callback)) {
-                Log.w(TAG, "Callback is already added, ignoring");
-            }
-            if (handler == null) {
-                handler = new Handler();
-            }
-            MessageHandler msgHandler = new MessageHandler(handler.getLooper(), callback);
-            callback.setHandler(msgHandler);
-            mCallbacks.add(callback);
-        }
-    }
-
-    public void removeCallback(Callback callback) {
-        mCallbacks.remove(callback);
-    }
-
-    /**
-     * Publish the current playback state to the system and any controllers.
-     * Valid values are defined in {@link RemoteControlClient}. TODO move play
-     * states somewhere else.
-     *
-     * @param state
-     */
-    public void setPlaybackState(int state) {
-        try {
-            mBinder.setPlaybackState(state);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in setPlaybackState: ", e);
-        }
-    }
-
-    /**
-     * This must be called when an app has finished performing playback. If
-     * playback is expected to start again shortly the session can be left open,
-     * but it must be released if your activity or service is being destroyed.
-     */
-    public void release() {
-        try {
-            mBinder.destroy();
-        } catch (RemoteException e) {
-            Log.e(TAG, "Dead object in onDestroy: ", e);
-        }
-    }
-
-    /**
-     * Retrieve a token object that can be used by apps to create a
-     * {@link MediaController} for interacting with this session. The owner of
-     * the session is responsible for deciding how to distribute these tokens.
-     *
-     * @return A token that can be used to create a MediaController for this
-     *         session
-     */
-    public MediaSessionToken getSessionToken() {
-        return mSessionToken;
-    }
-
-    private void postCommand(String command, Bundle extras) {
-        Bundle commandBundle = new Bundle();
-        commandBundle.putString(KEY_COMMAND, command);
-        commandBundle.putBundle(KEY_EXTRAS, extras);
-        synchronized (mLock) {
-            for (int i = mCallbacks.size() - 1; i >= 0; i--) {
-                Callback cb = mCallbacks.get(i);
-                Message msg = cb.mHandler.obtainMessage(MESSAGE_COMMAND, commandBundle);
-                cb.mHandler.sendMessage(msg);
-            }
-        }
-    }
-
-    private void postMediaButton(Intent mediaButtonIntent) {
-        synchronized (mLock) {
-            for (int i = mCallbacks.size() - 1; i >= 0; i--) {
-                Callback cb = mCallbacks.get(i);
-                Message msg = cb.mHandler.obtainMessage(MESSAGE_MEDIA_BUTTON, mediaButtonIntent);
-                cb.mHandler.sendMessage(msg);
-            }
-        }
-    }
-
-    private void postRequestRouteChange(Bundle mediaRouteDescriptor) {
-        synchronized (mLock) {
-            for (int i = mCallbacks.size() - 1; i >= 0; i--) {
-                Callback cb = mCallbacks.get(i);
-                Message msg = cb.mHandler.obtainMessage(MESSAGE_ROUTE_CHANGE, mediaRouteDescriptor);
-                cb.mHandler.sendMessage(msg);
-            }
-        }
-    }
-
-    /**
-     * Receives commands or updates from controllers and routes. An app can
-     * specify what commands and buttons it supports by setting them on the
-     * MediaSession (TODO).
-     */
-    public abstract static class Callback {
-        private MessageHandler mHandler;
-
-        public Callback() {
-        }
-
-        /**
-         * Called when a media button is pressed and this session has the
-         * highest priority or a controller sends a media button event to the
-         * session. TODO determine if using Intents identical to the ones
-         * RemoteControlClient receives is useful
-         * <p>
-         * The intent will be of type {@link Intent#ACTION_MEDIA_BUTTON} with a
-         * KeyEvent in {@link Intent#EXTRA_KEY_EVENT}
-         *
-         * @param mediaButtonIntent an intent containing the KeyEvent as an
-         *            extra
-         */
-        public void onMediaButton(Intent mediaButtonIntent) {
-        }
-
-        /**
-         * Called when a controller has sent a custom command to this session.
-         * The owner of the session may handle custom commands but is not
-         * required to.
-         *
-         * @param command
-         * @param extras optional
-         */
-        public void onCommand(String command, Bundle extras) {
-        }
-
-        /**
-         * Called when the user has selected a different route to connect to.
-         * The app is responsible for connecting to the new route and migrating
-         * ongoing playback if necessary.
-         *
-         * @param descriptor
-         */
-        public void onRequestRouteChange(Bundle descriptor) {
-        }
-
-        private void setHandler(MessageHandler handler) {
-            mHandler = handler;
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public static class CallbackStub extends IMediaSessionCallback.Stub {
-        private MediaSession mMediaSession;
-
-        public void setMediaSession(MediaSession session) {
-            mMediaSession = session;
-        }
-
-        @Override
-        public void onCommand(String command, Bundle extras) throws RemoteException {
-            mMediaSession.postCommand(command, extras);
-        }
-
-        @Override
-        public void onMediaButton(Intent mediaButtonIntent) throws RemoteException {
-            mMediaSession.postMediaButton(mediaButtonIntent);
-        }
-
-        @Override
-        public void onRequestRouteChange(Bundle mediaRouteDescriptor) throws RemoteException {
-            mMediaSession.postRequestRouteChange(mediaRouteDescriptor);
-        }
-
-    }
-
-    private class MessageHandler extends Handler {
-        private MediaSession.Callback mCallback;
-
-        public MessageHandler(Looper looper, MediaSession.Callback callback) {
-            super(looper);
-            mCallback = callback;
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            synchronized (mLock) {
-                if (mCallback == null) {
-                    return;
-                }
-                switch (msg.what) {
-                    case MESSAGE_MEDIA_BUTTON:
-                        mCallback.onMediaButton((Intent) msg.obj);
-                        break;
-                    case MESSAGE_COMMAND:
-                        Bundle commandBundle = (Bundle) msg.obj;
-                        String command = commandBundle.getString(KEY_COMMAND);
-                        Bundle extras = commandBundle.getBundle(KEY_EXTRAS);
-                        mCallback.onCommand(command, extras);
-                        break;
-                    case MESSAGE_ROUTE_CHANGE:
-                        mCallback.onRequestRouteChange((Bundle) msg.obj);
-                        break;
-                }
-            }
-            msg.recycle();
-        }
-    }
-}
diff --git a/media/java/android/media/MediaSessionManager.java b/media/java/android/media/MediaSessionManager.java
deleted file mode 100644
index 90f0071..0000000
--- a/media/java/android/media/MediaSessionManager.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2014 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.content.Context;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * MediaSessionManager allows the creation and control of MediaSessions in the
- * system. A MediaSession enables publishing information about ongoing media and
- * interacting with MediaControllers and MediaRoutes.
- * <p>
- * Use <code>Context.getSystemService(Context.MEDIA_SESSION_SERVICE)</code> to
- * get an instance of this class.
- * <p>
- *
- * @see MediaSession
- * @see MediaController
- */
-public final class MediaSessionManager {
-    private static final String TAG = "MediaSessionManager";
-
-    private final IMediaSessionManager mService;
-
-    private Context mContext;
-
-    /**
-     * @hide
-     */
-    public MediaSessionManager(Context context) {
-        // Consider rewriting like DisplayManagerGlobal
-        // Decide if we need context
-        mContext = context;
-        IBinder b = ServiceManager.getService(Context.MEDIA_SESSION_SERVICE);
-        mService = IMediaSessionManager.Stub.asInterface(b);
-    }
-
-    /**
-     * Creates a new session.
-     *
-     * @param tag A short name for debugging purposes
-     * @return a {@link MediaSession} for the new session
-     */
-    public MediaSession createSession(String tag) {
-        try {
-            MediaSession.CallbackStub cbStub = new MediaSession.CallbackStub();
-            MediaSession session = new MediaSession(mService
-                    .createSession(mContext.getPackageName(), cbStub, tag), cbStub);
-            cbStub.setMediaSession(session);
-
-            return session;
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to create session: ", e);
-            return null;
-        }
-    }
-
-    /**
-     * Get a list of controllers for all ongoing sessions. This requires the
-     * android.Manifest.permission.MEDIA_CONTENT_CONTROL permission be held by
-     * the calling app.
-     *
-     * @return a list of controllers for ongoing sessions
-     */
-    public List<MediaController> getActiveSessions() {
-        // TODO
-        return new ArrayList<MediaController>();
-    }
-}
diff --git a/media/java/android/media/MediaSessionToken.aidl b/media/java/android/media/MediaSessionToken.aidl
deleted file mode 100644
index e2f1abc..0000000
--- a/media/java/android/media/MediaSessionToken.aidl
+++ /dev/null
@@ -1,18 +0,0 @@
-/* Copyright 2014, 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;
-
-parcelable MediaSessionToken;
diff --git a/media/java/android/media/MediaSessionToken.java b/media/java/android/media/MediaSessionToken.java
deleted file mode 100644
index 885fda3..0000000
--- a/media/java/android/media/MediaSessionToken.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2014 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.os.Parcelable;
-
-public class MediaSessionToken implements Parcelable {
-    private IMediaController mBinder;
-
-    /**
-     * @hide
-     */
-    MediaSessionToken(IMediaController binder) {
-        mBinder = binder;
-    }
-
-    private MediaSessionToken(Parcel in) {
-        mBinder = IMediaController.Stub.asInterface(in.readStrongBinder());
-    }
-
-    /**
-     * @hide
-     */
-    IMediaController getBinder() {
-        return mBinder;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeStrongBinder(mBinder.asBinder());
-    }
-
-    public static final Parcelable.Creator<MediaSessionToken> CREATOR
-            = new Parcelable.Creator<MediaSessionToken>() {
-        @Override
-        public MediaSessionToken createFromParcel(Parcel in) {
-            return new MediaSessionToken(in);
-        }
-
-        @Override
-        public MediaSessionToken[] newArray(int size) {
-            return new MediaSessionToken[size];
-        }
-    };
-}
diff --git a/media/java/android/media/session/IMediaController.aidl b/media/java/android/media/session/IMediaController.aidl
new file mode 100644
index 0000000..8ca0e45
--- /dev/null
+++ b/media/java/android/media/session/IMediaController.aidl
@@ -0,0 +1,34 @@
+/* Copyright (C) 2014 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.session;
+
+import android.content.Intent;
+import android.media.session.IMediaControllerCallback;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.view.KeyEvent;
+
+/**
+ * Interface to a MediaSession in the system.
+ * @hide
+ */
+interface IMediaController {
+    void sendCommand(String command, in Bundle extras);
+    void sendMediaButton(in KeyEvent mediaButton);
+    void registerCallbackListener(in IMediaControllerCallback cb);
+    void unregisterCallbackListener(in IMediaControllerCallback cb);
+    int getPlaybackState();
+}
\ No newline at end of file
diff --git a/media/java/android/media/session/IMediaControllerCallback.aidl b/media/java/android/media/session/IMediaControllerCallback.aidl
new file mode 100644
index 0000000..3aa0ee4
--- /dev/null
+++ b/media/java/android/media/session/IMediaControllerCallback.aidl
@@ -0,0 +1,28 @@
+/* Copyright (C) 2014 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.session;
+
+import android.os.Bundle;
+
+/**
+ * @hide
+ */
+oneway interface IMediaControllerCallback {
+    void onEvent(String event, in Bundle extras);
+    void onMetadataUpdate(in Bundle metadata);
+    void onPlaybackUpdate(int newState);
+    void onRouteChanged(in Bundle route);
+}
\ No newline at end of file
diff --git a/media/java/android/media/session/IMediaSession.aidl b/media/java/android/media/session/IMediaSession.aidl
new file mode 100644
index 0000000..19f7092
--- /dev/null
+++ b/media/java/android/media/session/IMediaSession.aidl
@@ -0,0 +1,33 @@
+/* Copyright (C) 2014 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.session;
+
+import android.media.session.IMediaController;
+import android.os.Bundle;
+
+/**
+ * Interface to a MediaSession in the system.
+ * @hide
+ */
+interface IMediaSession {
+    void sendEvent(in Bundle data);
+    IMediaController getMediaSessionToken();
+    void setPlaybackState(int state);
+    void setMetadata(in Bundle metadata);
+    void setRouteState(in Bundle routeState);
+    void setRoute(in Bundle mediaRouteDescriptor);
+    void destroy();
+}
\ No newline at end of file
diff --git a/media/java/android/media/session/IMediaSessionCallback.aidl b/media/java/android/media/session/IMediaSessionCallback.aidl
new file mode 100644
index 0000000..eb5f222
--- /dev/null
+++ b/media/java/android/media/session/IMediaSessionCallback.aidl
@@ -0,0 +1,29 @@
+/* Copyright (C) 2014 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.session;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+
+/**
+ * @hide
+ */
+oneway interface IMediaSessionCallback {
+    void onCommand(String command, in Bundle extras);
+    void onMediaButton(in Intent mediaRequestIntent);
+    void onRequestRouteChange(in Bundle route);
+}
\ No newline at end of file
diff --git a/media/java/android/media/session/IMediaSessionManager.aidl b/media/java/android/media/session/IMediaSessionManager.aidl
new file mode 100644
index 0000000..0b4328e
--- /dev/null
+++ b/media/java/android/media/session/IMediaSessionManager.aidl
@@ -0,0 +1,28 @@
+/* Copyright (C) 2014 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.session;
+
+import android.media.session.IMediaSession;
+import android.media.session.IMediaSessionCallback;
+import android.os.Bundle;
+
+/**
+ * Interface to the MediaSessionManagerService
+ * @hide
+ */
+interface IMediaSessionManager {
+    IMediaSession createSession(String packageName, in IMediaSessionCallback cb, String tag);
+}
\ No newline at end of file
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
new file mode 100644
index 0000000..09de859
--- /dev/null
+++ b/media/java/android/media/session/MediaController.java
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2014 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.session;
+
+import android.content.Intent;
+import android.media.session.IMediaController;
+import android.media.session.IMediaControllerCallback;
+import android.media.MediaMetadataRetriever;
+import android.media.RemoteControlClient;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.KeyEvent;
+
+import java.util.ArrayList;
+
+/**
+ * Allows an app to interact with an ongoing media session. Media buttons and
+ * other commands can be sent to the session. A callback may be registered to
+ * receive updates from the session, such as metadata and play state changes.
+ * <p>
+ * A MediaController can be created through {@link MediaSessionManager} if you
+ * hold the "android.permission.MEDIA_CONTENT_CONTROL" permission or directly if
+ * you have a {@link MediaSessionToken} from the session owner.
+ * <p>
+ * MediaController objects are thread-safe.
+ */
+public final class MediaController {
+    private static final String TAG = "MediaController";
+
+    private static final int MESSAGE_EVENT = 1;
+    private static final int MESSAGE_PLAYBACK_STATE = 2;
+    private static final int MESSAGE_METADATA = 3;
+    private static final int MESSAGE_ROUTE = 4;
+
+    private static final String KEY_EVENT = "event";
+    private static final String KEY_EXTRAS = "extras";
+
+    private final IMediaController mSessionBinder;
+
+    private final CallbackStub mCbStub = new CallbackStub();
+    private final ArrayList<Callback> mCbs = new ArrayList<Callback>();
+    private final Object mLock = new Object();
+
+    private boolean mCbRegistered = false;
+
+    /**
+     * If you have a {@link MediaSessionToken} from the owner of the session a
+     * controller can be created directly. It is up to the session creator to
+     * handle token distribution if desired.
+     *
+     * @see MediaSession#getSessionToken()
+     * @param token A token from the creator of the session
+     */
+    public MediaController(MediaSessionToken token) {
+        mSessionBinder = token.getBinder();
+    }
+
+    /**
+     * @hide
+     */
+    public MediaController(IMediaController sessionBinder) {
+        mSessionBinder = sessionBinder;
+    }
+
+    /**
+     * Sends a generic command to the session. It is up to the session creator
+     * to decide what commands and parameters they will support. As such,
+     * commands should only be sent to sessions that the controller owns.
+     *
+     * @param command The command to send
+     * @param params Any parameters to include with the command
+     */
+    public void sendCommand(String command, Bundle params) {
+        if (TextUtils.isEmpty(command)) {
+            throw new IllegalArgumentException("command cannot be null or empty");
+        }
+        try {
+            mSessionBinder.sendCommand(command, params);
+        } catch (RemoteException e) {
+            Log.d(TAG, "Dead object in sendCommand.", e);
+        }
+    }
+
+    /**
+     * Send the specified media button to the session. Only media keys can be
+     * sent using this method.
+     *
+     * @param keycode The media button keycode, such as
+     *            {@link KeyEvent#KEYCODE_MEDIA_PLAY}.
+     */
+    public void sendMediaButton(int keycode) {
+        if (!KeyEvent.isMediaKey(keycode)) {
+            throw new IllegalArgumentException("May only send media buttons through "
+                    + "sendMediaButton");
+        }
+        // TODO do something better than key down/up events
+        KeyEvent event = new KeyEvent(KeyEvent.ACTION_UP, keycode);
+        try {
+            mSessionBinder.sendMediaButton(event);
+        } catch (RemoteException e) {
+            Log.d(TAG, "Dead object in sendMediaButton", e);
+        }
+    }
+
+    /**
+     * Adds a callback to receive updates from the Session. Updates will be
+     * posted on the caller's thread.
+     *
+     * @param cb The callback object, must not be null
+     */
+    public void addCallback(Callback cb) {
+        addCallback(cb, null);
+    }
+
+    /**
+     * Adds a callback to receive updates from the session. Updates will be
+     * posted on the specified handler.
+     *
+     * @param cb Cannot be null.
+     * @param handler The handler to post updates on, if null the callers thread
+     *            will be used
+     */
+    public void addCallback(Callback cb, Handler handler) {
+        if (handler == null) {
+            handler = new Handler();
+        }
+        synchronized (mLock) {
+            addCallbackLocked(cb, handler);
+        }
+    }
+
+    /**
+     * Stop receiving updates on the specified callback. If an update has
+     * already been posted you may still receive it after calling this method.
+     *
+     * @param cb The callback to remove
+     */
+    public void removeCallback(Callback cb) {
+        synchronized (mLock) {
+            removeCallbackLocked(cb);
+        }
+    }
+
+    /*
+     * @hide
+     */
+    IMediaController getSessionBinder() {
+        return mSessionBinder;
+    }
+
+    private void addCallbackLocked(Callback cb, Handler handler) {
+        if (cb == null) {
+            throw new IllegalArgumentException("Callback cannot be null");
+        }
+        if (handler == null) {
+            throw new IllegalArgumentException("Handler cannot be null");
+        }
+        if (mCbs.contains(cb)) {
+            Log.w(TAG, "Callback is already added, ignoring");
+            return;
+        }
+        cb.setHandler(handler);
+        mCbs.add(cb);
+
+        // Only register one cb binder, track callbacks internally and notify
+        if (!mCbRegistered) {
+            try {
+                mSessionBinder.registerCallbackListener(mCbStub);
+                mCbRegistered = true;
+            } catch (RemoteException e) {
+                Log.d(TAG, "Dead object in registerCallback", e);
+            }
+        }
+    }
+
+    private void removeCallbackLocked(Callback cb) {
+        if (cb == null) {
+            throw new IllegalArgumentException("Callback cannot be null");
+        }
+        mCbs.remove(cb);
+
+        if (mCbs.size() == 0 && mCbRegistered) {
+            try {
+                mSessionBinder.unregisterCallbackListener(mCbStub);
+            } catch (RemoteException e) {
+                Log.d(TAG, "Dead object in unregisterCallback", e);
+            }
+            mCbRegistered = false;
+        }
+    }
+
+    private void pushOnEventLocked(String event, Bundle extras) {
+        for (int i = mCbs.size() - 1; i >= 0; i--) {
+            mCbs.get(i).postEvent(event, extras);
+        }
+    }
+
+    private void pushOnMetadataUpdateLocked(Bundle metadata) {
+        for (int i = mCbs.size() - 1; i >= 0; i--) {
+            mCbs.get(i).postMetadataUpdate(metadata);
+        }
+    }
+
+    private void pushOnPlaybackUpdateLocked(int newState) {
+        for (int i = mCbs.size() - 1; i >= 0; i--) {
+            mCbs.get(i).postPlaybackStateChange(newState);
+        }
+    }
+
+    private void pushOnRouteChangedLocked(Bundle routeDescriptor) {
+        for (int i = mCbs.size() - 1; i >= 0; i--) {
+            mCbs.get(i).postRouteChanged(routeDescriptor);
+        }
+    }
+
+    /**
+     * MediaSession callbacks will be posted on the thread that created the
+     * Callback object.
+     */
+    public static abstract class Callback {
+        private Handler mHandler;
+
+        /**
+         * Override to handle custom events sent by the session owner.
+         * Controllers should only handle these for sessions they own.
+         *
+         * @param event
+         */
+        public void onEvent(String event, Bundle extras) {
+        }
+
+        /**
+         * Override to handle updates to the playback state. Valid values are in
+         * {@link RemoteControlClient}. TODO put playstate values somewhere more
+         * generic.
+         *
+         * @param state
+         */
+        public void onPlaybackStateChange(int state) {
+        }
+
+        /**
+         * Override to handle metadata changes for this session's media. The
+         * default supported fields are those in {@link MediaMetadataRetriever}.
+         *
+         * @param metadata
+         */
+        public void onMetadataUpdate(Bundle metadata) {
+        }
+
+        /**
+         * Override to handle route changes for this session.
+         *
+         * @param route
+         */
+        public void onRouteChanged(Bundle route) {
+        }
+
+        private void setHandler(Handler handler) {
+            mHandler = new MessageHandler(handler.getLooper(), this);
+        }
+
+        private void postEvent(String event, Bundle extras) {
+            Bundle eventBundle = new Bundle();
+            eventBundle.putString(KEY_EVENT, event);
+            eventBundle.putBundle(KEY_EXTRAS, extras);
+            Message msg = mHandler.obtainMessage(MESSAGE_EVENT, eventBundle);
+            mHandler.sendMessage(msg);
+        }
+
+        private void postPlaybackStateChange(final int state) {
+            Message msg = mHandler.obtainMessage(MESSAGE_PLAYBACK_STATE, state, 0);
+            mHandler.sendMessage(msg);
+        }
+
+        private void postMetadataUpdate(final Bundle metadata) {
+            Message msg = mHandler.obtainMessage(MESSAGE_METADATA, metadata);
+            mHandler.sendMessage(msg);
+        }
+
+        private void postRouteChanged(final Bundle descriptor) {
+            Message msg = mHandler.obtainMessage(MESSAGE_ROUTE, descriptor);
+            mHandler.sendMessage(msg);
+        }
+    }
+
+    private final class CallbackStub extends IMediaControllerCallback.Stub {
+
+        @Override
+        public void onEvent(String event, Bundle extras) throws RemoteException {
+            synchronized (mLock) {
+                pushOnEventLocked(event, extras);
+            }
+        }
+
+        @Override
+        public void onMetadataUpdate(Bundle metadata) throws RemoteException {
+            synchronized (mLock) {
+                pushOnMetadataUpdateLocked(metadata);
+            }
+        }
+
+        @Override
+        public void onPlaybackUpdate(final int newState) throws RemoteException {
+            synchronized (mLock) {
+                pushOnPlaybackUpdateLocked(newState);
+            }
+        }
+
+        @Override
+        public void onRouteChanged(Bundle mediaRouteDescriptor) throws RemoteException {
+            synchronized (mLock) {
+                pushOnRouteChangedLocked(mediaRouteDescriptor);
+            }
+        }
+
+    }
+
+    private final static class MessageHandler extends Handler {
+        private final MediaController.Callback mCb;
+
+        public MessageHandler(Looper looper, MediaController.Callback cb) {
+            super(looper);
+            mCb = cb;
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MESSAGE_EVENT:
+                    Bundle eventBundle = (Bundle) msg.obj;
+                    String event = eventBundle.getString(KEY_EVENT);
+                    Bundle extras = eventBundle.getBundle(KEY_EXTRAS);
+                    mCb.onEvent(event, extras);
+                    break;
+                case MESSAGE_PLAYBACK_STATE:
+                    mCb.onPlaybackStateChange(msg.arg1);
+                    break;
+                case MESSAGE_METADATA:
+                    mCb.onMetadataUpdate((Bundle) msg.obj);
+                    break;
+                case MESSAGE_ROUTE:
+                    mCb.onRouteChanged((Bundle) msg.obj);
+            }
+        }
+    }
+
+}
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
new file mode 100644
index 0000000..1f1533b
--- /dev/null
+++ b/media/java/android/media/session/MediaSession.java
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2014 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.session;
+
+import android.content.Intent;
+import android.media.session.IMediaController;
+import android.media.session.IMediaSession;
+import android.media.session.IMediaSessionCallback;
+import android.media.RemoteControlClient;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+/**
+ * Allows interaction with media controllers, media routes, volume keys, media
+ * buttons, and transport controls.
+ * <p>
+ * A MediaSession should be created when an app wants to publish media playback
+ * information or negotiate with a media route. In general an app only needs one
+ * session for all playback, though multiple sessions can be created for sending
+ * media to multiple routes or to provide finer grain controls of media.
+ * <p>
+ * A MediaSession is created by calling
+ * {@link MediaSessionManager#createSession(String)}. Once a session is created
+ * apps that have the MEDIA_CONTENT_CONTROL permission can interact with the
+ * session through {@link MediaSessionManager#getActiveSessions()}. The owner of
+ * the session may also use {@link #getSessionToken()} to allow apps without
+ * this permission to create a {@link MediaController} to interact with this
+ * session.
+ * <p>
+ * To receive commands, media keys, and other events a Callback must be set with
+ * {@link #addCallback(Callback)}.
+ * <p>
+ * When an app is finished performing playback it must call {@link #release()}
+ * to clean up the session and notify any controllers.
+ * <p>
+ * MediaSession objects are thread safe
+ */
+public final class MediaSession {
+    private static final String TAG = "MediaSession";
+
+    private static final int MESSAGE_MEDIA_BUTTON = 1;
+    private static final int MESSAGE_COMMAND = 2;
+    private static final int MESSAGE_ROUTE_CHANGE = 3;
+
+    private static final String KEY_COMMAND = "command";
+    private static final String KEY_EXTRAS = "extras";
+
+    private final Object mLock = new Object();
+
+    private final MediaSessionToken mSessionToken;
+    private final IMediaSession mBinder;
+    private final CallbackStub mCbStub;
+
+    private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
+
+    /**
+     * @hide
+     */
+    public MediaSession(IMediaSession binder, CallbackStub cbStub) {
+        mBinder = binder;
+        mCbStub = cbStub;
+        IMediaController controllerBinder = null;
+        try {
+            controllerBinder = mBinder.getMediaSessionToken();
+        } catch (RemoteException e) {
+            throw new RuntimeException("Dead object in MediaSessionController constructor: ", e);
+        }
+        mSessionToken = new MediaSessionToken(controllerBinder);
+    }
+
+    /**
+     * Set the callback to receive updates on.
+     *
+     * @param callback The callback object
+     */
+    public void addCallback(Callback callback) {
+        addCallback(callback, null);
+    }
+
+    public void addCallback(Callback callback, Handler handler) {
+        if (callback == null) {
+            throw new IllegalArgumentException("Callback cannot be null");
+        }
+        synchronized (mLock) {
+            if (mCallbacks.contains(callback)) {
+                Log.w(TAG, "Callback is already added, ignoring");
+            }
+            if (handler == null) {
+                handler = new Handler();
+            }
+            MessageHandler msgHandler = new MessageHandler(handler.getLooper(), callback);
+            callback.setHandler(msgHandler);
+            mCallbacks.add(callback);
+        }
+    }
+
+    public void removeCallback(Callback callback) {
+        mCallbacks.remove(callback);
+    }
+
+    /**
+     * Publish the current playback state to the system and any controllers.
+     * Valid values are defined in {@link RemoteControlClient}. TODO move play
+     * states somewhere else.
+     *
+     * @param state
+     */
+    public void setPlaybackState(int state) {
+        try {
+            mBinder.setPlaybackState(state);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in setPlaybackState: ", e);
+        }
+    }
+
+    /**
+     * This must be called when an app has finished performing playback. If
+     * playback is expected to start again shortly the session can be left open,
+     * but it must be released if your activity or service is being destroyed.
+     */
+    public void release() {
+        try {
+            mBinder.destroy();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in onDestroy: ", e);
+        }
+    }
+
+    /**
+     * Retrieve a token object that can be used by apps to create a
+     * {@link MediaController} for interacting with this session. The owner of
+     * the session is responsible for deciding how to distribute these tokens.
+     *
+     * @return A token that can be used to create a MediaController for this
+     *         session
+     */
+    public MediaSessionToken getSessionToken() {
+        return mSessionToken;
+    }
+
+    private void postCommand(String command, Bundle extras) {
+        Bundle commandBundle = new Bundle();
+        commandBundle.putString(KEY_COMMAND, command);
+        commandBundle.putBundle(KEY_EXTRAS, extras);
+        synchronized (mLock) {
+            for (int i = mCallbacks.size() - 1; i >= 0; i--) {
+                Callback cb = mCallbacks.get(i);
+                Message msg = cb.mHandler.obtainMessage(MESSAGE_COMMAND, commandBundle);
+                cb.mHandler.sendMessage(msg);
+            }
+        }
+    }
+
+    private void postMediaButton(Intent mediaButtonIntent) {
+        synchronized (mLock) {
+            for (int i = mCallbacks.size() - 1; i >= 0; i--) {
+                Callback cb = mCallbacks.get(i);
+                Message msg = cb.mHandler.obtainMessage(MESSAGE_MEDIA_BUTTON, mediaButtonIntent);
+                cb.mHandler.sendMessage(msg);
+            }
+        }
+    }
+
+    private void postRequestRouteChange(Bundle mediaRouteDescriptor) {
+        synchronized (mLock) {
+            for (int i = mCallbacks.size() - 1; i >= 0; i--) {
+                Callback cb = mCallbacks.get(i);
+                Message msg = cb.mHandler.obtainMessage(MESSAGE_ROUTE_CHANGE, mediaRouteDescriptor);
+                cb.mHandler.sendMessage(msg);
+            }
+        }
+    }
+
+    /**
+     * Receives commands or updates from controllers and routes. An app can
+     * specify what commands and buttons it supports by setting them on the
+     * MediaSession (TODO).
+     */
+    public abstract static class Callback {
+        private MessageHandler mHandler;
+
+        public Callback() {
+        }
+
+        /**
+         * Called when a media button is pressed and this session has the
+         * highest priority or a controller sends a media button event to the
+         * session. TODO determine if using Intents identical to the ones
+         * RemoteControlClient receives is useful
+         * <p>
+         * The intent will be of type {@link Intent#ACTION_MEDIA_BUTTON} with a
+         * KeyEvent in {@link Intent#EXTRA_KEY_EVENT}
+         *
+         * @param mediaButtonIntent an intent containing the KeyEvent as an
+         *            extra
+         */
+        public void onMediaButton(Intent mediaButtonIntent) {
+        }
+
+        /**
+         * Called when a controller has sent a custom command to this session.
+         * The owner of the session may handle custom commands but is not
+         * required to.
+         *
+         * @param command
+         * @param extras optional
+         */
+        public void onCommand(String command, Bundle extras) {
+        }
+
+        /**
+         * Called when the user has selected a different route to connect to.
+         * The app is responsible for connecting to the new route and migrating
+         * ongoing playback if necessary.
+         *
+         * @param descriptor
+         */
+        public void onRequestRouteChange(Bundle descriptor) {
+        }
+
+        private void setHandler(MessageHandler handler) {
+            mHandler = handler;
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public static class CallbackStub extends IMediaSessionCallback.Stub {
+        private MediaSession mMediaSession;
+
+        public void setMediaSession(MediaSession session) {
+            mMediaSession = session;
+        }
+
+        @Override
+        public void onCommand(String command, Bundle extras) throws RemoteException {
+            mMediaSession.postCommand(command, extras);
+        }
+
+        @Override
+        public void onMediaButton(Intent mediaButtonIntent) throws RemoteException {
+            mMediaSession.postMediaButton(mediaButtonIntent);
+        }
+
+        @Override
+        public void onRequestRouteChange(Bundle mediaRouteDescriptor) throws RemoteException {
+            mMediaSession.postRequestRouteChange(mediaRouteDescriptor);
+        }
+
+    }
+
+    private class MessageHandler extends Handler {
+        private MediaSession.Callback mCallback;
+
+        public MessageHandler(Looper looper, MediaSession.Callback callback) {
+            super(looper);
+            mCallback = callback;
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            synchronized (mLock) {
+                if (mCallback == null) {
+                    return;
+                }
+                switch (msg.what) {
+                    case MESSAGE_MEDIA_BUTTON:
+                        mCallback.onMediaButton((Intent) msg.obj);
+                        break;
+                    case MESSAGE_COMMAND:
+                        Bundle commandBundle = (Bundle) msg.obj;
+                        String command = commandBundle.getString(KEY_COMMAND);
+                        Bundle extras = commandBundle.getBundle(KEY_EXTRAS);
+                        mCallback.onCommand(command, extras);
+                        break;
+                    case MESSAGE_ROUTE_CHANGE:
+                        mCallback.onRequestRouteChange((Bundle) msg.obj);
+                        break;
+                }
+            }
+            msg.recycle();
+        }
+    }
+}
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
new file mode 100644
index 0000000..e3f2d9c
--- /dev/null
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2014 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.session;
+
+import android.content.Context;
+import android.media.session.IMediaSessionManager;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * MediaSessionManager allows the creation and control of MediaSessions in the
+ * system. A MediaSession enables publishing information about ongoing media and
+ * interacting with MediaControllers and MediaRoutes.
+ * <p>
+ * Use <code>Context.getSystemService(Context.MEDIA_SESSION_SERVICE)</code> to
+ * get an instance of this class.
+ * <p>
+ *
+ * @see MediaSession
+ * @see MediaController
+ */
+public final class MediaSessionManager {
+    private static final String TAG = "MediaSessionManager";
+
+    private final IMediaSessionManager mService;
+
+    private Context mContext;
+
+    /**
+     * @hide
+     */
+    public MediaSessionManager(Context context) {
+        // Consider rewriting like DisplayManagerGlobal
+        // Decide if we need context
+        mContext = context;
+        IBinder b = ServiceManager.getService(Context.MEDIA_SESSION_SERVICE);
+        mService = IMediaSessionManager.Stub.asInterface(b);
+    }
+
+    /**
+     * Creates a new session.
+     *
+     * @param tag A short name for debugging purposes
+     * @return a {@link MediaSession} for the new session
+     */
+    public MediaSession createSession(String tag) {
+        try {
+            MediaSession.CallbackStub cbStub = new MediaSession.CallbackStub();
+            MediaSession session = new MediaSession(mService
+                    .createSession(mContext.getPackageName(), cbStub, tag), cbStub);
+            cbStub.setMediaSession(session);
+
+            return session;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to create session: ", e);
+            return null;
+        }
+    }
+
+    /**
+     * Get a list of controllers for all ongoing sessions. This requires the
+     * android.Manifest.permission.MEDIA_CONTENT_CONTROL permission be held by
+     * the calling app.
+     *
+     * @return a list of controllers for ongoing sessions
+     */
+    public List<MediaController> getActiveSessions() {
+        // TODO
+        return new ArrayList<MediaController>();
+    }
+}
diff --git a/media/java/android/media/session/MediaSessionToken.aidl b/media/java/android/media/session/MediaSessionToken.aidl
new file mode 100644
index 0000000..5812682
--- /dev/null
+++ b/media/java/android/media/session/MediaSessionToken.aidl
@@ -0,0 +1,18 @@
+/* Copyright 2014, 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.session;
+
+parcelable MediaSessionToken;
diff --git a/media/java/android/media/session/MediaSessionToken.java b/media/java/android/media/session/MediaSessionToken.java
new file mode 100644
index 0000000..dbb4964
--- /dev/null
+++ b/media/java/android/media/session/MediaSessionToken.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2014 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.session;
+
+import android.media.session.IMediaController;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class MediaSessionToken implements Parcelable {
+    private IMediaController mBinder;
+
+    /**
+     * @hide
+     */
+    MediaSessionToken(IMediaController binder) {
+        mBinder = binder;
+    }
+
+    private MediaSessionToken(Parcel in) {
+        mBinder = IMediaController.Stub.asInterface(in.readStrongBinder());
+    }
+
+    /**
+     * @hide
+     */
+    IMediaController getBinder() {
+        return mBinder;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeStrongBinder(mBinder.asBinder());
+    }
+
+    public static final Parcelable.Creator<MediaSessionToken> CREATOR
+            = new Parcelable.Creator<MediaSessionToken>() {
+        @Override
+        public MediaSessionToken createFromParcel(Parcel in) {
+            return new MediaSessionToken(in);
+        }
+
+        @Override
+        public MediaSessionToken[] newArray(int size) {
+            return new MediaSessionToken[size];
+        }
+    };
+}
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 51fccd4..ed98b96 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -38,6 +38,7 @@
     libcamera_client \
     libmtp \
     libusbhost \
+    libjhead \
     libexif \
     libstagefright_amrnb_common \
 
@@ -61,8 +62,7 @@
     $(call include-path-for, libhardware)/hardware \
     system/media/camera/include \
     $(PV_INCLUDES) \
-    $(JNI_H_INCLUDE) \
-    $(call include-path-for, corecg graphics)
+    $(JNI_H_INCLUDE)
 
 LOCAL_CFLAGS +=
 
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 3ce483d..b2fb2df 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -112,12 +112,35 @@
     mLooper->registerHandler(this);
 }
 
-JMediaCodec::~JMediaCodec() {
+void JMediaCodec::release() {
     if (mCodec != NULL) {
         mCodec->release();
         mCodec.clear();
     }
 
+    if (mLooper != NULL) {
+        mLooper->unregisterHandler(id());
+        mLooper->stop();
+        mLooper.clear();
+    }
+}
+
+JMediaCodec::~JMediaCodec() {
+    if (mCodec != NULL || mLooper != NULL) {
+        /* MediaCodec and looper should have been released explicitly already
+         * in setMediaCodec() (see comments in setMediaCodec()).
+         *
+         * Otherwise JMediaCodec::~JMediaCodec() might be called from within the
+         * message handler, doing release() there risks deadlock as MediaCodec::
+         * release() post synchronous message to the same looper.
+         *
+         * Print a warning and try to proceed with releasing.
+         */
+        ALOGW("try to release MediaCodec from JMediaCodec::~JMediaCodec()...");
+        release();
+        ALOGW("done releasing MediaCodec from JMediaCodec::~JMediaCodec().");
+    }
+
     JNIEnv *env = AndroidRuntime::getJNIEnv();
 
     env->DeleteWeakGlobalRef(mObject);
@@ -432,6 +455,12 @@
         codec->incStrong(thiz);
     }
     if (old != NULL) {
+        /* release MediaCodec and stop the looper now before decStrong.
+         * otherwise JMediaCodec::~JMediaCodec() could be called from within
+         * its message handler, doing release() from there will deadlock
+         * (as MediaCodec::release() post synchronous message to the same looper)
+         */
+        old->release();
         old->decStrong(thiz);
     }
     env->SetLongField(thiz, gFields.context, (jlong)codec.get());
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index 53254c9..2f2ea96 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -42,6 +42,7 @@
     status_t initCheck() const;
 
     void registerSelf();
+    void release();
 
     status_t configure(
             const sp<AMessage> &format,
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index d3a8b22..a78f16d 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -561,7 +561,7 @@
         return JNI_FALSE;
     }
 
-    size_t numSubSamples = size / sizeof(size_t);
+    size_t numSubSamples = size / sizeof(int32_t);
 
     if (numSubSamples == 0) {
         return JNI_FALSE;
@@ -571,7 +571,7 @@
     jboolean isCopy;
     jint *dst = env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
     for (size_t i = 0; i < numSubSamples; ++i) {
-        dst[i] = ((const size_t *)data)[i];
+        dst[i] = ((const int32_t *)data)[i];
     }
     env->ReleaseIntArrayElements(numBytesOfEncryptedDataObj, dst, 0);
     dst = NULL;
@@ -588,7 +588,7 @@
         jboolean isCopy;
         jint *dst = env->GetIntArrayElements(numBytesOfPlainDataObj, &isCopy);
         for (size_t i = 0; i < numSubSamples; ++i) {
-            dst[i] = ((const size_t *)data)[i];
+            dst[i] = ((const int32_t *)data)[i];
         }
         env->ReleaseIntArrayElements(numBytesOfPlainDataObj, dst, 0);
         dst = NULL;
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index f17209f..4e42ae3 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -21,7 +21,7 @@
 #include <assert.h>
 #include <utils/Log.h>
 #include <utils/threads.h>
-#include <core/SkBitmap.h>
+#include <SkBitmap.h>
 #include <media/IMediaHTTPService.h>
 #include <media/mediametadataretriever.h>
 #include <private/media/VideoFrame.h>
@@ -256,7 +256,7 @@
                         fields.createConfigMethod,
                         SkBitmap::kRGB_565_Config);
 
-    size_t width, height;
+    uint32_t width, height;
     bool swapWidthAndHeight = false;
     if (videoFrame->mRotationAngle == 90 || videoFrame->mRotationAngle == 270) {
         width = videoFrame->mHeight;
@@ -287,8 +287,8 @@
 
     if (videoFrame->mDisplayWidth  != videoFrame->mWidth ||
         videoFrame->mDisplayHeight != videoFrame->mHeight) {
-        size_t displayWidth = videoFrame->mDisplayWidth;
-        size_t displayHeight = videoFrame->mDisplayHeight;
+        uint32_t displayWidth = videoFrame->mDisplayWidth;
+        uint32_t displayHeight = videoFrame->mDisplayHeight;
         if (swapWidthAndHeight) {
             displayWidth = videoFrame->mDisplayHeight;
             displayHeight = videoFrame->mDisplayWidth;
diff --git a/media/jni/mediaeditor/Android.mk b/media/jni/mediaeditor/Android.mk
index 6be7fdd..76e8346 100644
--- a/media/jni/mediaeditor/Android.mk
+++ b/media/jni/mediaeditor/Android.mk
@@ -35,7 +35,6 @@
     $(TOP)/frameworks/base/media/libstagefright/include \
     $(TOP)/frameworks/base/media/libstagefright/rtsp \
     $(JNI_H_INCLUDE) \
-    $(call include-path-for, corecg graphics) \
     $(TOP)/frameworks/native/include/media/editor \
     $(TOP)/frameworks/base/core/jni/mediaeditor \
     $(TOP)/frameworks/av/libvideoeditor/vss/inc \
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediarecorder/MediaRecorderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediarecorder/MediaRecorderTest.java
index 599522b..d7069cac 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediarecorder/MediaRecorderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediarecorder/MediaRecorderTest.java
@@ -58,6 +58,7 @@
     private MediaRecorder mRecorder;
 
     private int MIN_VIDEO_FPS = 5;
+    private int HIGH_SPEED_FPS = 120;
 
     private static final int CAMERA_ID = 0;
 
@@ -221,10 +222,12 @@
         return success;
     }
 
-    private boolean recordVideoFromSurface(int frameRate, int width, int height,
+    private boolean recordVideoFromSurface(
+            int frameRate, int captureRate, int width, int height,
             int videoFormat, int outFormat, String outFile, boolean videoOnly) {
         Log.v(TAG,"recordVideoFromSurface");
         MediaRecorder recorder = new MediaRecorder();
+        int sleepTime = 33; // normal capture at 33ms / frame
         try {
             if (!videoOnly) {
                 recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
@@ -233,6 +236,10 @@
             recorder.setOutputFormat(outFormat);
             recorder.setOutputFile(outFile);
             recorder.setVideoFrameRate(frameRate);
+            if (captureRate > 0) {
+                recorder.setCaptureRate(captureRate);
+                sleepTime = 1000 / captureRate;
+            }
             recorder.setVideoSize(width, height);
             recorder.setVideoEncoder(videoFormat);
             if (!videoOnly) {
@@ -256,7 +263,7 @@
                 String text = "Frame #" + i;
                 canvas.drawText(text, 100, 100, paint);
                 surface.unlockCanvasAndPost(canvas);
-                Thread.sleep(33);
+                Thread.sleep(sleepTime);
             }
 
             Log.v(TAG, "start");
@@ -270,7 +277,7 @@
                 String text = "Frame #" + i;
                 canvas.drawText(text, 100, 100, paint);
                 surface.unlockCanvasAndPost(canvas);
-                Thread.sleep(33);
+                Thread.sleep(sleepTime);
             }
 
             Log.v(TAG, "stop");
@@ -517,7 +524,7 @@
                 String filename = "/sdcard/surface_" +
                             (k==0?"video_only":"with_audio") + ".3gp";
 
-                success = recordVideoFromSurface(frameRate, 352, 288, codec,
+                success = recordVideoFromSurface(frameRate, 0, 352, 288, codec,
                         MediaRecorder.OutputFormat.THREE_GPP, filename,
                         k == 0 ? true : false /* videoOnly */);
                 if (success) {
@@ -532,4 +539,38 @@
         }
         assertTrue("testSurfaceRecording", noOfFailure == 0);
     }
+
+    // Test recording from surface source with/without audio
+    public void testSurfaceRecordingTimeLapse() {
+        boolean success = false;
+        int noOfFailure = 0;
+        try {
+            int codec = MediaRecorder.VideoEncoder.H264;
+            int frameRate = MediaProfileReader.getMaxFrameRateForCodec(codec);
+            for (int k = 0; k < 2; k++) {
+                // k==0: time lapse test, set capture rate to MIN_VIDEO_FPS
+                // k==1: slow motion test, set capture rate to HIGH_SPEED_FPS
+                String filename = "/sdcard/surface_" +
+                            (k==0 ? "time_lapse" : "slow_motion") + ".3gp";
+
+                // always set videoOnly=false, MediaRecorder should disable
+                // audio automatically with time lapse/slow motion
+                success = recordVideoFromSurface(frameRate,
+                        k==0 ? MIN_VIDEO_FPS : HIGH_SPEED_FPS,
+                        352, 288, codec,
+                        MediaRecorder.OutputFormat.THREE_GPP,
+                        filename, false /* videoOnly */);
+                if (success) {
+                    success = validateVideo(filename, 352, 288);
+                }
+                if (!success) {
+                    noOfFailure++;
+                }
+            }
+        } catch (Exception e) {
+            Log.v(TAG, e.toString());
+        }
+        assertTrue("testSurfaceRecordingTimeLapse", noOfFailure == 0);
+    }
+
 }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java
index 8c76421..eb1a589 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java
@@ -85,8 +85,8 @@
         super.setUp();
         mMockProvider = EasyMock.createMock(IContentProvider.class);
         mMediaInserter = new MediaInserter(mMockProvider,
-		mPackageName, TEST_BUFFER_SIZE);
-	mPackageName = getInstrumentation().getContext().getPackageName();
+        mPackageName, TEST_BUFFER_SIZE);
+        mPackageName = getInstrumentation().getContext().getPackageName();
         mFilesCounter = 0;
         mAudioCounter = 0;
         mVideoCounter = 0;
@@ -224,19 +224,19 @@
     @SmallTest
     public void testInsertContentsWithDifferentSizePerContentType() throws Exception {
         EasyMock.expect(mMockProvider.bulkInsert(mPackageName,
-		MediaUriMatcher.expectMediaUri(sFilesUri),
+        MediaUriMatcher.expectMediaUri(sFilesUri),
                 (ContentValues[]) EasyMock.anyObject())).andReturn(1);
         EasyMock.expectLastCall().times(1);
         EasyMock.expect(mMockProvider.bulkInsert(mPackageName,
-		MediaUriMatcher.expectMediaUri(sAudioUri),
+        MediaUriMatcher.expectMediaUri(sAudioUri),
                 (ContentValues[]) EasyMock.anyObject())).andReturn(1);
         EasyMock.expectLastCall().times(2);
         EasyMock.expect(mMockProvider.bulkInsert(mPackageName,
-		MediaUriMatcher.expectMediaUri(sVideoUri),
+        MediaUriMatcher.expectMediaUri(sVideoUri),
                 (ContentValues[]) EasyMock.anyObject())).andReturn(1);
         EasyMock.expectLastCall().times(3);
         EasyMock.expect(mMockProvider.bulkInsert(mPackageName,
-		MediaUriMatcher.expectMediaUri(sImagesUri),
+        MediaUriMatcher.expectMediaUri(sImagesUri),
                 (ContentValues[]) EasyMock.anyObject())).andReturn(1);
         EasyMock.expectLastCall().times(4);
         EasyMock.replay(mMockProvider);
diff --git a/media/tests/omxjpegdecoder/Android.mk b/media/tests/omxjpegdecoder/Android.mk
index ad874c8..95ae33b 100644
--- a/media/tests/omxjpegdecoder/Android.mk
+++ b/media/tests/omxjpegdecoder/Android.mk
@@ -34,11 +34,6 @@
 
 LOCAL_C_INCLUDES := \
     $(TOP)/external/jpeg \
-    $(TOP)/external/skia/include/config \
-    $(TOP)/external/skia/include/core \
-    $(TOP)/external/skia/include/images \
-    $(TOP)/external/skia/include/utils \
-    $(TOP)/external/skia/include/effects \
     $(TOP)/frameworks/base/media/libstagefright \
     $(TOP)/frameworks/base/include/ \
     $(TOP)/frameworks/base/ \
diff --git a/media/tests/omxjpegdecoder/StreamSource.h b/media/tests/omxjpegdecoder/StreamSource.h
index 6c34cbd..9807385 100644
--- a/media/tests/omxjpegdecoder/StreamSource.h
+++ b/media/tests/omxjpegdecoder/StreamSource.h
@@ -20,7 +20,7 @@
 
 #include <stdio.h>
 
-#include <core/SkStream.h>
+#include <SkStream.h>
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/MediaErrors.h>
 #include <utils/threads.h>
diff --git a/native/graphics/jni/Android.mk b/native/graphics/jni/Android.mk
index 8b333e7..3154030 100644
--- a/native/graphics/jni/Android.mk
+++ b/native/graphics/jni/Android.mk
@@ -23,7 +23,6 @@
     libskia
 
 LOCAL_C_INCLUDES += \
-	external/skia/include/core \
 	frameworks/base/native/include \
 	frameworks/base/core/jni/android/graphics
 
diff --git a/opengl/java/android/opengl/EGL14.java b/opengl/java/android/opengl/EGL14.java
index b93557d..cf09c58 100644
--- a/opengl/java/android/opengl/EGL14.java
+++ b/opengl/java/android/opengl/EGL14.java
@@ -160,6 +160,13 @@
         int display_id
     );
 
+    /**
+     * {@hide}
+     */
+    public static native EGLDisplay eglGetDisplay(
+        long display_id
+    );
+
     // C function EGLBoolean eglInitialize ( EGLDisplay dpy, EGLint *major, EGLint *minor )
 
     public static native boolean eglInitialize(
@@ -324,7 +331,7 @@
     );
 
     // C function EGLSurface eglCreatePbufferFromClientBuffer ( EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list )
-
+    // TODO Deprecate the below method
     public static native EGLSurface eglCreatePbufferFromClientBuffer(
         EGLDisplay dpy,
         int buftype,
@@ -333,6 +340,18 @@
         int[] attrib_list,
         int offset
     );
+    // TODO Unhide the below method
+    /**
+     * {@hide}
+     */
+    public static native EGLSurface eglCreatePbufferFromClientBuffer(
+        EGLDisplay dpy,
+        int buftype,
+        long buffer,
+        EGLConfig config,
+        int[] attrib_list,
+        int offset
+    );
 
     // C function EGLBoolean eglSurfaceAttrib ( EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value )
 
diff --git a/opengl/java/android/opengl/EGLConfig.java b/opengl/java/android/opengl/EGLConfig.java
index a7a6bbb..9881070 100644
--- a/opengl/java/android/opengl/EGLConfig.java
+++ b/opengl/java/android/opengl/EGLConfig.java
@@ -22,7 +22,7 @@
  *
  */
 public class EGLConfig extends EGLObjectHandle {
-    private EGLConfig(int handle) {
+    private EGLConfig(long handle) {
         super(handle);
     }
 
@@ -32,6 +32,6 @@
         if (!(o instanceof EGLConfig)) return false;
 
         EGLConfig that = (EGLConfig) o;
-        return getHandle() == that.getHandle();
+        return getNativeHandle() == that.getNativeHandle();
     }
 }
diff --git a/opengl/java/android/opengl/EGLContext.java b/opengl/java/android/opengl/EGLContext.java
index c93bd6e..f791e7e 100644
--- a/opengl/java/android/opengl/EGLContext.java
+++ b/opengl/java/android/opengl/EGLContext.java
@@ -22,7 +22,7 @@
  *
  */
 public class EGLContext extends EGLObjectHandle {
-    private EGLContext(int handle) {
+    private EGLContext(long handle) {
         super(handle);
     }
 
@@ -32,6 +32,6 @@
         if (!(o instanceof EGLContext)) return false;
 
         EGLContext that = (EGLContext) o;
-        return getHandle() == that.getHandle();
+        return getNativeHandle() == that.getNativeHandle();
     }
 }
diff --git a/opengl/java/android/opengl/EGLDisplay.java b/opengl/java/android/opengl/EGLDisplay.java
index 5b8043a..e872761 100644
--- a/opengl/java/android/opengl/EGLDisplay.java
+++ b/opengl/java/android/opengl/EGLDisplay.java
@@ -22,7 +22,7 @@
  *
  */
 public class EGLDisplay extends EGLObjectHandle {
-    private EGLDisplay(int handle) {
+    private EGLDisplay(long handle) {
         super(handle);
     }
 
@@ -32,6 +32,6 @@
         if (!(o instanceof EGLDisplay)) return false;
 
         EGLDisplay that = (EGLDisplay) o;
-        return getHandle() == that.getHandle();
+        return getNativeHandle() == that.getNativeHandle();
     }
 }
diff --git a/opengl/java/android/opengl/EGLObjectHandle.java b/opengl/java/android/opengl/EGLObjectHandle.java
index d2710de..f961eb7 100644
--- a/opengl/java/android/opengl/EGLObjectHandle.java
+++ b/opengl/java/android/opengl/EGLObjectHandle.java
@@ -22,12 +22,30 @@
  *
  */
 public abstract class EGLObjectHandle {
-    private final int mHandle;
+    private final long mHandle;
 
+    /**
+     * @deprecated Use {@link #EGLObjectHandle(long)} instead. Handles
+     *     on 64 bit platforms will be wider than java ints.
+     */
+    @Deprecated
     protected EGLObjectHandle(int handle) {
         mHandle = handle;
     }
-
+    protected EGLObjectHandle(long handle) {
+        mHandle = handle;
+    }
+    /**
+     * @deprecated Use {@link #getNativeHandle()} instead. Handles on
+     *     64 bit platforms will be wider than java ints.
+     */
+    @Deprecated
+    public int getHandle() {
+        if ((mHandle & 0xffffffffL) != mHandle) {
+            throw new UnsupportedOperationException();
+        }
+        return (int)mHandle;
+    }
     /**
      * Returns the native handle of the wrapped EGL object. This handle can be
      * cast to the corresponding native type on the native side.
@@ -36,12 +54,17 @@
      *
      * @return the native handle of the wrapped EGL object.
      */
-    public int getHandle() {
+    public long getNativeHandle() {
         return mHandle;
     }
-
     @Override
     public int hashCode() {
-        return getHandle();
+        /*
+         * Based on the algorithm suggested in
+         * http://developer.android.com/reference/java/lang/Object.html
+         */
+        int result = 17;
+        result = 31 * result + (int) (mHandle ^ (mHandle >>> 32));
+        return result;
     }
 }
diff --git a/opengl/java/android/opengl/EGLSurface.java b/opengl/java/android/opengl/EGLSurface.java
index c379dc9..c200f72 100644
--- a/opengl/java/android/opengl/EGLSurface.java
+++ b/opengl/java/android/opengl/EGLSurface.java
@@ -22,7 +22,7 @@
  *
  */
 public class EGLSurface extends EGLObjectHandle {
-    private EGLSurface(int handle) {
+    private EGLSurface(long handle) {
         super(handle);
     }
 
@@ -32,6 +32,6 @@
         if (!(o instanceof EGLSurface)) return false;
 
         EGLSurface that = (EGLSurface) o;
-        return getHandle() == that.getHandle();
+        return getNativeHandle() == that.getNativeHandle();
     }
 }
diff --git a/opengl/java/android/opengl/GLES10.java b/opengl/java/android/opengl/GLES10.java
index db52b82..fed84d5 100644
--- a/opengl/java/android/opengl/GLES10.java
+++ b/opengl/java/android/opengl/GLES10.java
@@ -262,7 +262,7 @@
 
     native private static void _nativeClassInit();
     static {
-	    _nativeClassInit();
+        _nativeClassInit();
     }
 
     private static Buffer _colorPointer;
diff --git a/opengl/java/android/opengl/GLES10Ext.java b/opengl/java/android/opengl/GLES10Ext.java
index 81fc59e..3dc26eb 100644
--- a/opengl/java/android/opengl/GLES10Ext.java
+++ b/opengl/java/android/opengl/GLES10Ext.java
@@ -22,7 +22,7 @@
 public class GLES10Ext {
     native private static void _nativeClassInit();
     static {
-	    _nativeClassInit();
+        _nativeClassInit();
     }
     
     // C function GLbitfield glQueryMatrixxOES ( GLfixed *mantissa, GLint *exponent )
diff --git a/opengl/java/android/opengl/GLES11.java b/opengl/java/android/opengl/GLES11.java
index 1ca179b..bb69bba 100644
--- a/opengl/java/android/opengl/GLES11.java
+++ b/opengl/java/android/opengl/GLES11.java
@@ -147,7 +147,7 @@
 
     native private static void _nativeClassInit();
     static {
-	    _nativeClassInit();
+        _nativeClassInit();
     }
 
     private static Buffer _pointSizePointerOES;
diff --git a/opengl/java/android/opengl/GLES11Ext.java b/opengl/java/android/opengl/GLES11Ext.java
index 484439a..04d1b5d 100644
--- a/opengl/java/android/opengl/GLES11Ext.java
+++ b/opengl/java/android/opengl/GLES11Ext.java
@@ -132,7 +132,7 @@
 
     native private static void _nativeClassInit();
     static {
-	    _nativeClassInit();
+        _nativeClassInit();
     }
     
     private static final int GL_BYTE = GLES10.GL_BYTE;
diff --git a/opengl/java/android/opengl/GLES30.java b/opengl/java/android/opengl/GLES30.java
index 9164849..342ffa4 100644
--- a/opengl/java/android/opengl/GLES30.java
+++ b/opengl/java/android/opengl/GLES30.java
@@ -864,13 +864,13 @@
         int buffer
     );
 
-	// C function void glTransformFeedbackVaryings ( GLuint program, GLsizei count, const GLchar *varyings, GLenum bufferMode )
+    // C function void glTransformFeedbackVaryings ( GLuint program, GLsizei count, const GLchar *varyings, GLenum bufferMode )
 
-	public static native void glTransformFeedbackVaryings(
+    public static native void glTransformFeedbackVaryings(
         int program,
         String[] varyings,
         int bufferMode
-	);
+    );
 
     // C function void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name )
 
@@ -1245,14 +1245,14 @@
         int size
     );
 
-	// C function void glGetUniformIndices ( GLuint program, GLsizei uniformCount, const GLchar *const *uniformNames, GLuint *uniformIndices )
+    // C function void glGetUniformIndices ( GLuint program, GLsizei uniformCount, const GLchar *const *uniformNames, GLuint *uniformIndices )
 
-	public static native void glGetUniformIndices(
+    public static native void glGetUniformIndices(
         int program,
         String[] uniformNames,
         int[] uniformIndices,
         int uniformIndicesOffset
-	);
+    );
 
     // C function void glGetUniformIndices ( GLuint program, GLsizei uniformCount, const GLchar *const *uniformNames, GLuint *uniformIndices )
 
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index 5a2e261..a9322b9 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -595,13 +595,9 @@
         mDetached = false;
     }
 
-    /**
-     * This method is used as part of the View class and is not normally
-     * called or subclassed by clients of GLSurfaceView.
-     * Must not be called before a renderer has been set.
-     */
+    /** @hide */
     @Override
-    protected void onDetachedFromWindow() {
+    protected void onDetachedFromWindowInternal() {
         if (LOG_ATTACH_DETACH) {
             Log.d(TAG, "onDetachedFromWindow");
         }
@@ -609,7 +605,7 @@
             mGLThread.requestExitAndWait();
         }
         mDetached = true;
-        super.onDetachedFromWindow();
+        super.onDetachedFromWindowInternal();
     }
 
     // ----------------------------------------------------------------------
diff --git a/opengl/java/com/google/android/gles_jni/GLImpl.java b/opengl/java/com/google/android/gles_jni/GLImpl.java
index 6b23be9..d4c0c80 100644
--- a/opengl/java/com/google/android/gles_jni/GLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/GLImpl.java
@@ -39,7 +39,7 @@
 
     native private static void _nativeClassInit();
     static {
-	_nativeClassInit();
+        _nativeClassInit();
     }
 
     Buffer _colorPointer = null;
diff --git a/packages/Keyguard/Android.mk b/packages/Keyguard/Android.mk
index 1f2b5fb..5b08674 100644
--- a/packages/Keyguard/Android.mk
+++ b/packages/Keyguard/Android.mk
@@ -16,7 +16,8 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-subdir-Iaidl-files)
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-subdir-Iaidl-files) \
+                   $(call all-proto-files-under,src)
 
 LOCAL_PACKAGE_NAME := Keyguard
 
@@ -26,6 +27,9 @@
 
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
 
+LOCAL_PROTOC_OPTIMIZE_TYPE := nano
+LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
+
 include $(BUILD_PACKAGE)
 
 #include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/Keyguard/res/layout-land/keyguard_simple_host_view.xml b/packages/Keyguard/res/layout-land/keyguard_simple_host_view.xml
new file mode 100644
index 0000000..ebd0a64
--- /dev/null
+++ b/packages/Keyguard/res/layout-land/keyguard_simple_host_view.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This is the host view that generally contains two sub views: the widget view
+    and the security view. -->
+<com.android.keyguard.KeyguardSimpleHostView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    android:id="@+id/keyguard_host_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <com.android.keyguard.KeyguardSecurityContainer
+        android:id="@+id/keyguard_security_container"
+        android:layout_width="wrap_content"
+        android:layout_height="@dimen/keyguard_security_height"
+        android:clipChildren="false"
+        android:clipToPadding="false"
+        android:padding="0dp"
+        android:layout_gravity="center">
+        <com.android.keyguard.KeyguardSecurityViewFlipper
+            android:id="@+id/view_flipper"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:clipChildren="false"
+            android:clipToPadding="false"
+            android:paddingTop="@dimen/keyguard_security_view_margin"
+            android:gravity="center">
+        </com.android.keyguard.KeyguardSecurityViewFlipper>
+    </com.android.keyguard.KeyguardSecurityContainer>
+
+</com.android.keyguard.KeyguardSimpleHostView>
+
diff --git a/packages/Keyguard/res/values-am/strings.xml b/packages/Keyguard/res/values-am/strings.xml
index fd4cf78..ebe678e 100644
--- a/packages/Keyguard/res/values-am/strings.xml
+++ b/packages/Keyguard/res/values-am/strings.xml
@@ -27,7 +27,7 @@
     <string name="keyguard_password_entry_touch_hint" msgid="7858547464982981384"><font size="17">"የይለፍ ቃል ለመተየብ ንካ"</font></string>
     <string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"ለመክፈት የይለፍ ቃል ተይብ"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"ለመክፈት ፒን ተይብ"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"ትክክል ያልሆነ PIN ኮድ።"</string>
+    <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"ትክክል ያልሆነ ፒን  ኮድ።"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"ለመክፈት፣ምናሌ ተጫን ከዛ 0"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"የመጨረሻውን  የገጽ ክፈት ሙከራዎችን አልፏል"</string>
     <string name="keyguard_charged" msgid="3272223906073492454">"ባትሪ ሞልቷል"</string>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index 7ac94bd..1e79ee4 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -1051,9 +1051,6 @@
     }
 
     private void enableUserSelectorIfNecessary() {
-        if (!UserManager.supportsMultipleUsers()) {
-            return; // device doesn't support multi-user mode
-        }
         final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
         if (um == null) {
             Throwable t = new Throwable();
@@ -1063,61 +1060,53 @@
         }
 
         // if there are multiple users, we need to enable to multi-user switcher
-        final List<UserInfo> users = um.getUsers(true);
-        if (users == null) {
-            Throwable t = new Throwable();
-            t.fillInStackTrace();
-            Log.e(TAG, "list of users is null.", t);
+        if (!um.isUserSwitcherEnabled()) {
             return;
         }
 
         final View multiUserView = findViewById(R.id.keyguard_user_selector);
         if (multiUserView == null) {
-            Throwable t = new Throwable();
-            t.fillInStackTrace();
-            Log.e(TAG, "can't find user_selector in layout.", t);
+            if (DEBUG) Log.d(TAG, "can't find user_selector in layout.");
             return;
         }
 
-        if (users.size() > 1) {
-            if (multiUserView instanceof KeyguardMultiUserSelectorView) {
-                mKeyguardMultiUserSelectorView = (KeyguardMultiUserSelectorView) multiUserView;
-                mKeyguardMultiUserSelectorView.setVisibility(View.VISIBLE);
-                mKeyguardMultiUserSelectorView.addUsers(users);
-                UserSwitcherCallback callback = new UserSwitcherCallback() {
-                    @Override
-                    public void hideSecurityView(int duration) {
-                        getSecurityContainer().animate().alpha(0).setDuration(duration);
-                    }
-
-                    @Override
-                    public void showSecurityView() {
-                        getSecurityContainer().setAlpha(1.0f);
-                    }
-
-                    @Override
-                    public void showUnlockHint() {
-                        if (getSecurityContainer() != null) {
-                            getSecurityContainer().showUsabilityHint();
-                        }
-                    }
-
-                    @Override
-                    public void userActivity() {
-                        if (mViewMediatorCallback != null) {
-                            mViewMediatorCallback.userActivity();
-                        }
-                    }
-                };
-                mKeyguardMultiUserSelectorView.setCallback(callback);
-            } else {
-                Throwable t = new Throwable();
-                t.fillInStackTrace();
-                if (multiUserView == null) {
-                    Log.e(TAG, "could not find the user_selector.", t);
-                } else {
-                    Log.e(TAG, "user_selector is the wrong type.", t);
+        if (multiUserView instanceof KeyguardMultiUserSelectorView) {
+            mKeyguardMultiUserSelectorView = (KeyguardMultiUserSelectorView) multiUserView;
+            mKeyguardMultiUserSelectorView.setVisibility(View.VISIBLE);
+            mKeyguardMultiUserSelectorView.addUsers(um.getUsers(true));
+            UserSwitcherCallback callback = new UserSwitcherCallback() {
+                @Override
+                public void hideSecurityView(int duration) {
+                    getSecurityContainer().animate().alpha(0).setDuration(duration);
                 }
+
+                @Override
+                public void showSecurityView() {
+                    getSecurityContainer().setAlpha(1.0f);
+                }
+
+                @Override
+                public void showUnlockHint() {
+                    if (getSecurityContainer() != null) {
+                        getSecurityContainer().showUsabilityHint();
+                    }
+                }
+
+                @Override
+                public void userActivity() {
+                    if (mViewMediatorCallback != null) {
+                        mViewMediatorCallback.userActivity();
+                    }
+                }
+            };
+            mKeyguardMultiUserSelectorView.setCallback(callback);
+        } else {
+            Throwable t = new Throwable();
+            t.fillInStackTrace();
+            if (multiUserView == null) {
+                Log.e(TAG, "could not find the user_selector.", t);
+            } else {
+                Log.e(TAG, "user_selector is the wrong type.", t);
             }
         }
     }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardMultiUserSelectorView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardMultiUserSelectorView.java
index 7975d8e..06815e1 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardMultiUserSelectorView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardMultiUserSelectorView.java
@@ -76,11 +76,13 @@
         Collections.sort(users, mOrderAddedComparator);
 
         for (UserInfo user: users) {
-            KeyguardMultiUserAvatar uv = createAndAddUser(user);
-            if (user.id == activeUser.id) {
-                mActiveUserAvatar = uv;
+            if (user.supportsSwitchTo()) {
+                KeyguardMultiUserAvatar uv = createAndAddUser(user);
+                if (user.id == activeUser.id) {
+                    mActiveUserAvatar = uv;
+                }
+                uv.setActive(false, false, null);
             }
-            uv.setActive(false, false, null);
         }
         mActiveUserAvatar.lockPressed(true);
     }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java
index 43165eb..8738288 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java
@@ -21,11 +21,11 @@
 
 import com.android.internal.policy.IKeyguardShowCallback;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.analytics.KeyguardAnalytics;
 
 import org.xmlpull.v1.XmlPullParser;
 
 import android.app.ActivityManager;
-import android.appwidget.AppWidgetManager;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
@@ -71,10 +71,12 @@
 
     // Timeout used for keypresses
     static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
+    private static final boolean ENABLE_SIMPLE_KEYGUARD = false;
 
     private final Context mContext;
     private final ViewManager mViewManager;
     private final KeyguardViewMediator.ViewMediatorCallback mViewMediatorCallback;
+    private final KeyguardAnalytics.Callback mAnalyticsCallback;
 
     private WindowManager.LayoutParams mWindowLayoutParams;
     private boolean mNeedsInput = false;
@@ -106,11 +108,12 @@
      */
     public KeyguardViewManager(Context context, ViewManager viewManager,
             KeyguardViewMediator.ViewMediatorCallback callback,
-            LockPatternUtils lockPatternUtils) {
+            LockPatternUtils lockPatternUtils, KeyguardAnalytics.Callback analyticsCallback) {
         mContext = context;
         mViewManager = viewManager;
         mViewMediatorCallback = callback;
         mLockPatternUtils = lockPatternUtils;
+        mAnalyticsCallback = analyticsCallback;
     }
 
     /**
@@ -119,6 +122,9 @@
      */
     public synchronized void show(Bundle options) {
         if (DEBUG) Log.d(TAG, "show(); mKeyguardView==" + mKeyguardView);
+        if (mAnalyticsCallback != null) {
+            mAnalyticsCallback.onShow();
+        }
 
         boolean enableScreenRotation = shouldEnableScreenRotation();
 
@@ -261,6 +267,15 @@
             }
             return super.dispatchKeyEvent(event);
         }
+
+        @Override
+        public boolean dispatchTouchEvent(MotionEvent ev) {
+            boolean result = false;
+            if (mAnalyticsCallback != null) {
+                result = mAnalyticsCallback.onTouchEvent(ev, getWidth(), getHeight()) || result;
+            }
+            return super.dispatchTouchEvent(ev) || result;
+        }
     }
 
     SparseArray<Parcelable> mStateContainer = new SparseArray<Parcelable>();
@@ -312,7 +327,7 @@
         if (force || mKeyguardView == null) {
             mKeyguardHost.setCustomBackground(null);
             mKeyguardHost.removeAllViews();
-            int layout = allowNotificationsOnSecureKeyguard()
+            int layout = (allowNotificationsOnSecureKeyguard() && ENABLE_SIMPLE_KEYGUARD)
                     ? R.layout.keyguard_simple_host_view
                     : R.layout.keyguard_host_view;
             if (mCurrentLayout != layout) {
@@ -472,6 +487,9 @@
                 Slog.w(TAG, "Exception calling onShown():", e);
             }
         }
+        if (mAnalyticsCallback != null) {
+            mAnalyticsCallback.onScreenOn();
+        }
     }
 
     public synchronized void verifyUnlock() {
@@ -486,6 +504,10 @@
     public synchronized void hide() {
         if (DEBUG) Log.d(TAG, "hide()");
 
+        if (mAnalyticsCallback != null) {
+            mAnalyticsCallback.onHide();
+        }
+
         if (mKeyguardHost != null) {
             mKeyguardHost.setVisibility(View.GONE);
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
index e0ee4e0..31e806c 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
@@ -19,6 +19,7 @@
 import com.android.internal.policy.IKeyguardExitCallback;
 import com.android.internal.policy.IKeyguardShowCallback;
 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+import static com.android.keyguard.analytics.KeyguardAnalytics.SessionTypeAdapter;
 
 import android.app.Activity;
 import android.app.ActivityManagerNative;
@@ -33,6 +34,7 @@
 import android.content.IntentFilter;
 import android.media.AudioManager;
 import android.media.SoundPool;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -54,6 +56,10 @@
 
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.analytics.Session;
+import com.android.keyguard.analytics.KeyguardAnalytics;
+
+import java.io.File;
 
 
 /**
@@ -100,6 +106,7 @@
 public class KeyguardViewMediator {
     private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
     final static boolean DEBUG = false;
+    private static final boolean ENABLE_ANALYTICS = Build.IS_DEBUGGABLE;
     private final static boolean DBG_WAKE = false;
 
     private final static String TAG = "KeyguardViewMediator";
@@ -161,6 +168,11 @@
      */
     private static final boolean ALLOW_NOTIFICATIONS_DEFAULT = false;
 
+    /**
+     * Secure setting whether analytics are collected on the keyguard.
+     */
+    private static final String KEYGUARD_ANALYTICS_SETTING = "keyguard_analytics";
+
     /** The stream type that the lock sounds are tied to. */
     private int mMasterStreamType;
 
@@ -194,6 +206,8 @@
 
     private KeyguardViewManager mKeyguardViewManager;
 
+    private final KeyguardAnalytics mKeyguardAnalytics;
+
     // these are protected by synchronized (this)
 
     /**
@@ -528,12 +542,25 @@
                 && !mLockPatternUtils.isLockScreenDisabled();
 
         WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
-
-        mKeyguardViewManager = new KeyguardViewManager(context, wm, mViewMediatorCallback,
-                mLockPatternUtils);
-
         final ContentResolver cr = mContext.getContentResolver();
 
+        if (ENABLE_ANALYTICS && !LockPatternUtils.isSafeModeEnabled() &&
+                Settings.Secure.getInt(cr, KEYGUARD_ANALYTICS_SETTING, 0) == 1) {
+            mKeyguardAnalytics = new KeyguardAnalytics(context, new SessionTypeAdapter() {
+
+                @Override
+                public int getSessionType() {
+                    return mLockPatternUtils.isSecure() ? Session.TYPE_KEYGUARD_SECURE
+                            : Session.TYPE_KEYGUARD_INSECURE;
+                }
+            }, new File(mContext.getCacheDir(), "keyguard_analytics.bin"));
+        } else {
+            mKeyguardAnalytics = null;
+        }
+        mKeyguardViewManager = new KeyguardViewManager(context, wm, mViewMediatorCallback,
+                mLockPatternUtils,
+                mKeyguardAnalytics != null ? mKeyguardAnalytics.getCallback() : null);
+
         mScreenOn = mPM.isScreenOn();
 
         mLockSounds = new SoundPool(1, AudioManager.STREAM_SYSTEM, 0);
@@ -631,6 +658,9 @@
             } else {
                 doKeyguardLocked(null);
             }
+            if (ENABLE_ANALYTICS && mKeyguardAnalytics != null) {
+                mKeyguardAnalytics.getCallback().onScreenOff();
+            }
         }
         KeyguardUpdateMonitor.getInstance(mContext).dispatchScreenTurndOff(why);
     }
@@ -704,7 +734,7 @@
 
     private void maybeSendUserPresentBroadcast() {
         if (mSystemReady && mLockPatternUtils.isLockScreenDisabled()
-                && mUserManager.getUsers(true).size() == 1) {
+                && !mUserManager.isUserSwitcherEnabled()) {
             // Lock screen is disabled because the user has set the preference to "None".
             // In this case, send out ACTION_USER_PRESENT here instead of in
             // handleKeyguardDone()
@@ -869,6 +899,9 @@
                 updateActivityLockScreenState();
                 adjustStatusBarLocked();
             }
+            if (ENABLE_ANALYTICS && mKeyguardAnalytics != null) {
+                mKeyguardAnalytics.getCallback().onSetHidden(isHidden);
+            }
         }
     }
 
@@ -940,7 +973,7 @@
             return;
         }
 
-        if (mUserManager.getUsers(true).size() < 2
+        if (!mUserManager.isUserSwitcherEnabled()
                 && mLockPatternUtils.isLockScreenDisabled() && !lockedOrMissing) {
             if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
             return;
diff --git a/packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java b/packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java
new file mode 100644
index 0000000..55750cc
--- /dev/null
+++ b/packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2014 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.keyguard.analytics;
+
+import com.google.protobuf.nano.CodedOutputByteBufferNano;
+import com.google.protobuf.nano.MessageNano;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.AsyncTask;
+import android.util.Log;
+import android.view.MotionEvent;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Tracks sessions, touch and sensor events in Keyguard.
+ *
+ * A session starts when the user is presented with the Keyguard and ends when the Keyguard is no
+ * longer visible to the user.
+ */
+public class KeyguardAnalytics implements SensorEventListener {
+
+    private static final boolean DEBUG = false;
+    private static final String TAG = "KeyguardAnalytics";
+    private static final long TIMEOUT_MILLIS = 11000; // 11 seconds.
+
+    private static final int[] SENSORS = new int[] {
+            Sensor.TYPE_ACCELEROMETER,
+            Sensor.TYPE_GYROSCOPE,
+            Sensor.TYPE_PROXIMITY,
+            Sensor.TYPE_LIGHT,
+            Sensor.TYPE_ROTATION_VECTOR,
+    };
+
+    private Session mCurrentSession = null;
+    // Err on the side of caution, so logging is not started after a crash even tough the screen
+    // is off.
+    private boolean mScreenOn = false;
+    private boolean mHidden = false;
+
+    private final SensorManager mSensorManager;
+    private final SessionTypeAdapter mSessionTypeAdapter;
+    private final File mAnalyticsFile;
+
+    public KeyguardAnalytics(Context context, SessionTypeAdapter sessionTypeAdapter,
+            File analyticsFile) {
+        mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
+        mSessionTypeAdapter = sessionTypeAdapter;
+        mAnalyticsFile = analyticsFile;
+    }
+
+    public Callback getCallback() {
+        return mCallback;
+    }
+
+    public interface Callback {
+        public void onShow();
+        public void onHide();
+        public void onScreenOn();
+        public void onScreenOff();
+        public boolean onTouchEvent(MotionEvent ev, int width, int height);
+        public void onSetHidden(boolean hidden);
+    }
+
+    public interface SessionTypeAdapter {
+        public int getSessionType();
+    }
+
+    private void sessionEntrypoint() {
+        if (mCurrentSession == null && mScreenOn && !mHidden) {
+            onSessionStart();
+        }
+    }
+
+    private void sessionExitpoint(int result) {
+        if (mCurrentSession != null) {
+            onSessionEnd(result);
+        }
+    }
+
+    private void onSessionStart() {
+        int type = mSessionTypeAdapter.getSessionType();
+        mCurrentSession = new Session(System.currentTimeMillis(), System.nanoTime(), type);
+        if (type == Session.TYPE_KEYGUARD_SECURE) {
+            mCurrentSession.setRedactTouchEvents();
+        }
+        for (int sensorType : SENSORS) {
+            Sensor s = mSensorManager.getDefaultSensor(sensorType);
+            if (s != null) {
+                mSensorManager.registerListener(this, s, SensorManager.SENSOR_DELAY_GAME);
+            }
+        }
+        if (DEBUG) {
+            Log.d(TAG, "onSessionStart()");
+        }
+    }
+
+    private void onSessionEnd(int result) {
+        if (DEBUG) {
+            Log.d(TAG, String.format("onSessionEnd(success=%d)", result));
+        }
+        mSensorManager.unregisterListener(this);
+
+        Session session = mCurrentSession;
+        mCurrentSession = null;
+
+        session.end(System.currentTimeMillis(), result);
+        queueSession(session);
+    }
+
+    private void queueSession(final Session currentSession) {
+        if (DEBUG) {
+            Log.i(TAG, "Saving session.");
+        }
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... params) {
+                try {
+                    byte[] b = writeDelimitedProto(currentSession.toProto());
+                    OutputStream os = new FileOutputStream(mAnalyticsFile, true /* append */);
+                    if (DEBUG) {
+                        Log.d(TAG, String.format("Serialized size: %d kB.", b.length / 1024));
+                    }
+                    try {
+                        os.write(b);
+                        os.flush();
+                    } finally {
+                        try {
+                            os.close();
+                        } catch (IOException e) {
+                            Log.e(TAG, "Exception while closing file", e);
+                        }
+                    }
+                } catch (IOException e) {
+                    Log.e(TAG, "Exception while writing file", e);
+                }
+                return null;
+            }
+
+            private byte[] writeDelimitedProto(MessageNano proto)
+                    throws IOException {
+                byte[] result = new byte[CodedOutputByteBufferNano.computeMessageSizeNoTag(proto)];
+                CodedOutputByteBufferNano ob = CodedOutputByteBufferNano.newInstance(result);
+                ob.writeMessageNoTag(proto);
+                ob.checkNoSpaceLeft();
+                return result;
+            }
+        }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
+    }
+
+    @Override
+    public synchronized void onSensorChanged(SensorEvent event) {
+        if (false) {
+            Log.v(TAG, String.format(
+                    "onSensorChanged(name=%s, values[0]=%f)",
+                    event.sensor.getName(), event.values[0]));
+        }
+        if (mCurrentSession != null) {
+            mCurrentSession.addSensorEvent(event, System.nanoTime());
+            enforceTimeout();
+        }
+    }
+
+    private void enforceTimeout() {
+        if (System.currentTimeMillis() - mCurrentSession.getStartTimestampMillis()
+                > TIMEOUT_MILLIS) {
+            onSessionEnd(Session.RESULT_UNKNOWN);
+            if (DEBUG) {
+                Log.i(TAG, "Analytics timed out.");
+            }
+        }
+    }
+
+    @Override
+    public void onAccuracyChanged(Sensor sensor, int accuracy) {
+    }
+
+    private final Callback mCallback = new Callback() {
+        @Override
+        public void onShow() {
+            if (DEBUG) {
+                Log.d(TAG, "onShow()");
+            }
+            synchronized (KeyguardAnalytics.this) {
+                sessionEntrypoint();
+            }
+        }
+
+        @Override
+        public void onHide() {
+            if (DEBUG) {
+                Log.d(TAG, "onHide()");
+            }
+            synchronized (KeyguardAnalytics.this) {
+                sessionExitpoint(Session.RESULT_SUCCESS);
+            }
+        }
+
+        @Override
+        public void onScreenOn() {
+            if (DEBUG) {
+                Log.d(TAG, "onScreenOn()");
+            }
+            synchronized (KeyguardAnalytics.this) {
+                mScreenOn = true;
+                sessionEntrypoint();
+            }
+        }
+
+        @Override
+        public void onScreenOff() {
+            if (DEBUG) {
+                Log.d(TAG, "onScreenOff()");
+            }
+            synchronized (KeyguardAnalytics.this) {
+                mScreenOn = false;
+                sessionExitpoint(Session.RESULT_FAILURE);
+            }
+        }
+
+        @Override
+        public boolean onTouchEvent(MotionEvent ev, int width, int height) {
+            if (DEBUG) {
+                Log.v(TAG, "onTouchEvent(ev.action="
+                        + MotionEvent.actionToString(ev.getAction()) + ")");
+            }
+            synchronized (KeyguardAnalytics.this) {
+                if (mCurrentSession != null) {
+                    mCurrentSession.addMotionEvent(ev);
+                    mCurrentSession.setTouchArea(width, height);
+                    enforceTimeout();
+                }
+            }
+            return true;
+        }
+
+        @Override
+        public void onSetHidden(boolean hidden) {
+            synchronized (KeyguardAnalytics.this) {
+                if (hidden != mHidden) {
+                    if (DEBUG) {
+                        Log.d(TAG, "onSetHidden(" + hidden + ")");
+                    }
+                    mHidden = hidden;
+                    if (hidden) {
+                        // Could have gone to camera on purpose / by falsing or an app could have
+                        // launched on top of the lockscreen.
+                        sessionExitpoint(Session.RESULT_UNKNOWN);
+                    } else {
+                        sessionEntrypoint();
+                    }
+                }
+            }
+        }
+    };
+
+}
diff --git a/packages/Keyguard/src/com/android/keyguard/analytics/PointerTracker.java b/packages/Keyguard/src/com/android/keyguard/analytics/PointerTracker.java
new file mode 100644
index 0000000..e68f751
--- /dev/null
+++ b/packages/Keyguard/src/com/android/keyguard/analytics/PointerTracker.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2014 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.keyguard.analytics;
+
+import android.graphics.RectF;
+import android.util.FloatMath;
+import android.util.SparseArray;
+import android.view.MotionEvent;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.android.keyguard.analytics.KeyguardAnalyticsProtos.Session.TouchEvent.BoundingBox;
+
+/**
+ * Takes motion events and tracks the length and bounding box of each pointer gesture as well as
+ * the bounding box of the whole gesture.
+ */
+public class PointerTracker {
+    private SparseArray<Pointer> mPointerInfoMap = new SparseArray<Pointer>();
+    private RectF mTotalBoundingBox = new RectF();
+
+    public void addMotionEvent(MotionEvent ev) {
+        if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
+            float x = ev.getX();
+            float y = ev.getY();
+            mTotalBoundingBox.set(x, y, x, y);
+        }
+        for (int i = 0; i < ev.getPointerCount(); i++) {
+            int id = ev.getPointerId(i);
+            Pointer pointer = getPointer(id);
+            float x = ev.getX(i);
+            float y = ev.getY(i);
+            boolean down = ev.getActionMasked() == MotionEvent.ACTION_DOWN
+                    || (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN
+                            && ev.getActionIndex() == i);
+            pointer.addPoint(x, y, down);
+            mTotalBoundingBox.union(x, y);
+        }
+    }
+
+    public float getPointerLength(int id) {
+        return getPointer(id).length;
+    }
+
+    public BoundingBox getBoundingBox() {
+        return boundingBoxFromRect(mTotalBoundingBox);
+    }
+
+    public BoundingBox getPointerBoundingBox(int id) {
+        return boundingBoxFromRect(getPointer(id).boundingBox);
+    }
+
+    private BoundingBox boundingBoxFromRect(RectF f) {
+        BoundingBox bb = new BoundingBox();
+        bb.setHeight(f.height());
+        bb.setWidth(f.width());
+        return bb;
+    }
+
+    private Pointer getPointer(int id) {
+        Pointer p = mPointerInfoMap.get(id);
+        if (p == null) {
+            p = new Pointer();
+            mPointerInfoMap.put(id, p);
+        }
+        return p;
+    }
+
+    private static class Pointer {
+        public float length;
+        public final RectF boundingBox = new RectF();
+
+        private float mLastX;
+        private float mLastY;
+
+        public void addPoint(float x, float y, boolean down) {
+            float deltaX;
+            float deltaY;
+            if (down) {
+                boundingBox.set(x, y, x, y);
+                length = 0f;
+                deltaX = 0;
+                deltaY = 0;
+            } else {
+                deltaX = x - mLastX;
+                deltaY = y - mLastY;
+            }
+            mLastX = x;
+            mLastY = y;
+            length += FloatMath.sqrt(deltaX * deltaX + deltaY * deltaY);
+            boundingBox.union(x, y);
+        }
+    }
+}
diff --git a/packages/Keyguard/src/com/android/keyguard/analytics/Session.java b/packages/Keyguard/src/com/android/keyguard/analytics/Session.java
new file mode 100644
index 0000000..05f9165
--- /dev/null
+++ b/packages/Keyguard/src/com/android/keyguard/analytics/Session.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2014 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.keyguard.analytics;
+
+import android.os.Build;
+import android.util.Slog;
+import android.view.MotionEvent;
+
+import java.util.ArrayList;
+
+import static com.android.keyguard.analytics.KeyguardAnalyticsProtos.Session.SensorEvent;
+import static com.android.keyguard.analytics.KeyguardAnalyticsProtos.Session.TouchEvent;
+
+/**
+ * Records data about one keyguard session.
+ *
+ * The recorded data contains start and end of the session, whether it unlocked the device
+ * successfully, sensor data and touch data.
+ *
+ * If the keyguard is secure, the recorded touch data will correlate or contain the user pattern or
+ * PIN. If this is not desired, the touch coordinates can be redacted before serialization.
+ */
+public class Session {
+
+    private static final String TAG = "KeyguardAnalytics";
+    private static final boolean DEBUG = false;
+
+    /**
+     * The user has failed to unlock the device in this session.
+     */
+    public static final int RESULT_FAILURE = KeyguardAnalyticsProtos.Session.FAILURE;
+    /**
+     * The user has succeeded in unlocking the device in this session.
+     */
+    public static final int RESULT_SUCCESS = KeyguardAnalyticsProtos.Session.SUCCESS;
+
+    /**
+     * It is unknown how the session with the keyguard ended.
+     */
+    public static final int RESULT_UNKNOWN = KeyguardAnalyticsProtos.Session.UNKNOWN;
+
+    /**
+     * This session took place on an insecure keyguard.
+     */
+    public static final int TYPE_KEYGUARD_INSECURE
+            = KeyguardAnalyticsProtos.Session.KEYGUARD_INSECURE;
+
+    /**
+     * This session took place on an secure keyguard.
+     */
+    public static final int TYPE_KEYGUARD_SECURE
+            = KeyguardAnalyticsProtos.Session.KEYGUARD_SECURE;
+
+    /**
+     * This session took place during a fake wake up of the device.
+     */
+    public static final int TYPE_RANDOM_WAKEUP = KeyguardAnalyticsProtos.Session.RANDOM_WAKEUP;
+
+
+    private final PointerTracker mPointerTracker = new PointerTracker();
+
+    private final long mStartTimestampMillis;
+    private final long mStartSystemTimeNanos;
+    private final int mType;
+
+    private boolean mRedactTouchEvents;
+    private ArrayList<TouchEvent> mMotionEvents = new ArrayList<TouchEvent>(200);
+    private ArrayList<SensorEvent> mSensorEvents = new ArrayList<SensorEvent>(600);
+    private int mTouchAreaHeight;
+    private int mTouchAreaWidth;
+
+    private long mEndTimestampMillis;
+    private int mResult;
+    private boolean mEnded;
+
+    public Session(long startTimestampMillis, long startSystemTimeNanos, int type) {
+        mStartTimestampMillis = startTimestampMillis;
+        mStartSystemTimeNanos = startSystemTimeNanos;
+        mType = type;
+    }
+
+    public void end(long endTimestampMillis, int result) {
+        mEnded = true;
+        mEndTimestampMillis = endTimestampMillis;
+        mResult = result;
+    }
+
+    public void addMotionEvent(MotionEvent motionEvent) {
+        if (mEnded) {
+            return;
+        }
+        mPointerTracker.addMotionEvent(motionEvent);
+        mMotionEvents.add(protoFromMotionEvent(motionEvent));
+    }
+
+    public void addSensorEvent(android.hardware.SensorEvent eventOrig, long systemTimeNanos) {
+        if (mEnded) {
+            return;
+        }
+        SensorEvent event = protoFromSensorEvent(eventOrig, systemTimeNanos);
+        mSensorEvents.add(event);
+        if (DEBUG) {
+            Slog.v(TAG, String.format("addSensorEvent(name=%s, values[0]=%f",
+                    event.getType(), event.values[0]));
+        }
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder("Session{");
+        sb.append("mType=").append(mType);
+        sb.append(", mStartTimestampMillis=").append(mStartTimestampMillis);
+        sb.append(", mStartSystemTimeNanos=").append(mStartSystemTimeNanos);
+        sb.append(", mEndTimestampMillis=").append(mEndTimestampMillis);
+        sb.append(", mResult=").append(mResult);
+        sb.append(", mRedactTouchEvents=").append(mRedactTouchEvents);
+        sb.append(", mTouchAreaHeight=").append(mTouchAreaHeight);
+        sb.append(", mTouchAreaWidth=").append(mTouchAreaWidth);
+        sb.append(", mMotionEvents=[size=").append(mMotionEvents.size()).append("]");
+        sb.append(", mSensorEvents=[size=").append(mSensorEvents.size()).append("]");
+        sb.append('}');
+        return sb.toString();
+    }
+
+    public KeyguardAnalyticsProtos.Session toProto() {
+        KeyguardAnalyticsProtos.Session proto = new KeyguardAnalyticsProtos.Session();
+        proto.setStartTimestampMillis(mStartTimestampMillis);
+        proto.setDurationMillis(mEndTimestampMillis - mStartTimestampMillis);
+        proto.setBuild(Build.FINGERPRINT);
+        proto.setResult(mResult);
+        proto.sensorEvents = mSensorEvents.toArray(proto.sensorEvents);
+        proto.touchEvents = mMotionEvents.toArray(proto.touchEvents);
+        proto.setTouchAreaWidth(mTouchAreaWidth);
+        proto.setTouchAreaHeight(mTouchAreaHeight);
+        proto.setType(mType);
+        if (mRedactTouchEvents) {
+            redactTouchEvents(proto.touchEvents);
+        }
+        return proto;
+    }
+
+    private void redactTouchEvents(TouchEvent[] touchEvents) {
+        for (int i = 0; i < touchEvents.length; i++) {
+            TouchEvent t = touchEvents[i];
+            for (int j = 0; j < t.pointers.length; j++) {
+                TouchEvent.Pointer p = t.pointers[j];
+                p.clearX();
+                p.clearY();
+            }
+            t.setRedacted(true);
+        }
+    }
+
+    private SensorEvent protoFromSensorEvent(android.hardware.SensorEvent ev, long sysTimeNanos) {
+        SensorEvent proto = new SensorEvent();
+        proto.setType(ev.sensor.getType());
+        proto.setTimeOffsetNanos(sysTimeNanos - mStartSystemTimeNanos);
+        proto.setTimestamp(ev.timestamp);
+        proto.values = ev.values.clone();
+        return proto;
+    }
+
+    private TouchEvent protoFromMotionEvent(MotionEvent ev) {
+        int count = ev.getPointerCount();
+        TouchEvent proto = new TouchEvent();
+        proto.setTimeOffsetNanos(ev.getEventTimeNano() - mStartSystemTimeNanos);
+        proto.setAction(ev.getActionMasked());
+        proto.setActionIndex(ev.getActionIndex());
+        proto.pointers = new TouchEvent.Pointer[count];
+        for (int i = 0; i < count; i++) {
+            TouchEvent.Pointer p = new TouchEvent.Pointer();
+            p.setX(ev.getX(i));
+            p.setY(ev.getY(i));
+            p.setSize(ev.getSize(i));
+            p.setPressure(ev.getPressure(i));
+            p.setId(ev.getPointerId(i));
+            proto.pointers[i] = p;
+            if ((ev.getActionMasked() == MotionEvent.ACTION_POINTER_UP && ev.getActionIndex() == i)
+                    || ev.getActionMasked() == MotionEvent.ACTION_UP) {
+                p.boundingBox = mPointerTracker.getPointerBoundingBox(p.getId());
+                p.setLength(mPointerTracker.getPointerLength(p.getId()));
+            }
+        }
+        if (ev.getActionMasked() == MotionEvent.ACTION_UP) {
+            proto.boundingBox = mPointerTracker.getBoundingBox();
+        }
+        return proto;
+    }
+
+    /**
+     * Discards the x / y coordinates of the touch events on serialization. Retained are the
+     * size of the individual and overall bounding boxes and the length of each pointer's gesture.
+     */
+    public void setRedactTouchEvents() {
+        mRedactTouchEvents = true;
+    }
+
+    public void setTouchArea(int width, int height) {
+        mTouchAreaWidth = width;
+        mTouchAreaHeight = height;
+    }
+
+    public long getStartTimestampMillis() {
+        return mStartTimestampMillis;
+    }
+}
diff --git a/packages/Keyguard/src/com/android/keyguard/analytics/keyguard_analytics.proto b/packages/Keyguard/src/com/android/keyguard/analytics/keyguard_analytics.proto
new file mode 100644
index 0000000..68b1590
--- /dev/null
+++ b/packages/Keyguard/src/com/android/keyguard/analytics/keyguard_analytics.proto
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2014 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
+ */
+
+syntax = "proto2";
+
+package keyguard;
+
+option java_package = "com.android.keyguard.analytics";
+option java_outer_classname = "KeyguardAnalyticsProtos";
+
+message Session {
+    message TouchEvent {
+        message BoundingBox {
+            optional float width = 1;
+            optional float height = 2;
+        }
+
+        enum Action {
+            // Keep in sync with MotionEvent.
+            DOWN = 0;
+            UP = 1;
+            MOVE = 2;
+            CANCEL = 3;
+            OUTSIDE = 4;
+            POINTER_DOWN = 5;
+            POINTER_UP = 6;
+        }
+
+        message Pointer {
+            optional float x = 1;
+            optional float y = 2;
+            optional float size = 3;
+            optional float pressure = 4;
+            optional int32 id = 5;
+            optional float length = 6;
+            // Bounding box of the pointer. Only set on UP or POINTER_UP event of this pointer.
+            optional BoundingBox boundingBox = 7;
+        }
+
+        optional uint64 timeOffsetNanos = 1;
+        optional Action action = 2;
+        optional int32 actionIndex = 3;
+        repeated Pointer pointers = 4;
+        /* If true, the the x / y coordinates of the touch events were redacted. Retained are the
+           size of the individual and overall bounding boxes and the length of each pointer's
+           gesture. */
+        optional bool redacted = 5;
+        // Bounding box of the whole gesture. Only set on UP event.
+        optional BoundingBox boundingBox = 6;
+    }
+
+    message SensorEvent {
+        enum Type {
+            ACCELEROMETER = 1;
+            GYROSCOPE = 4;
+            LIGHT = 5;
+            PROXIMITY = 8;
+            ROTATION_VECTOR = 11;
+        }
+
+        optional Type type = 1;
+        optional uint64 timeOffsetNanos = 2;
+        repeated float values = 3;
+        optional uint64 timestamp = 4;
+    }
+
+    enum Result {
+        FAILURE = 0;
+        SUCCESS = 1;
+        UNKNOWN = 2;
+    }
+
+    enum Type {
+        KEYGUARD_INSECURE = 0;
+        KEYGUARD_SECURE = 1;
+        RANDOM_WAKEUP = 2;
+    }
+
+    optional uint64 startTimestampMillis = 1;
+    optional uint64 durationMillis = 2;
+    optional string build = 3;
+    optional Result result = 4;
+    repeated TouchEvent touchEvents = 5;
+    repeated SensorEvent sensorEvents = 6;
+
+    optional int32 touchAreaWidth = 9;
+    optional int32 touchAreaHeight = 10;
+    optional Type type = 11;
+}
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 69f7152..59b486f 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -183,4 +183,10 @@
     <!-- Default for Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE -->
     <integer name="def_wifi_scan_always_available">0</integer>
 
+    <!-- Default for Settings.Global.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1==on -->
+    <integer name="def_lock_screen_show_notifications">1</integer>
+
+    <!-- Default for Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED, 1==on -->
+    <integer name="def_heads_up_enabled">1</integer>
+
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index f316d88..55d7def 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -69,7 +69,7 @@
     // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
     // is properly propagated through your change.  Not doing so will result in a loss of user
     // settings.
-    private static final int DATABASE_VERSION = 98;
+    private static final int DATABASE_VERSION = 100;
 
     private Context mContext;
     private int mUserHandle;
@@ -1556,6 +1556,42 @@
             upgradeVersion = 98;
         }
 
+        if (upgradeVersion == 98) {
+            if (mUserHandle == UserHandle.USER_OWNER) {
+                db.beginTransaction();
+                SQLiteStatement stmt = null;
+                try {
+                    stmt = db.compileStatement("INSERT OR REPLACE INTO global(name,value)"
+                            + " VALUES(?,?);");
+                    loadIntegerSetting(stmt, Settings.Global.LOCK_SCREEN_SHOW_NOTIFICATIONS,
+                            R.integer.def_lock_screen_show_notifications);
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                    if (stmt != null) stmt.close();
+                }
+            }
+            upgradeVersion = 99;
+        }
+
+        if (upgradeVersion == 99) {
+            if (mUserHandle == UserHandle.USER_OWNER) {
+                db.beginTransaction();
+                SQLiteStatement stmt = null;
+                try {
+                    stmt = db.compileStatement("INSERT OR REPLACE INTO global(name,value)"
+                            + " VALUES(?,?);");
+                    loadIntegerSetting(stmt, Global.HEADS_UP_NOTIFICATIONS_ENABLED,
+                            R.integer.def_heads_up_enabled);
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                    if (stmt != null) stmt.close();
+                }
+            }
+            upgradeVersion = 100;
+        }
+
         // *** Remember to update DATABASE_VERSION above!
 
         if (upgradeVersion != currentVersion) {
diff --git a/packages/SystemUI/res/anim/heads_up_exit.xml b/packages/SystemUI/res/anim/heads_up_exit.xml
index 05c144a..2cad8f6 100644
--- a/packages/SystemUI/res/anim/heads_up_exit.xml
+++ b/packages/SystemUI/res/anim/heads_up_exit.xml
@@ -1,13 +1,11 @@
 <?xml version="1.0" encoding="utf-8"?>
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         >
-    <scale
-        android:interpolator="@android:interpolator/accelerate_quad"
-        android:fromXScale="1.0" android:toXScale="0.7"
-        android:fromYScale="1.0" android:toYScale="0.7"
-        android:pivotX="50%" android:pivotY="50%"
-        android:duration="@android:integer/config_shortAnimTime" />
-    <alpha 
+    <translate
+            android:interpolator="@android:interpolator/overshoot"
+            android:fromYDelta="0" android:toYDelta="-50%"
+            android:duration="@android:integer/config_shortAnimTime" />
+    <alpha
         android:interpolator="@android:interpolator/accelerate_quad"
         android:fromAlpha="1.0" android:toAlpha="0.0"
         android:duration="@android:integer/config_shortAnimTime" />
diff --git a/packages/SystemUI/res/anim/hydraulic_brake_interpolator.xml b/packages/SystemUI/res/anim/hydraulic_brake_interpolator.xml
deleted file mode 100644
index 5b6778e..0000000
--- a/packages/SystemUI/res/anim/hydraulic_brake_interpolator.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/res/anim/ease_out_interpolator.xml
-**
-** 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.
-*/
--->
-
-<decelerateInterpolator 
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:factor="10.0" />
diff --git a/packages/SystemUI/res/anim/lights_out_in.xml b/packages/SystemUI/res/anim/lights_out_in.xml
deleted file mode 100644
index f76a452..0000000
--- a/packages/SystemUI/res/anim/lights_out_in.xml
+++ /dev/null
@@ -1,26 +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.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-    >
-    <translate android:fromYDelta="-100%p" android:toYDelta="0"
-        android:duration="@android:integer/config_mediumAnimTime" 
-        android:interpolator="@anim/hydraulic_brake_interpolator"
-        />
-    <alpha android:fromAlpha="0.5" android:toAlpha="1.0"
-        android:duration="@android:integer/config_longAnimTime" 
-        />
-</set>
diff --git a/packages/SystemUI/res/anim/lights_out_out.xml b/packages/SystemUI/res/anim/lights_out_out.xml
deleted file mode 100644
index 610ac7a..0000000
--- a/packages/SystemUI/res/anim/lights_out_out.xml
+++ /dev/null
@@ -1,26 +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.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-    >
-    <translate android:toYDelta="-100%p" android:fromYDelta="0" 
-        android:duration="@android:integer/config_mediumAnimTime" 
-        android:interpolator="@anim/hydraulic_brake_interpolator"
-        />
-    <alpha android:toAlpha="0.5" android:fromAlpha="1.0"
-        android:duration="@android:integer/config_longAnimTime" 
-        />
-</set>
diff --git a/packages/SystemUI/res/anim/notification_dnd_off.xml b/packages/SystemUI/res/anim/notification_dnd_off.xml
deleted file mode 100644
index 4e88855..0000000
--- a/packages/SystemUI/res/anim/notification_dnd_off.xml
+++ /dev/null
@@ -1,23 +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.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-    >
-    <translate android:fromXDelta="100%p" android:toXDelta="0"
-        android:duration="@android:integer/config_longAnimTime" 
-        android:interpolator="@anim/hydraulic_brake_interpolator"
-        />
-</set>
diff --git a/packages/SystemUI/res/anim/notification_dnd_on.xml b/packages/SystemUI/res/anim/notification_dnd_on.xml
deleted file mode 100644
index 309943b..0000000
--- a/packages/SystemUI/res/anim/notification_dnd_on.xml
+++ /dev/null
@@ -1,23 +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.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-    >
-    <translate android:toXDelta="100%p" android:fromXDelta="0"
-        android:duration="@android:integer/config_longAnimTime" 
-        android:interpolator="@anim/hydraulic_brake_interpolator"
-        />
-</set>
diff --git a/packages/SystemUI/res/drawable-hdpi/heads_up_window_bg.9.png b/packages/SystemUI/res/drawable-hdpi/heads_up_window_bg.9.png
deleted file mode 100644
index 3b952d0..0000000
--- a/packages/SystemUI/res/drawable-hdpi/heads_up_window_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_color_space_alpha.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_color_space_alpha.png
new file mode 100644
index 0000000..fe6dc52
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_color_space_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_contrast_alpha.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_contrast_alpha.png
new file mode 100644
index 0000000..0f9dfc7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_contrast_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_inversion_alpha.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_inversion_alpha.png
new file mode 100644
index 0000000..aea75c1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_inversion_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/spinner_default_holo_dark_am_no_underline.9.png b/packages/SystemUI/res/drawable-hdpi/spinner_default_holo_dark_am_no_underline.9.png
new file mode 100644
index 0000000..267e7ba
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/spinner_default_holo_dark_am_no_underline.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_zen_full.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_zen_full.png
new file mode 100644
index 0000000..fa23e85
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_zen_full.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_zen_limited.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_zen_limited.png
new file mode 100644
index 0000000..aa8635c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_zen_limited.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldpi/ic_qs_color_space_alpha.png b/packages/SystemUI/res/drawable-ldpi/ic_qs_color_space_alpha.png
new file mode 100644
index 0000000..46d2a16
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldpi/ic_qs_color_space_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldpi/ic_qs_contrast_alpha.png b/packages/SystemUI/res/drawable-ldpi/ic_qs_contrast_alpha.png
new file mode 100644
index 0000000..704b4ec
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldpi/ic_qs_contrast_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldpi/ic_qs_inversion_alpha.png b/packages/SystemUI/res/drawable-ldpi/ic_qs_inversion_alpha.png
new file mode 100644
index 0000000..d56efb5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldpi/ic_qs_inversion_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/heads_up_window_bg.9.png b/packages/SystemUI/res/drawable-mdpi/heads_up_window_bg.9.png
deleted file mode 100644
index a0ab991..0000000
--- a/packages/SystemUI/res/drawable-mdpi/heads_up_window_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_color_space_alpha.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_color_space_alpha.png
new file mode 100644
index 0000000..18b6029
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_color_space_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_contrast_alpha.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_contrast_alpha.png
new file mode 100644
index 0000000..a4dd087
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_contrast_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_inversion_alpha.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_inversion_alpha.png
new file mode 100644
index 0000000..b6ea14e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_inversion_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/spinner_default_holo_dark_am_no_underline.9.png b/packages/SystemUI/res/drawable-mdpi/spinner_default_holo_dark_am_no_underline.9.png
new file mode 100644
index 0000000..db51f6b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/spinner_default_holo_dark_am_no_underline.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_zen_full.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_zen_full.png
new file mode 100644
index 0000000..b0185a5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_zen_full.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_zen_limited.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_zen_limited.png
new file mode 100644
index 0000000..949ab10
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_zen_limited.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/heads_up_window_bg.9.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/heads_up_window_bg.9.png
new file mode 100644
index 0000000..b30cf15
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/heads_up_window_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/heads_up_window_bg.9.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/heads_up_window_bg.9.png
index 6002cfb..31eb8f7 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/heads_up_window_bg.9.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/heads_up_window_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/heads_up_window_bg.9.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/heads_up_window_bg.9.png
index 586a738..c76d0e1 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/heads_up_window_bg.9.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/heads_up_window_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/heads_up_window_bg.9.png b/packages/SystemUI/res/drawable-xhdpi/heads_up_window_bg.9.png
deleted file mode 100644
index 42e5593..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/heads_up_window_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_color_space_alpha.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_color_space_alpha.png
new file mode 100644
index 0000000..95cf67f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_color_space_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_contrast_alpha.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_contrast_alpha.png
new file mode 100644
index 0000000..9331e52
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_contrast_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_inversion_alpha.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_inversion_alpha.png
new file mode 100644
index 0000000..efd8b9e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_inversion_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/spinner_default_holo_dark_am_no_underline.9.png b/packages/SystemUI/res/drawable-xhdpi/spinner_default_holo_dark_am_no_underline.9.png
new file mode 100644
index 0000000..8d22ce2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/spinner_default_holo_dark_am_no_underline.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_zen_full.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_zen_full.png
new file mode 100644
index 0000000..7f7cb63
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_zen_full.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_zen_limited.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_zen_limited.png
new file mode 100644
index 0000000..abdeb3b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_zen_limited.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/heads_up_window_bg.9.png b/packages/SystemUI/res/drawable-xxhdpi/heads_up_window_bg.9.png
deleted file mode 100644
index 586a738..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/heads_up_window_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_color_space_alpha.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_color_space_alpha.png
new file mode 100644
index 0000000..7f441c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_color_space_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_contrast_alpha.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_contrast_alpha.png
new file mode 100644
index 0000000..82c3842
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_contrast_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_inversion_alpha.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_inversion_alpha.png
new file mode 100644
index 0000000..ce9bae2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_inversion_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/spinner_default_holo_dark_am_no_underline.9.png b/packages/SystemUI/res/drawable-xxhdpi/spinner_default_holo_dark_am_no_underline.9.png
new file mode 100644
index 0000000..29fb50f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/spinner_default_holo_dark_am_no_underline.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_zen_full.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_zen_full.png
new file mode 100644
index 0000000..afe85b4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_zen_full.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_zen_limited.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_zen_limited.png
new file mode 100644
index 0000000..5e5053f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_zen_limited.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/heads_up_notification_row_bg.xml b/packages/SystemUI/res/drawable/heads_up_notification_row_bg.xml
deleted file mode 100644
index 59d9fcf..0000000
--- a/packages/SystemUI/res/drawable/heads_up_notification_row_bg.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
-          android:exitFadeDuration="@android:integer/config_mediumAnimTime">
-    <item android:state_pressed="true"
-          android:drawable="@drawable/heads_up_notification_bg_pressed" />
-</selector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_color_space_off.xml b/packages/SystemUI/res/drawable/ic_qs_color_space_off.xml
new file mode 100644
index 0000000..cf34ba6
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_color_space_off.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_qs_color_space_alpha"
+    android:tint="@color/ic_qs_off" />
diff --git a/packages/SystemUI/res/drawable/ic_qs_color_space_on.xml b/packages/SystemUI/res/drawable/ic_qs_color_space_on.xml
new file mode 100644
index 0000000..1806688
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_color_space_on.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_qs_color_space_alpha"
+    android:tint="@color/ic_qs_on" />
diff --git a/packages/SystemUI/res/drawable/ic_qs_contrast_off.xml b/packages/SystemUI/res/drawable/ic_qs_contrast_off.xml
new file mode 100644
index 0000000..5f65d8a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_contrast_off.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_qs_contrast_alpha"
+    android:tint="@color/ic_qs_off" />
diff --git a/packages/SystemUI/res/drawable/ic_qs_contrast_on.xml b/packages/SystemUI/res/drawable/ic_qs_contrast_on.xml
new file mode 100644
index 0000000..a018929
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_contrast_on.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_qs_contrast_alpha"
+    android:tint="@color/ic_qs_on" />
diff --git a/packages/SystemUI/res/drawable/ic_qs_inversion_off.xml b/packages/SystemUI/res/drawable/ic_qs_inversion_off.xml
new file mode 100644
index 0000000..9018a90
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_inversion_off.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_qs_inversion_alpha"
+    android:tint="@color/ic_qs_off" />
diff --git a/packages/SystemUI/res/drawable/ic_qs_inversion_on.xml b/packages/SystemUI/res/drawable/ic_qs_inversion_on.xml
new file mode 100644
index 0000000..9110201
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_inversion_on.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_qs_inversion_alpha"
+    android:tint="@color/ic_qs_on" />
diff --git a/packages/SystemUI/res/drawable/notification_icon_legacy_bg.xml b/packages/SystemUI/res/drawable/notification_icon_legacy_bg.xml
new file mode 100644
index 0000000..4ac67c3
--- /dev/null
+++ b/packages/SystemUI/res/drawable/notification_icon_legacy_bg.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 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
+  -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="oval">
+    <solid
+            android:color="@color/notification_icon_legacy_bg_color"/>
+</shape>
diff --git a/packages/SystemUI/res/drawable/notification_icon_legacy_bg_inset.xml b/packages/SystemUI/res/drawable/notification_icon_legacy_bg_inset.xml
new file mode 100644
index 0000000..96c5573
--- /dev/null
+++ b/packages/SystemUI/res/drawable/notification_icon_legacy_bg_inset.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 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
+  -->
+
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+       android:drawable="@drawable/notification_icon_legacy_bg" android:insetBottom="8dp"
+       android:insetLeft="8dp" android:insetRight="8dp" android:insetTop="8dp"
+       android:visible="true"/>
diff --git a/packages/SystemUI/res/layout-sw600dp/heads_up.xml b/packages/SystemUI/res/layout-sw600dp/heads_up.xml
new file mode 100644
index 0000000..71f7c21
--- /dev/null
+++ b/packages/SystemUI/res/layout-sw600dp/heads_up.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<com.android.systemui.statusbar.policy.HeadsUpNotificationView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    >
+    <FrameLayout
+        android:id="@+id/content_holder"
+        android:layout_height="wrap_content"
+        android:layout_width="@dimen/notification_panel_width"
+        android:layout_marginStart="@dimen/notification_panel_margin_left"
+        android:background="@drawable/heads_up_window_bg"
+        />
+</com.android.systemui.statusbar.policy.HeadsUpNotificationView>
diff --git a/packages/SystemUI/res/layout/heads_up.xml b/packages/SystemUI/res/layout/heads_up.xml
index 564dc51..3a58b84 100644
--- a/packages/SystemUI/res/layout/heads_up.xml
+++ b/packages/SystemUI/res/layout/heads_up.xml
@@ -17,25 +17,11 @@
 ** limitations under the License.
 */
 -->
-
-<!--    android:background="@drawable/status_bar_closed_default_background" -->
 <com.android.systemui.statusbar.policy.HeadsUpNotificationView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_height="wrap_content"
-    android:layout_width="match_parent"
-    android:orientation="vertical"
-    >
-    <FrameLayout
-            android:layout_height="wrap_content"
-            android:layout_width="@dimen/notification_panel_width"
-            android:id="@+id/content_slider"
-            android:layout_marginStart="@dimen/notification_panel_margin_left"
-            >
-        <FrameLayout
-                android:layout_height="wrap_content"
-                android:layout_width="match_parent"
-                android:id="@+id/content_holder"
-                android:background="@drawable/heads_up_window_bg"
-                />
-    </FrameLayout>
-</com.android.systemui.statusbar.policy.HeadsUpNotificationView>
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_height="wrap_content"
+        android:layout_width="@dimen/notification_panel_width"
+        android:id="@+id/content_holder"
+        android:layout_marginStart="@dimen/notification_panel_margin_left"
+        android:background="@drawable/notification_panel_bg"
+        />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index eb66908..ea6be1b 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -62,7 +62,11 @@
                 android:src="@drawable/stat_notify_more"
                 android:visibility="gone"
                 />
-
+            <com.android.systemui.statusbar.StatusBarIconView android:id="@+id/modeIcon"
+                android:layout_width="@dimen/status_bar_icon_size"
+                android:layout_height="match_parent"
+                android:visibility="gone"
+                />
             <com.android.systemui.statusbar.phone.IconMerger android:id="@+id/notificationIcons"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 1693e01..56c1f4e 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -58,6 +58,12 @@
             android:layout_height="@dimen/notification_panel_header_height"
             />
 
+        <com.android.systemui.statusbar.phone.ZenModeView
+            android:id="@+id/zenmode"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            />
+
         <TextView
             android:id="@+id/emergency_calls_only"
             android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Network.EmergencyOnly"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 9aa7cfd..25c516b 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -15,7 +15,7 @@
 ** limitations under the License.
 -->
 
-<LinearLayout
+<com.android.systemui.statusbar.phone.PanelHeaderView
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
     android:id="@+id/header"
@@ -106,4 +106,4 @@
             android:contentDescription="@string/accessibility_notifications_button"
             />
     </FrameLayout>
-</LinearLayout>
+</com.android.systemui.statusbar.phone.PanelHeaderView>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 797f713..29ca84a9 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -69,7 +69,7 @@
     <string name="screenshot_failed_title" msgid="705781116746922771">"Nepavyko užfiksuoti ekrano kopijos."</string>
     <string name="screenshot_failed_text" msgid="8134011269572415402">"Nepavyko išsaugoti ekrano kopijos. Gali būti naudojama atmintis."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB failo perdavimo parinktys"</string>
-    <string name="use_mtp_button_title" msgid="4333504413563023626">"Įmontuoti kaip medijos grotuvą (MTP)"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Įmontuoti kaip medijos leistuvą (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Įmontuoti kaip fotoaparatą (PTP)"</string>
     <string name="installer_cd_button_title" msgid="2312667578562201583">"Įdiegti „Mac“ skirtą „Android“ perkėl. priem. pr."</string>
     <string name="accessibility_back" msgid="567011538994429120">"Atgal"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index b5c24d7..033e56d 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -72,7 +72,7 @@
     <string name="use_mtp_button_title" msgid="4333504413563023626">"ต่อเชื่อมเป็นโปรแกรมเล่นสื่อ (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"ต่อเชื่อมเป็นกล้องถ่ายรูป (PTP)"</string>
     <string name="installer_cd_button_title" msgid="2312667578562201583">"ติดตั้งแอปพลิเคชัน Android File Transfer ของ Mac"</string>
-    <string name="accessibility_back" msgid="567011538994429120">"ย้อนกลับ"</string>
+    <string name="accessibility_back" msgid="567011538994429120">"กลับ"</string>
     <string name="accessibility_home" msgid="8217216074895377641">"หน้าแรก"</string>
     <string name="accessibility_menu" msgid="316839303324695949">"เมนู"</string>
     <string name="accessibility_recent" msgid="8571350598987952883">"แอปพลิเคชันล่าสุด"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 83fdd12..bf2d7ce 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -199,7 +199,7 @@
     <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
     <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"未連線"</string>
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"沒有網路"</string>
-    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"關閉 Wi-Fi"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi:關閉"</string>
     <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"投放螢幕"</string>
     <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"亮度"</string>
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index e525fbb..a59dc75 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -39,4 +39,12 @@
     <color name="status_bar_clock_color">#FFFFFFFF</color>
     <drawable name="notification_item_background_color">#ff111111</drawable>
     <drawable name="notification_item_background_color_pressed">#ff454545</drawable>
+    <color name="notification_icon_legacy_bg_color">#ff4285F4</color>
+    <color name="notification_action_legacy_color_filter">#ff555555</color>
+
+    <!-- Tint color for inactive Quick Settings icons. -->
+    <color name="ic_qs_off">#ff404040</color>
+
+    <!-- Tint color for active Quick Settings icons. -->
+    <color name="ic_qs_on">#ffffffff</color>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index e6b2b8b..65cd231 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -79,6 +79,9 @@
     <!-- Height of a large notification in the status bar -->
     <dimen name="notification_max_height">256dp</dimen>
 
+    <!-- Height of a medium notification in the status bar -->
+    <dimen name="notification_mid_height">128dp</dimen>
+
     <!-- Height of a small notification in the status bar plus glow, padding, etc -->
     <dimen name="notification_row_min_height">70dp</dimen>
 
diff --git a/packages/SystemUI/src/com/android/systemui/ImageUtils.java b/packages/SystemUI/src/com/android/systemui/ImageUtils.java
new file mode 100644
index 0000000..540ba20
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ImageUtils.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui;
+
+import android.graphics.Bitmap;
+
+/**
+ * Utility class for image analysis and processing.
+ */
+public class ImageUtils {
+
+    // Amount (max is 255) that two channels can differ before the color is no longer "gray".
+    private static final int TOLERANCE = 20;
+
+    // Alpha amount for which values below are considered transparent.
+    private static final int ALPHA_TOLERANCE = 50;
+
+    private int[] mTempBuffer;
+
+    /**
+     * Checks whether a bitmap is grayscale. Grayscale here means "very close to a perfect
+     * gray".
+     */
+    public boolean isGrayscale(Bitmap bitmap) {
+        final int height = bitmap.getHeight();
+        final int width = bitmap.getWidth();
+        int size = height*width;
+
+        ensureBufferSize(size);
+        bitmap.getPixels(mTempBuffer, 0, width, 0, 0, width, height);
+        for (int i = 0; i < size; i++) {
+            if (!isGrayscale(mTempBuffer[i])) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Makes sure that {@code mTempBuffer} has at least length {@code size}.
+     */
+    private void ensureBufferSize(int size) {
+        if (mTempBuffer == null || mTempBuffer.length < size) {
+            mTempBuffer = new int[size];
+        }
+    }
+
+    /**
+     * Classifies a color as grayscale or not. Grayscale here means "very close to a perfect
+     * gray"; if all three channels are approximately equal, this will return true.
+     *
+     * Note that really transparent colors are always grayscale.
+     */
+    public boolean isGrayscale(int color) {
+        int alpha = 0xFF & (color >> 24);
+        if (alpha < ALPHA_TOLERANCE) {
+            return true;
+        }
+
+        int r = 0xFF & (color >> 16);
+        int g = 0xFF & (color >> 8);
+        int b = 0xFF & color;
+
+        return Math.abs(r - g) < TOLERANCE
+                && Math.abs(r - b) < TOLERANCE
+                && Math.abs(g - b) < TOLERANCE;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerDialogWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerDialogWarnings.java
new file mode 100644
index 0000000..feec87c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerDialogWarnings.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2014 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.power;
+
+import android.app.AlertDialog;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.media.AudioManager;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Slog;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+
+import java.io.PrintWriter;
+
+public class PowerDialogWarnings implements PowerUI.WarningsUI {
+    private static final String TAG = PowerUI.TAG + ".Dialog";
+    private static final boolean DEBUG = PowerUI.DEBUG;
+
+    private final Context mContext;
+
+    private int mBatteryLevel;
+    private int mBucket;
+    private long mScreenOffTime;
+
+    private AlertDialog mInvalidChargerDialog;
+    private AlertDialog mLowBatteryDialog;
+    private TextView mBatteryLevelTextView;
+
+    public PowerDialogWarnings(Context context) {
+        mContext = context;
+    }
+
+    @Override
+    public void dump(PrintWriter pw) {
+        pw.print("mInvalidChargerDialog=");
+        pw.println(mInvalidChargerDialog == null ? "null" : mInvalidChargerDialog.toString());
+        pw.print("mLowBatteryDialog=");
+        pw.println(mLowBatteryDialog == null ? "null" : mLowBatteryDialog.toString());
+    }
+
+    @Override
+    public void update(int batteryLevel, int bucket, long screenOffTime) {
+        mBatteryLevel = batteryLevel;
+        mBucket = bucket;
+        mScreenOffTime = screenOffTime;
+    }
+
+    @Override
+    public boolean isInvalidChargerWarningShowing() {
+        return mInvalidChargerDialog != null;
+    }
+
+    @Override
+    public void updateLowBatteryWarning() {
+        if (mBatteryLevelTextView != null) {
+            showLowBatteryWarning(false /*playSound*/);
+        }
+    }
+
+    @Override
+    public void dismissLowBatteryWarning() {
+        if (mLowBatteryDialog != null) {
+            Slog.i(TAG, "closing low battery warning: level=" + mBatteryLevel);
+            mLowBatteryDialog.dismiss();
+        }
+    }
+
+    @Override
+    public void showLowBatteryWarning(boolean playSound) {
+        Slog.i(TAG,
+                ((mBatteryLevelTextView == null) ? "showing" : "updating")
+                + " low battery warning: level=" + mBatteryLevel
+                + " [" + mBucket + "]");
+
+        CharSequence levelText = mContext.getString(
+                R.string.battery_low_percent_format, mBatteryLevel);
+
+        if (mBatteryLevelTextView != null) {
+            mBatteryLevelTextView.setText(levelText);
+        } else {
+            View v = View.inflate(mContext, R.layout.battery_low, null);
+            mBatteryLevelTextView = (TextView)v.findViewById(R.id.level_percent);
+
+            mBatteryLevelTextView.setText(levelText);
+
+            AlertDialog.Builder b = new AlertDialog.Builder(mContext);
+                b.setCancelable(true);
+                b.setTitle(R.string.battery_low_title);
+                b.setView(v);
+                b.setIconAttribute(android.R.attr.alertDialogIcon);
+                b.setPositiveButton(android.R.string.ok, null);
+
+            final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                    | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
+                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+                    | Intent.FLAG_ACTIVITY_NO_HISTORY);
+            if (intent.resolveActivity(mContext.getPackageManager()) != null) {
+                b.setNegativeButton(R.string.battery_low_why,
+                        new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+                        dismissLowBatteryWarning();
+                    }
+                });
+            }
+
+            AlertDialog d = b.create();
+            d.setOnDismissListener(new DialogInterface.OnDismissListener() {
+                    @Override
+                    public void onDismiss(DialogInterface dialog) {
+                        mLowBatteryDialog = null;
+                        mBatteryLevelTextView = null;
+                    }
+                });
+            d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+            d.getWindow().getAttributes().privateFlags |=
+                    WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+            d.show();
+            mLowBatteryDialog = d;
+            if (playSound) {
+                playLowBatterySound();
+            }
+        }
+    }
+
+    private void playLowBatterySound() {
+        final ContentResolver cr = mContext.getContentResolver();
+
+        final int silenceAfter = Settings.Global.getInt(cr,
+                Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0);
+        final long offTime = SystemClock.elapsedRealtime() - mScreenOffTime;
+        if (silenceAfter > 0
+                && mScreenOffTime > 0
+                && offTime > silenceAfter) {
+            Slog.i(TAG, "screen off too long (" + offTime + "ms, limit " + silenceAfter
+                    + "ms): not waking up the user with low battery sound");
+            return;
+        }
+
+        if (DEBUG) {
+            Slog.d(TAG, "playing low battery sound. pick-a-doop!"); // WOMP-WOMP is deprecated
+        }
+
+        if (Settings.Global.getInt(cr, Settings.Global.POWER_SOUNDS_ENABLED, 1) == 1) {
+            final String soundPath = Settings.Global.getString(cr,
+                    Settings.Global.LOW_BATTERY_SOUND);
+            if (soundPath != null) {
+                final Uri soundUri = Uri.parse("file://" + soundPath);
+                if (soundUri != null) {
+                    final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
+                    if (sfx != null) {
+                        sfx.setStreamType(AudioManager.STREAM_SYSTEM);
+                        sfx.play();
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public void dismissInvalidChargerWarning() {
+        if (mInvalidChargerDialog != null) {
+            mInvalidChargerDialog.dismiss();
+        }
+    }
+
+    @Override
+    public void showInvalidChargerWarning() {
+        Slog.d(TAG, "showing invalid charger dialog");
+
+        dismissLowBatteryWarning();
+
+        AlertDialog.Builder b = new AlertDialog.Builder(mContext);
+            b.setCancelable(true);
+            b.setMessage(R.string.invalid_charger);
+            b.setIconAttribute(android.R.attr.alertDialogIcon);
+            b.setPositiveButton(android.R.string.ok, null);
+
+        AlertDialog d = b.create();
+            d.setOnDismissListener(new DialogInterface.OnDismissListener() {
+                    public void onDismiss(DialogInterface dialog) {
+                        mInvalidChargerDialog = null;
+                        mBatteryLevelTextView = null;
+                    }
+                });
+
+        d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        d.show();
+        mInvalidChargerDialog = d;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 28c2772..0fb0f8b 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -16,29 +16,17 @@
 
 package com.android.systemui.power;
 
-import android.app.AlertDialog;
 import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
 import android.content.Context;
-import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.media.AudioManager;
-import android.media.Ringtone;
-import android.media.RingtoneManager;
-import android.net.Uri;
 import android.os.BatteryManager;
 import android.os.Handler;
 import android.os.PowerManager;
 import android.os.SystemClock;
-import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Slog;
-import android.view.View;
-import android.view.WindowManager;
-import android.widget.TextView;
 
-import com.android.systemui.R;
 import com.android.systemui.SystemUI;
 
 import java.io.FileDescriptor;
@@ -50,19 +38,17 @@
 
     static final boolean DEBUG = false;
 
-    Handler mHandler = new Handler();
+    private WarningsUI mWarnings;
 
-    int mBatteryLevel = 100;
-    int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
-    int mPlugType = 0;
-    int mInvalidCharger = 0;
+    private final Handler mHandler = new Handler();
 
-    int mLowBatteryAlertCloseLevel;
-    int[] mLowBatteryReminderLevels = new int[2];
+    private int mBatteryLevel = 100;
+    private int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
+    private int mPlugType = 0;
+    private int mInvalidCharger = 0;
 
-    AlertDialog mInvalidChargerDialog;
-    AlertDialog mLowBatteryDialog;
-    TextView mBatteryLevelTextView;
+    private int mLowBatteryAlertCloseLevel;
+    private final int[] mLowBatteryReminderLevels = new int[2];
 
     private long mScreenOffTime = -1;
 
@@ -77,6 +63,7 @@
 
         final PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mScreenOffTime = pm.isScreenOn() ? -1 : SystemClock.elapsedRealtime();
+        mWarnings = new PowerDialogWarnings(mContext);
 
         // Register for Intent broadcasts for...
         IntentFilter filter = new IntentFilter();
@@ -145,13 +132,14 @@
                     Slog.d(TAG, "plugged        " + oldPlugged + " --> " + plugged);
                 }
 
+                mWarnings.update(mBatteryLevel, bucket, mScreenOffTime);
                 if (oldInvalidCharger == 0 && mInvalidCharger != 0) {
                     Slog.d(TAG, "showing invalid charger warning");
-                    showInvalidChargerDialog();
+                    mWarnings.showInvalidChargerWarning();
                     return;
                 } else if (oldInvalidCharger != 0 && mInvalidCharger == 0) {
-                    dismissInvalidChargerDialog();
-                } else if (mInvalidChargerDialog != null) {
+                    mWarnings.dismissInvalidChargerWarning();
+                } else if (mWarnings.isInvalidChargerWarningShowing()) {
                     // if invalid charger is showing, don't show low battery
                     return;
                 }
@@ -160,16 +148,13 @@
                         && (bucket < oldBucket || oldPlugged)
                         && mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
                         && bucket < 0) {
-                    showLowBatteryWarning();
-
                     // only play SFX when the dialog comes up or the bucket changes
-                    if (bucket != oldBucket || oldPlugged) {
-                        playLowBatterySound();
-                    }
+                    final boolean playSound = bucket != oldBucket || oldPlugged;
+                    mWarnings.showLowBatteryWarning(playSound);
                 } else if (plugged || (bucket > oldBucket && bucket > 0)) {
-                    dismissLowBatteryWarning();
-                } else if (mBatteryLevelTextView != null) {
-                    showLowBatteryWarning();
+                    mWarnings.dismissLowBatteryWarning();
+                } else {
+                    mWarnings.updateLowBatteryWarning();
                 }
             } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
                 mScreenOffTime = SystemClock.elapsedRealtime();
@@ -181,142 +166,11 @@
         }
     };
 
-    void dismissLowBatteryWarning() {
-        if (mLowBatteryDialog != null) {
-            Slog.i(TAG, "closing low battery warning: level=" + mBatteryLevel);
-            mLowBatteryDialog.dismiss();
-        }
-    }
-
-    void showLowBatteryWarning() {
-        Slog.i(TAG,
-                ((mBatteryLevelTextView == null) ? "showing" : "updating")
-                + " low battery warning: level=" + mBatteryLevel
-                + " [" + findBatteryLevelBucket(mBatteryLevel) + "]");
-
-        CharSequence levelText = mContext.getString(
-                R.string.battery_low_percent_format, mBatteryLevel);
-
-        if (mBatteryLevelTextView != null) {
-            mBatteryLevelTextView.setText(levelText);
-        } else {
-            View v = View.inflate(mContext, R.layout.battery_low, null);
-            mBatteryLevelTextView = (TextView)v.findViewById(R.id.level_percent);
-
-            mBatteryLevelTextView.setText(levelText);
-
-            AlertDialog.Builder b = new AlertDialog.Builder(mContext);
-                b.setCancelable(true);
-                b.setTitle(R.string.battery_low_title);
-                b.setView(v);
-                b.setIconAttribute(android.R.attr.alertDialogIcon);
-                b.setPositiveButton(android.R.string.ok, null);
-
-            final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                    | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
-                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
-                    | Intent.FLAG_ACTIVITY_NO_HISTORY);
-            if (intent.resolveActivity(mContext.getPackageManager()) != null) {
-                b.setNegativeButton(R.string.battery_low_why,
-                        new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int which) {
-                        mContext.startActivityAsUser(intent, UserHandle.CURRENT);
-                        dismissLowBatteryWarning();
-                    }
-                });
-            }
-
-            AlertDialog d = b.create();
-            d.setOnDismissListener(new DialogInterface.OnDismissListener() {
-                    @Override
-                    public void onDismiss(DialogInterface dialog) {
-                        mLowBatteryDialog = null;
-                        mBatteryLevelTextView = null;
-                    }
-                });
-            d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
-            d.getWindow().getAttributes().privateFlags |=
-                    WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
-            d.show();
-            mLowBatteryDialog = d;
-        }
-    }
-
-    void playLowBatterySound() {
-        final ContentResolver cr = mContext.getContentResolver();
-
-        final int silenceAfter = Settings.Global.getInt(cr,
-                Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0);
-        final long offTime = SystemClock.elapsedRealtime() - mScreenOffTime;
-        if (silenceAfter > 0
-                && mScreenOffTime > 0
-                && offTime > silenceAfter) {
-            Slog.i(TAG, "screen off too long (" + offTime + "ms, limit " + silenceAfter
-                    + "ms): not waking up the user with low battery sound");
-            return;
-        }
-
-        if (DEBUG) {
-            Slog.d(TAG, "playing low battery sound. pick-a-doop!"); // WOMP-WOMP is deprecated
-        }
-
-        if (Settings.Global.getInt(cr, Settings.Global.POWER_SOUNDS_ENABLED, 1) == 1) {
-            final String soundPath = Settings.Global.getString(cr,
-                    Settings.Global.LOW_BATTERY_SOUND);
-            if (soundPath != null) {
-                final Uri soundUri = Uri.parse("file://" + soundPath);
-                if (soundUri != null) {
-                    final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
-                    if (sfx != null) {
-                        sfx.setStreamType(AudioManager.STREAM_SYSTEM);
-                        sfx.play();
-                    }
-                }
-            }
-        }
-    }
-
-    void dismissInvalidChargerDialog() {
-        if (mInvalidChargerDialog != null) {
-            mInvalidChargerDialog.dismiss();
-        }
-    }
-
-    void showInvalidChargerDialog() {
-        Slog.d(TAG, "showing invalid charger dialog");
-
-        dismissLowBatteryWarning();
-
-        AlertDialog.Builder b = new AlertDialog.Builder(mContext);
-            b.setCancelable(true);
-            b.setMessage(R.string.invalid_charger);
-            b.setIconAttribute(android.R.attr.alertDialogIcon);
-            b.setPositiveButton(android.R.string.ok, null);
-
-        AlertDialog d = b.create();
-            d.setOnDismissListener(new DialogInterface.OnDismissListener() {
-                    public void onDismiss(DialogInterface dialog) {
-                        mInvalidChargerDialog = null;
-                        mBatteryLevelTextView = null;
-                    }
-                });
-
-        d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
-        d.show();
-        mInvalidChargerDialog = d;
-    }
-
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.print("mLowBatteryAlertCloseLevel=");
         pw.println(mLowBatteryAlertCloseLevel);
         pw.print("mLowBatteryReminderLevels=");
         pw.println(Arrays.toString(mLowBatteryReminderLevels));
-        pw.print("mInvalidChargerDialog=");
-        pw.println(mInvalidChargerDialog == null ? "null" : mInvalidChargerDialog.toString());
-        pw.print("mLowBatteryDialog=");
-        pw.println(mLowBatteryDialog == null ? "null" : mLowBatteryDialog.toString());
         pw.print("mBatteryLevel=");
         pw.println(Integer.toString(mBatteryLevel));
         pw.print("mBatteryStatus=");
@@ -338,6 +192,18 @@
                 Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0));
         pw.print("bucket: ");
         pw.println(Integer.toString(findBatteryLevelBucket(mBatteryLevel)));
+        mWarnings.dump(pw);
+    }
+
+    public interface WarningsUI {
+        void update(int batteryLevel, int bucket, long screenOffTime);
+        void dismissLowBatteryWarning();
+        void showLowBatteryWarning(boolean playSound);
+        void dismissInvalidChargerWarning();
+        void showInvalidChargerWarning();
+        void updateLowBatteryWarning();
+        boolean isInvalidChargerWarningShowing();
+        void dump(PrintWriter pw);
     }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 7ff52de..eb07d88 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -28,9 +28,15 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.ColorStateList;
 import android.content.res.Configuration;
 import android.database.ContentObserver;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
 import android.graphics.Rect;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Handler;
@@ -44,9 +50,13 @@
 import android.service.dreams.DreamService;
 import android.service.dreams.IDreamManager;
 import android.service.notification.StatusBarNotification;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
 import android.text.TextUtils;
+import android.text.style.TextAppearanceSpan;
 import android.util.Log;
 import android.util.SparseBooleanArray;
+import android.view.ContextThemeWrapper;
 import android.view.Display;
 import android.view.IWindowManager;
 import android.view.LayoutInflater;
@@ -57,6 +67,7 @@
 import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
+import android.widget.Button;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.PopupMenu;
@@ -67,6 +78,7 @@
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.statusbar.StatusBarIconList;
 import com.android.internal.widget.SizeAdaptiveLayout;
+import com.android.systemui.ImageUtils;
 import com.android.systemui.R;
 import com.android.systemui.RecentsComponent;
 import com.android.systemui.SearchPanelView;
@@ -76,6 +88,7 @@
 
 import java.util.ArrayList;
 import java.util.Locale;
+import java.util.Stack;
 
 public abstract class BaseStatusBar extends SystemUI implements
         CommandQueue.Callbacks {
@@ -96,7 +109,7 @@
     protected static final boolean ENABLE_HEADS_UP = true;
     // scores above this threshold should be displayed in heads up mode.
     protected static final int INTERRUPTION_THRESHOLD = 11;
-    protected static final String SETTING_HEADS_UP = "heads_up_enabled";
+    protected static final String SETTING_HEADS_UP_TICKER = "ticker_gets_heads_up";
 
     // Should match the value in PhoneWindowManager
     public static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
@@ -104,6 +117,9 @@
     public static final int EXPANDED_LEAVE_ALONE = -10000;
     public static final int EXPANDED_FULL_OPEN = -10001;
 
+    private static final String EXTRA_INTERCEPT = "android.intercept";
+    private static final float INTERCEPTED_ALPHA = .2f;
+
     protected CommandQueue mCommandQueue;
     protected IStatusBarService mBarService;
     protected H mHandler = createHandler();
@@ -128,6 +144,7 @@
     protected int mLayoutDirection = -1; // invalid
     private Locale mLocale;
     protected boolean mUseHeadsUp = false;
+    protected boolean mHeadsUpTicker = false;
 
     protected IDreamManager mDreamManager;
     PowerManager mPowerManager;
@@ -136,6 +153,8 @@
     // public mode, private notifications, etc
     private boolean mLockscreenPublicMode = false;
     private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
+    private Context mLightThemeContext;
+    private ImageUtils mImageUtils = new ImageUtils();
 
     // UI-specific methods
 
@@ -155,6 +174,8 @@
 
     private RecentsComponent mRecents;
 
+    protected int mZenMode;
+
     public IStatusBarService getStatusBarService() {
         return mBarService;
     }
@@ -163,7 +184,7 @@
         return mDeviceProvisioned;
     }
 
-    private final ContentObserver mProvisioningObserver = new ContentObserver(mHandler) {
+    protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
         @Override
         public void onChange(boolean selfChange) {
             final boolean provisioned = 0 != Settings.Global.getInt(
@@ -172,6 +193,9 @@
                 mDeviceProvisioned = provisioned;
                 updateNotificationIcons();
             }
+            final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
+            setZenMode(mode);
         }
     };
 
@@ -239,16 +263,21 @@
                 ServiceManager.checkService(DreamService.DREAM_SERVICE));
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
 
-        mProvisioningObserver.onChange(false); // set up
+        mSettingsObserver.onChange(false); // set up
         mContext.getContentResolver().registerContentObserver(
                 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), true,
-                mProvisioningObserver);
+                mSettingsObserver);
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.ZEN_MODE), false,
+                mSettingsObserver);
 
         mContext.getContentResolver().registerContentObserver(
                 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS),
                 true,
                 mLockscreenSettingsObserver,
                 UserHandle.USER_ALL);
+        mLightThemeContext = new RemoteViewsThemeContextWrapper(mContext,
+                android.R.style.Theme_Holo_Light);
 
         mBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
@@ -400,6 +429,158 @@
         }
     }
 
+    private void processLegacyHoloNotification(StatusBarNotification sbn, View content) {
+
+        // TODO: Also skip processing if it is a holo-style notification.
+        // If the notification is custom, we can't process it.
+        if (!sbn.getNotification().extras.getBoolean(Notification.EXTRA_BUILDER_REMOTE_VIEWS)) {
+            return;
+        }
+
+        processLegacyHoloLargeIcon(content);
+        processLegacyHoloActions(content);
+        processLegacyNotificationIcon(content);
+        processLegacyTextViews(content);
+    }
+
+    /**
+     * @return the context to be used for the inflation of the specified {@code sbn}; this is
+     *      dependent whether the notification is quantum-style or holo-style
+     */
+    private Context getInflationContext(StatusBarNotification sbn) {
+
+        // TODO: Adjust this logic when we change the theme of the status bar windows.
+        if (sbn.getNotification().extras.getBoolean(Notification.EXTRA_BUILDER_REMOTE_VIEWS)) {
+            return mLightThemeContext;
+        } else {
+            return mContext;
+        }
+    }
+
+    private void processLegacyNotificationIcon(View content) {
+        View v = content.findViewById(com.android.internal.R.id.right_icon);
+        if (v != null & v instanceof ImageView) {
+            ImageView iv = (ImageView) v;
+            Drawable d = iv.getDrawable();
+            if (isMonochrome(d)) {
+                d.mutate();
+                d.setColorFilter(mLightThemeContext.getResources().getColor(
+                        R.color.notification_action_legacy_color_filter), PorterDuff.Mode.MULTIPLY);
+            }
+        }
+    }
+
+    private void processLegacyHoloLargeIcon(View content) {
+        View v = content.findViewById(com.android.internal.R.id.icon);
+        if (v != null & v instanceof ImageView) {
+            ImageView iv = (ImageView) v;
+            if (isMonochrome(iv.getDrawable())) {
+                iv.setBackground(mLightThemeContext.getResources().getDrawable(
+                        R.drawable.notification_icon_legacy_bg_inset));
+            }
+        }
+    }
+
+    private boolean isMonochrome(Drawable d) {
+        if (d == null) {
+            return false;
+        } else if (d instanceof BitmapDrawable) {
+            BitmapDrawable bd = (BitmapDrawable) d;
+            return bd.getBitmap() != null && mImageUtils.isGrayscale(bd.getBitmap());
+        } else if (d instanceof AnimationDrawable) {
+            AnimationDrawable ad = (AnimationDrawable) d;
+            int count = ad.getNumberOfFrames();
+            return count > 0 && isMonochrome(ad.getFrame(0));
+        } else {
+            return false;
+        }
+    }
+
+    private void processLegacyHoloActions(View content) {
+        View v = content.findViewById(com.android.internal.R.id.actions);
+        if (v != null & v instanceof ViewGroup) {
+            ViewGroup vg = (ViewGroup) v;
+            int childCount = vg.getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                View child = vg.getChildAt(i);
+                if (child instanceof Button) {
+                    Button button = (Button) child;
+                    Drawable[] compoundDrawables = button.getCompoundDrawablesRelative();
+                    if (isMonochrome(compoundDrawables[0])) {
+                        Drawable d = compoundDrawables[0];
+                        d.mutate();
+                        d.setColorFilter(mLightThemeContext.getResources().getColor(
+                                R.color.notification_action_legacy_color_filter),
+                                PorterDuff.Mode.MULTIPLY);
+                    }
+                }
+            }
+        }
+    }
+
+    private void processLegacyTextViews(View content) {
+        Stack<View> viewStack = new Stack<View>();
+        viewStack.push(content);
+        while(!viewStack.isEmpty()) {
+            View current = viewStack.pop();
+            if(current instanceof ViewGroup){
+                ViewGroup currentGroup = (ViewGroup) current;
+                int numChildren = currentGroup.getChildCount();
+                for(int i=0;i<numChildren;i++){
+                    viewStack.push(currentGroup.getChildAt(i));
+                }
+            }
+            if (current instanceof TextView) {
+                processLegacyTextView((TextView) current);
+            }
+        }
+    }
+
+    private void processLegacyTextView(TextView textView) {
+        if (textView.getText() instanceof Spanned) {
+            Spanned ss = (Spanned) textView.getText();
+            Object[] spans = ss.getSpans(0, ss.length(), Object.class);
+            SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString());
+            for (Object span : spans) {
+                Object resultSpan = span;
+                if (span instanceof TextAppearanceSpan) {
+                    resultSpan = processTextAppearanceSpan((TextAppearanceSpan) span);
+                }
+                builder.setSpan(resultSpan, ss.getSpanStart(span), ss.getSpanEnd(span),
+                        ss.getSpanFlags(span));
+            }
+            textView.setText(builder);
+        }
+    }
+
+    private TextAppearanceSpan processTextAppearanceSpan(TextAppearanceSpan span) {
+        ColorStateList colorStateList = span.getTextColor();
+        if (colorStateList != null) {
+            int[] colors = colorStateList.getColors();
+            boolean changed = false;
+            for (int i = 0; i < colors.length; i++) {
+                if (mImageUtils.isGrayscale(colors[i])) {
+                    colors[i] = processColor(colors[i]);
+                    changed = true;
+                }
+            }
+            if (changed) {
+                return new TextAppearanceSpan(
+                        span.getFamily(), span.getTextStyle(), span.getTextSize(),
+                        new ColorStateList(colorStateList.getStates(), colors),
+                        span.getLinkTextColor());
+            }
+        }
+        return span;
+    }
+
+    private int processColor(int color) {
+        return Color.argb(Color.alpha(color),
+                255 - Color.red(color),
+                255 - Color.green(color),
+                255 - Color.blue(color));
+    }
+
     private void startApplicationDetailsActivity(String packageName) {
         Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                 Uri.fromParts("package", packageName, null));
@@ -683,6 +864,13 @@
         StatusBarNotification sbn = entry.notification;
         RemoteViews contentView = sbn.getNotification().contentView;
         RemoteViews bigContentView = sbn.getNotification().bigContentView;
+
+        if (isHeadsUp) {
+            maxHeight =
+                    mContext.getResources().getDimensionPixelSize(R.dimen.notification_mid_height);
+            bigContentView = sbn.getNotification().headsUpContentView;
+        }
+
         if (contentView == null) {
             return false;
         }
@@ -729,9 +917,11 @@
         View contentViewLocal = null;
         View bigContentViewLocal = null;
         try {
-            contentViewLocal = contentView.apply(mContext, expanded, mOnClickHandler);
+            contentViewLocal = contentView.apply(getInflationContext(sbn), expanded,
+                    mOnClickHandler);
             if (bigContentView != null) {
-                bigContentViewLocal = bigContentView.apply(mContext, expanded, mOnClickHandler);
+                bigContentViewLocal = bigContentView.apply(getInflationContext(sbn), expanded,
+                        mOnClickHandler);
             }
         }
         catch (RuntimeException e) {
@@ -761,7 +951,7 @@
         View publicViewLocal = null;
         if (publicNotification != null) {
             try {
-                publicViewLocal = publicNotification.contentView.apply(mContext,
+                publicViewLocal = publicNotification.contentView.apply(getInflationContext(sbn),
                         expandedPublic, mOnClickHandler);
 
                 if (publicViewLocal != null) {
@@ -812,6 +1002,13 @@
         row.setDrawingCacheEnabled(true);
 
         applyLegacyRowBackground(sbn, content);
+        processLegacyHoloNotification(sbn, contentViewLocal);
+        if (bigContentViewLocal != null) {
+            processLegacyHoloNotification(sbn, bigContentViewLocal);
+        }
+        if (publicViewLocal != null) {
+            processLegacyHoloNotification(sbn, publicViewLocal);
+        }
 
         if (MULTIUSER_DEBUG) {
             TextView debug = (TextView) row.findViewById(R.id.debug_info);
@@ -980,6 +1177,7 @@
         if (DEBUG) {
             Log.d(TAG, "addNotificationViews: added at " + pos);
         }
+        updateInterceptedState(entry);
         updateExpansionStates();
         updateNotificationIcons();
     }
@@ -1010,6 +1208,35 @@
         }
     }
 
+    protected void setZenMode(int mode) {
+        if (!isDeviceProvisioned()) return;
+        final boolean change = mZenMode != mode;
+        mZenMode = mode;
+        final int N = mNotificationData.size();
+        for (int i = 0; i < N; i++) {
+            final NotificationData.Entry entry = mNotificationData.get(i);
+            if (change && !shouldIntercept()) {
+                entry.notification.getNotification().extras.putBoolean(EXTRA_INTERCEPT, false);
+            }
+            updateInterceptedState(entry);
+        }
+        updateNotificationIcons();
+    }
+
+    private boolean shouldIntercept() {
+        return mZenMode == Settings.Global.ZEN_MODE_LIMITED
+                || mZenMode == Settings.Global.ZEN_MODE_FULL;
+    }
+
+    protected boolean shouldIntercept(Notification n) {
+        return shouldIntercept() && n.extras.getBoolean(EXTRA_INTERCEPT);
+    }
+
+    private void updateInterceptedState(NotificationData.Entry entry) {
+        final boolean intercepted = shouldIntercept(entry.notification.getNotification());
+        entry.row.findViewById(R.id.container).setAlpha(intercepted ? INTERCEPTED_ALPHA : 1);
+    }
+
     protected abstract void haltTicker();
     protected abstract void setAreThereNotifications();
     protected abstract void updateNotificationIcons();
@@ -1038,6 +1265,8 @@
         final RemoteViews contentView = notification.getNotification().contentView;
         final RemoteViews oldBigContentView = oldNotification.getNotification().bigContentView;
         final RemoteViews bigContentView = notification.getNotification().bigContentView;
+        final RemoteViews oldHeadsUpContentView = oldNotification.getNotification().headsUpContentView;
+        final RemoteViews headsUpContentView = notification.getNotification().headsUpContentView;
         final Notification oldPublicNotification = oldNotification.getNotification().publicVersion;
         final RemoteViews oldPublicContentView = oldPublicNotification != null
                 ? oldPublicNotification.contentView : null;
@@ -1077,6 +1306,13 @@
                     && oldBigContentView.getPackage() != null
                     && oldBigContentView.getPackage().equals(bigContentView.getPackage())
                     && oldBigContentView.getLayoutId() == bigContentView.getLayoutId());
+        boolean headsUpContentsUnchanged =
+                (oldHeadsUpContentView == null && headsUpContentView == null)
+                || ((oldHeadsUpContentView != null && headsUpContentView != null)
+                    && headsUpContentView.getPackage() != null
+                    && oldHeadsUpContentView.getPackage() != null
+                    && oldHeadsUpContentView.getPackage().equals(headsUpContentView.getPackage())
+                    && oldHeadsUpContentView.getLayoutId() == headsUpContentView.getLayoutId());
         boolean publicUnchanged  =
                 (oldPublicContentView == null && publicContentView == null)
                 || ((oldPublicContentView != null && publicContentView != null)
@@ -1095,7 +1331,7 @@
                 && !TextUtils.equals(notification.getNotification().tickerText,
                         oldEntry.notification.getNotification().tickerText);
         boolean isTopAnyway = isTopNotification(rowParent, oldEntry);
-        if (contentsUnchanged && bigContentsUnchanged && publicUnchanged
+        if (contentsUnchanged && bigContentsUnchanged && headsUpContentsUnchanged && publicUnchanged
                 && (orderUnchanged || isTopAnyway)) {
             if (DEBUG) Log.d(TAG, "reusing notification for key: " + key);
             oldEntry.notification = notification;
@@ -1179,18 +1415,25 @@
     private void updateNotificationViews(NotificationData.Entry entry,
             StatusBarNotification notification, boolean isHeadsUp) {
         final RemoteViews contentView = notification.getNotification().contentView;
-        final RemoteViews bigContentView = notification.getNotification().bigContentView;
+        final RemoteViews bigContentView = isHeadsUp
+                ? notification.getNotification().headsUpContentView
+                : notification.getNotification().bigContentView;
         final Notification publicVersion = notification.getNotification().publicVersion;
         final RemoteViews publicContentView = publicVersion != null ? publicVersion.contentView
                 : null;
 
         // Reapply the RemoteViews
-        contentView.reapply(mContext, entry.expanded, mOnClickHandler);
+        contentView.reapply(getInflationContext(notification), entry.expanded, mOnClickHandler);
+        processLegacyHoloNotification(notification, entry.expanded);
         if (bigContentView != null && entry.getBigContentView() != null) {
-            bigContentView.reapply(mContext, entry.getBigContentView(), mOnClickHandler);
+            bigContentView.reapply(getInflationContext(notification), entry.getBigContentView(),
+                    mOnClickHandler);
+            processLegacyHoloNotification(notification, entry.getBigContentView());
         }
         if (publicContentView != null && entry.getPublicContentView() != null) {
-            publicContentView.reapply(mContext, entry.getPublicContentView(), mOnClickHandler);
+            publicContentView.reapply(getInflationContext(notification),
+                    entry.getPublicContentView(), mOnClickHandler);
+            processLegacyHoloNotification(notification, entry.getPublicContentView());
         }
         // update the contentIntent
         final PendingIntent contentIntent = notification.getNotification().contentIntent;
@@ -1202,6 +1445,7 @@
         } else {
             entry.content.setOnClickListener(null);
         }
+        updateInterceptedState(entry);
     }
 
     protected void notifyHeadsUpScreenOn(boolean screenOn) {
@@ -1219,11 +1463,12 @@
                 || notification.vibrate != null;
         boolean isHighPriority = sbn.getScore() >= INTERRUPTION_THRESHOLD;
         boolean isFullscreen = notification.fullScreenIntent != null;
+        boolean hasTicker = mHeadsUpTicker && !TextUtils.isEmpty(notification.tickerText);
         boolean isAllowed = notification.extras.getInt(Notification.EXTRA_AS_HEADS_UP,
                 Notification.HEADS_UP_ALLOWED) != Notification.HEADS_UP_NEVER;
 
         final KeyguardTouchDelegate keyguard = KeyguardTouchDelegate.getInstance(mContext);
-        boolean interrupt = (isFullscreen || (isHighPriority && isNoisy))
+        boolean interrupt = (isFullscreen || (isHighPriority && (isNoisy || hasTicker)))
                 && isAllowed
                 && mPowerManager.isScreenOn()
                 && !keyguard.isShowingAndNotHidden()
@@ -1268,4 +1513,35 @@
         }
         mContext.unregisterReceiver(mBroadcastReceiver);
     }
+
+    /**
+     * A custom context theme wrapper that applies a platform theme to a created package context.
+     * This is useful if you want to inflate {@link RemoteViews} with a custom theme (normally, the
+     * theme used there is the default platform theme).
+     */
+    private static class RemoteViewsThemeContextWrapper extends ContextThemeWrapper {
+
+        private int mThemeRes;
+
+        private RemoteViewsThemeContextWrapper(Context base, int themeres) {
+            super(base, themeres);
+            mThemeRes = themeres;
+        }
+
+        @Override
+        public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
+                throws NameNotFoundException {
+            Context c = super.createPackageContextAsUser(packageName, flags, user);
+            c.setTheme(mThemeRes);
+            return c;
+        }
+
+        @Override
+        public Context createPackageContext(String packageName, int flags)
+                throws NameNotFoundException {
+            Context c = super.createPackageContext(packageName, flags);
+            c.setTheme(mThemeRes);
+            return c;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 4427466..b9a59dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -71,9 +71,9 @@
             final StatusBarNotification na = a.notification;
             final StatusBarNotification nb = b.notification;
             int d = na.getScore() - nb.getScore();
-	    if (a.interruption != b.interruption) {
-	      return a.interruption ? 1 : -1;
-	    } else if (d != 0) {
+            if (a.interruption != b.interruption) {
+                return a.interruption ? 1 : -1;
+            } else if (d != 0) {
                 return d;
             } else {
                 return (int) (na.getNotification().when - nb.getNotification().when);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 6be6d4d..237b7f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -20,6 +20,7 @@
 import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
+import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.EventLog;
 import android.view.MotionEvent;
@@ -56,6 +57,17 @@
         mHandleBar = resources.getDrawable(R.drawable.status_bar_close);
         mHandleBarHeight = resources.getDimensionPixelSize(R.dimen.close_handle_height);
         mHandleView = findViewById(R.id.handle);
+        PanelHeaderView header = (PanelHeaderView) findViewById(R.id.header);
+        ZenModeView zenModeView = (ZenModeView) findViewById(R.id.zenmode);
+        zenModeView.setAdapter(new ZenModeViewAdapter(mContext) {
+            @Override
+            public void configure() {
+                if (mStatusBar != null) {
+                    mStatusBar.startSettingsActivity(Settings.ACTION_ZEN_MODE_SETTINGS);
+                }
+            }
+        });
+        header.setZenModeView(zenModeView);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelHeaderView.java
new file mode 100644
index 0000000..a28324d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelHeaderView.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.widget.LinearLayout;
+
+public class PanelHeaderView extends LinearLayout {
+    private static final String TAG = "PanelHeaderView";
+    private static final boolean DEBUG = false;
+
+    private ZenModeView mZenModeView;
+
+    public PanelHeaderView(Context context) {
+        super(context);
+    }
+
+    public PanelHeaderView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public void setZenModeView(ZenModeView zmv) {
+        mZenModeView = zmv;
+    }
+
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent ev) {
+        final boolean rt = super.dispatchTouchEvent(ev);
+        if (DEBUG) logTouchEvent("dispatchTouchEvent", rt, ev);
+        if (mZenModeView != null) {
+            mZenModeView.dispatchExternalTouchEvent(ev);
+        }
+        return rt;
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        final boolean rt = super.onInterceptTouchEvent(ev);
+        if (DEBUG) logTouchEvent("onInterceptTouchEvent", rt, ev);
+        return rt;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        boolean rt = super.onTouchEvent(event);
+        if (DEBUG) logTouchEvent("onTouchEvent", rt, event);
+        return true;
+    }
+
+    private void logTouchEvent(String method, boolean rt, MotionEvent ev) {
+        Log.d(TAG, method + " " + (rt ? "TRUE" : "FALSE") + " " + ev);
+    }
+}
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 2114991..6718de1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -189,6 +189,8 @@
     IconMerger mNotificationIcons;
     // [+>
     View mMoreIcon;
+    // mode indicator icon
+    ImageView mModeIcon;
 
     // expanded notifications
     NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
@@ -310,13 +312,17 @@
         @Override
         public void onChange(boolean selfChange) {
             boolean wasUsing = mUseHeadsUp;
-            mUseHeadsUp = ENABLE_HEADS_UP && 0 != Settings.Global.getInt(
-                    mContext.getContentResolver(), SETTING_HEADS_UP, 0);
+            mUseHeadsUp = ENABLE_HEADS_UP && Settings.Global.HEADS_UP_OFF != Settings.Global.getInt(
+                    mContext.getContentResolver(), Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED,
+                    Settings.Global.HEADS_UP_OFF);
+            mHeadsUpTicker = mUseHeadsUp && 0 != Settings.Global.getInt(
+                    mContext.getContentResolver(), SETTING_HEADS_UP_TICKER, 0);
             Log.d(TAG, "heads up is " + (mUseHeadsUp ? "enabled" : "disabled"));
             if (wasUsing != mUseHeadsUp) {
                 if (!mUseHeadsUp) {
                     Log.d(TAG, "dismissing any existing heads up notification on disable event");
-                    mHandler.sendEmptyMessage(MSG_HIDE_HEADS_UP);
+                    setHeadsUpVisibility(false);
+                    mHeadsUpNotificationView.setNotification(null);
                     removeHeadsUpView();
                 } else {
                     addHeadsUpView();
@@ -341,6 +347,20 @@
         }};
 
     @Override
+    public void setZenMode(int mode) {
+        super.setZenMode(mode);
+        if (mModeIcon == null) return;
+        if (!isDeviceProvisioned()) return;
+        final boolean limited = mode == Settings.Global.ZEN_MODE_LIMITED;
+        final boolean full = mode == Settings.Global.ZEN_MODE_FULL;
+        mModeIcon.setVisibility(full || limited ? View.VISIBLE : View.GONE);
+        final int icon = limited ? R.drawable.stat_sys_zen_limited : R.drawable.stat_sys_zen_full;
+        if (full || limited) {
+            mModeIcon.setImageResource(icon);
+        }
+    }
+
+    @Override
     public void start() {
         mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
                 .getDefaultDisplay();
@@ -352,11 +372,15 @@
 
         // Lastly, call to the icon policy to install/update all the icons.
         mIconPolicy = new PhoneStatusBarPolicy(mContext);
+        mSettingsObserver.onChange(false); // set up
 
         mHeadsUpObserver.onChange(true); // set up
         if (ENABLE_HEADS_UP) {
             mContext.getContentResolver().registerContentObserver(
-                    Settings.Global.getUriFor(SETTING_HEADS_UP), true,
+                    Settings.Global.getUriFor(Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED), true,
+                    mHeadsUpObserver);
+            mContext.getContentResolver().registerContentObserver(
+                    Settings.Global.getUriFor(SETTING_HEADS_UP_TICKER), true,
                     mHeadsUpObserver);
         }
     }
@@ -455,6 +479,7 @@
         mNotificationIcons = (IconMerger)mStatusBarView.findViewById(R.id.notificationIcons);
         mMoreIcon = mStatusBarView.findViewById(R.id.moreIcon);
         mNotificationIcons.setOverflowIndicator(mMoreIcon);
+        mModeIcon = (ImageView)mStatusBarView.findViewById(R.id.modeIcon);
         mStatusBarContents = (LinearLayout)mStatusBarView.findViewById(R.id.status_bar_contents);
         mTickerView = mStatusBarView.findViewById(R.id.ticker);
 
@@ -855,7 +880,6 @@
                 PixelFormat.TRANSLUCENT);
         lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
         lp.gravity = Gravity.TOP;
-        lp.y = getStatusBarHeight();
         lp.setTitle("Heads Up");
         lp.packageName = mContext.getPackageName();
         lp.windowAnimations = R.style.Animation_StatusBar_HeadsUp;
@@ -909,41 +933,43 @@
         if (shadeEntry == null) {
             return;
         }
-        if (mUseHeadsUp && shouldInterrupt(notification)) {
-            if (DEBUG) Log.d(TAG, "launching notification in heads up mode");
-            Entry interruptionCandidate = new Entry(key, notification, null);
-            ViewGroup holder = mHeadsUpNotificationView.getHolder();
-            if (inflateViewsForHeadsUp(interruptionCandidate, holder)) {
-                mInterruptingNotificationTime = System.currentTimeMillis();
-                mInterruptingNotificationEntry = interruptionCandidate;
-                shadeEntry.setInterruption();
+        if (!shouldIntercept(notification.getNotification())) {
+            if (mUseHeadsUp && shouldInterrupt(notification)) {
+                if (DEBUG) Log.d(TAG, "launching notification in heads up mode");
+                Entry interruptionCandidate = new Entry(key, notification, null);
+                ViewGroup holder = mHeadsUpNotificationView.getHolder();
+                if (inflateViewsForHeadsUp(interruptionCandidate, holder)) {
+                    mInterruptingNotificationTime = System.currentTimeMillis();
+                    mInterruptingNotificationEntry = interruptionCandidate;
+                    shadeEntry.setInterruption();
 
-                // 1. Populate mHeadsUpNotificationView
-                mHeadsUpNotificationView.setNotification(mInterruptingNotificationEntry);
+                    // 1. Populate mHeadsUpNotificationView
+                    mHeadsUpNotificationView.setNotification(mInterruptingNotificationEntry);
 
-                // 2. Animate mHeadsUpNotificationView in
-                mHandler.sendEmptyMessage(MSG_SHOW_HEADS_UP);
+                    // 2. Animate mHeadsUpNotificationView in
+                    mHandler.sendEmptyMessage(MSG_SHOW_HEADS_UP);
 
-                // 3. Set alarm to age the notification off
-                resetHeadsUpDecayTimer();
-            }
-        } else if (notification.getNotification().fullScreenIntent != null) {
-            // Stop screensaver if the notification has a full-screen intent.
-            // (like an incoming phone call)
-            awakenDreams();
+                    // 3. Set alarm to age the notification off
+                    resetHeadsUpDecayTimer();
+                }
+            } else if (notification.getNotification().fullScreenIntent != null) {
+                // Stop screensaver if the notification has a full-screen intent.
+                // (like an incoming phone call)
+                awakenDreams();
 
-            // not immersive & a full-screen alert should be shown
-            if (DEBUG) Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
-            try {
-                notification.getNotification().fullScreenIntent.send();
-            } catch (PendingIntent.CanceledException e) {
-            }
-        } else {
-            // usual case: status bar visible & not immersive
+                // not immersive & a full-screen alert should be shown
+                if (DEBUG) Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
+                try {
+                    notification.getNotification().fullScreenIntent.send();
+                } catch (PendingIntent.CanceledException e) {
+                }
+            } else {
+                // usual case: status bar visible & not immersive
 
-            // show the ticker if there isn't already a heads up
-            if (mInterruptingNotificationEntry == null) {
-                tick(null, notification, true);
+                // show the ticker if there isn't already a heads up
+                if (mInterruptingNotificationEntry == null) {
+                    tick(null, notification, true);
+                }
             }
         }
         addNotificationViews(shadeEntry);
@@ -1096,6 +1122,9 @@
                 // in "public" mode (atop a secure keyguard), secret notifs are totally hidden
                 continue;
             }
+            if (shouldIntercept(ent.notification.getNotification())) {
+                continue;
+            }
             toShow.add(ent.icon);
         }
 
@@ -2183,6 +2212,9 @@
         pw.println(windowStateToString(mStatusBarWindowState));
         pw.print("  mStatusBarMode=");
         pw.println(BarTransitions.modeToString(mStatusBarMode));
+        pw.print("  mZenMode=");
+        pw.println(Settings.Global.zenModeToString(mZenMode));
+        pw.print("  mUseHeadsUp=" + mUseHeadsUp);
         dumpBarTransitions(pw, "mStatusBarView", mStatusBarView.getBarTransitions());
         if (mNavigationBarView != null) {
             pw.print("  mNavigationBarWindowState=");
@@ -2710,6 +2742,12 @@
                 || (mDisabled & StatusBarManager.DISABLE_SEARCH) != 0;
     }
 
+    public void startSettingsActivity(String action) {
+        if (mQS != null) {
+            mQS.startSettingsActivity(action);
+        }
+    }
+
     private static class FastColorDrawable extends Drawable {
         private final int mColor;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index 4d7ff5e..c1c8946 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -278,7 +278,7 @@
         mTilesSetUp = true;
     }
 
-    private void startSettingsActivity(String action) {
+    public void startSettingsActivity(String action) {
         Intent intent = new Intent(action);
         startSettingsActivity(intent);
     }
@@ -312,7 +312,7 @@
             public void onClick(View v) {
                 collapsePanels();
                 final UserManager um = UserManager.get(mContext);
-                if (um.getUsers(true).size() > 1) {
+                if (um.isUserSwitcherEnabled()) {
                     // Since keyguard and systemui were merged into the same process to save
                     // memory, they share the same Looper and graphics context.  As a result,
                     // there's no way to allow concurrent animation while keyguard inflates.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
index 48ee1ce..174cad8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
@@ -996,8 +996,8 @@
         mInversionState.toggled = enabled;
         mInversionState.type = type;
         // TODO: Add real icon assets.
-        mInversionState.iconId = enabled ? R.drawable.ic_qs_bluetooth_on
-                : R.drawable.ic_qs_bluetooth_off;
+        mInversionState.iconId = enabled ? R.drawable.ic_qs_inversion_on
+                : R.drawable.ic_qs_inversion_off;
         mInversionState.label = res.getString(R.string.quick_settings_inversion_label);
         mInversionCallback.refreshView(mInversionTile, mInversionState);
     }
@@ -1026,8 +1026,8 @@
         mContrastState.contrast = contrast;
         mContrastState.brightness = brightness;
         // TODO: Add real icon assets.
-        mContrastState.iconId = enabled ? R.drawable.ic_qs_bluetooth_on
-                : R.drawable.ic_qs_bluetooth_off;
+        mContrastState.iconId = enabled ? R.drawable.ic_qs_contrast_on
+                : R.drawable.ic_qs_contrast_off;
         mContrastState.label = res.getString(R.string.quick_settings_contrast_label);
         mContrastCallback.refreshView(mContrastTile, mContrastState);
     }
@@ -1053,8 +1053,8 @@
         mColorSpaceState.toggled = enabled;
         mColorSpaceState.type = type;
         // TODO: Add real icon assets.
-        mColorSpaceState.iconId = enabled ? R.drawable.ic_qs_bluetooth_on
-                : R.drawable.ic_qs_bluetooth_off;
+        mColorSpaceState.iconId = enabled ? R.drawable.ic_qs_color_space_on
+                : R.drawable.ic_qs_color_space_off;
         mColorSpaceState.label = res.getString(R.string.quick_settings_color_space_label);
         mColorSpaceCallback.refreshView(mColorSpaceTile, mColorSpaceState);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
new file mode 100644
index 0000000..fa7f96a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
@@ -0,0 +1,756 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.shapes.PathShape;
+import android.os.AsyncTask;
+import android.os.Vibrator;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
+import android.text.TextPaint;
+import android.text.method.LinkMovementMethod;
+import android.text.style.RelativeSizeSpan;
+import android.text.style.URLSpan;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.RelativeLayout;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.ZenModeView.Adapter.ExitCondition;
+
+public class ZenModeView extends RelativeLayout {
+    private static final String TAG = ZenModeView.class.getSimpleName();
+    private static final boolean DEBUG = false;
+
+    private static final Typeface CONDENSED =
+            Typeface.create("sans-serif-condensed", Typeface.NORMAL);
+    private static final int GRAY = 0xff999999; //TextAppearance.StatusBar.Expanded.Network
+    private static final int BACKGROUND = 0xff1d3741; //0x3333b5e5;
+    private static final long DURATION = new ValueAnimator().getDuration();
+    private static final long BOUNCE_DURATION = DURATION / 3;
+    private static final float BOUNCE_SCALE = 0.8f;
+    private static final float SETTINGS_ALPHA = 0.6f;
+
+    private static final String FULL_TEXT =
+            "You won't hear any calls, alarms or timers.";
+
+    private final Context mContext;
+    private final Paint mPathPaint;
+    private final TextView mHintText;
+    private final ModeSpinner mModeSpinner;
+    private final ImageView mCloseButton;
+    private final ImageView mSettingsButton;
+    private final Rect mLayoutRect = new Rect();
+    private final UntilPager mUntilPager;
+    private final AlarmWarning mAlarmWarning;
+    private final int mPopDuration;
+
+    private float mDownY;
+    private int mDownBottom;
+    private boolean mPeekable = true;
+    private boolean mClosing;
+    private int mBottom;
+    private int mWidthSpec;
+    private Adapter mAdapter;
+    private boolean mPopped;
+
+    public ZenModeView(Context context) {
+        this(context, null);
+    }
+
+    public ZenModeView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        if (DEBUG) log("new %s()", getClass().getSimpleName());
+        mContext = context;
+
+        mPathPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mPathPaint.setStyle(Paint.Style.STROKE);
+        mPathPaint.setColor(GRAY);
+        mPathPaint.setStrokeWidth(5);
+
+        final int iconSize = mContext.getResources()
+                .getDimensionPixelSize(com.android.internal.R.dimen.notification_large_icon_width);
+        final int topRowSize = iconSize * 2 / 3;
+
+        mCloseButton = new ImageView(mContext);
+        mCloseButton.setAlpha(0f);
+        mCloseButton.setImageDrawable(sd(closePath(topRowSize), topRowSize, mPathPaint));
+        addView(mCloseButton, new LayoutParams(topRowSize, topRowSize));
+        mCloseButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                bounce(v, null);
+                close();
+            }
+        });
+
+        mSettingsButton = new ImageView(mContext);
+        mSettingsButton.setAlpha(0f);
+        final int p = topRowSize / 7;
+        mSettingsButton.setPadding(p, p, p, p);
+        mSettingsButton.setImageResource(R.drawable.ic_notify_settings_normal);
+        LayoutParams lp = new LayoutParams(topRowSize, topRowSize);
+        lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
+        addView(mSettingsButton, lp);
+        mSettingsButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (mAdapter != null && mAdapter.getMode() == Adapter.MODE_LIMITED) {
+                    mAdapter.configure();
+                }
+                bounce(mSettingsButton, null);
+            }
+        });
+
+        mModeSpinner = new ModeSpinner(mContext);
+        mModeSpinner.setAlpha(0);
+        mModeSpinner.setEnabled(false);
+        mModeSpinner.setId(android.R.id.title);
+        lp = new LayoutParams(LayoutParams.WRAP_CONTENT, topRowSize);
+        lp.addRule(RelativeLayout.CENTER_HORIZONTAL);
+        addView(mModeSpinner, lp);
+
+        mUntilPager = new UntilPager(mContext, mPathPaint, iconSize);
+        mUntilPager.setId(android.R.id.tabhost);
+        mUntilPager.setAlpha(0);
+        lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+        lp.addRule(BELOW, mModeSpinner.getId());
+        addView(mUntilPager, lp);
+
+        mAlarmWarning = new AlarmWarning(mContext);
+        mAlarmWarning.setAlpha(0);
+        lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+        lp.addRule(CENTER_HORIZONTAL);
+        lp.addRule(BELOW, mUntilPager.getId());
+        addView(mAlarmWarning, lp);
+
+        mHintText = new TextView(mContext);
+        mHintText.setTypeface(CONDENSED);
+        mHintText.setText("Swipe down for Limited Interruptions");
+        mHintText.setGravity(Gravity.CENTER);
+        mHintText.setTextColor(GRAY);
+        addView(mHintText, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
+
+        mPopDuration = mContext.getResources().getInteger(R.integer.blinds_pop_duration_ms);
+    }
+
+    private boolean isApplicable() {
+        return mAdapter != null && mAdapter.isApplicable();
+    }
+
+    private void close() {
+        mClosing = true;
+        final int startBottom = mBottom;
+        final int max = mPeekable ? getExpandedBottom() : startBottom;
+        mHintText.animate().alpha(1).setUpdateListener(new AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                final float f = animation.getAnimatedFraction();
+                final int hintBottom = mHintText.getBottom();
+                final boolean isDone = f == 1;
+                setPeeked(hintBottom + (int)((1-f) * (startBottom - hintBottom)), max, isDone);
+                if (isDone) {
+                    mPeekable = true;
+                    mPopped = false;
+                    mClosing = false;
+                    mModeSpinner.updateState();
+                    if (mAdapter != null) {
+                        mAdapter.cancel();
+                    }
+                }
+            }
+        }).start();
+        mUntilPager.animate().alpha(0).start();
+        mAlarmWarning.animate().alpha(0).start();
+    }
+
+    public void setAdapter(Adapter adapter) {
+        mAdapter = adapter;
+        mAdapter.setCallbacks(new Adapter.Callbacks() {
+            @Override
+            public void onChanged() {
+                post(new Runnable() {
+                    @Override
+                    public void run() {
+                        updateState(true);
+                    }
+                });
+            }
+        });
+        updateState(false);
+    }
+
+    private void updateState(boolean animate) {
+        final boolean applicable = isApplicable();
+        setVisibility(applicable ? VISIBLE : GONE);
+        if (!applicable) {
+            return;
+        }
+        if (mAdapter != null && mAdapter.getMode() == Adapter.MODE_OFF && !mPeekable) {
+            close();
+        } else {
+            mModeSpinner.updateState();
+            mUntilPager.updateState();
+            mAlarmWarning.updateState(animate);
+            final float settingsAlpha = getSettingsButtonAlpha();
+            if (settingsAlpha != mSettingsButton.getAlpha()) {
+                if (animate) {
+                    mSettingsButton.animate().alpha(settingsAlpha).start();
+                } else {
+                    mSettingsButton.setAlpha(settingsAlpha);
+                }
+            }
+            if (mPeekable && mAdapter != null && mAdapter.getMode() != Adapter.MODE_OFF) {
+                if (DEBUG) log("panic expand!");
+                mPeekable = false;
+                mModeSpinner.setEnabled(true);
+                mBottom = getExpandedBottom();
+                setExpanded(1);
+            }
+        }
+    }
+
+    private float getSettingsButtonAlpha() {
+        final boolean full = mAdapter != null && mAdapter.getMode() == Adapter.MODE_FULL;
+        final boolean collapsed = mHintText.getAlpha() == 1;
+        return full || collapsed ? 0 : SETTINGS_ALPHA;
+    }
+
+    private static Path closePath(int size) {
+        final int pad = size / 4;
+        final Path p = new Path();
+        p.moveTo(pad, pad);
+        p.lineTo(size - pad, size - pad);
+        p.moveTo(size - pad, pad);
+        p.lineTo(pad, size - pad);
+        return p;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        if (DEBUG) log("onMeasure %s %s",
+                MeasureSpec.toString(widthMeasureSpec), MeasureSpec.toString(heightMeasureSpec));
+        final boolean widthExact = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY;
+
+        if (!widthExact || (widthMeasureSpec != mWidthSpec)) {
+            if (DEBUG) log("  super.onMeasure");
+            final int hms = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+            super.onMeasure(widthMeasureSpec, hms);
+            mBottom = mPeekable ? mHintText.getMeasuredHeight() : getExpandedBottom();
+            mWidthSpec = widthMeasureSpec;
+        }
+        if (DEBUG) log("mBottom (OM) = " + mBottom);
+        setMeasuredDimension(getMeasuredWidth(), mBottom);
+        if (DEBUG) log("  mw=%s mh=%s",
+                toString(getMeasuredWidthAndState()), toString(getMeasuredHeightAndState()));
+    }
+
+    private static String toString(int sizeAndState) {
+        final int size = sizeAndState & MEASURED_SIZE_MASK;
+        final boolean tooSmall = (sizeAndState & MEASURED_STATE_TOO_SMALL) != 0;
+        return size + (tooSmall ? "TOO SMALL" : "");
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        mLayoutRect.set(left, top, right, bottom);
+        if (DEBUG) log("onLayout %s %s %dx%d", changed,
+                mLayoutRect.toShortString(), mLayoutRect.width(), mLayoutRect.height());
+        super.onLayout(changed, left, top, right, bottom);
+    }
+
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent ev) {
+        final boolean rt = super.dispatchTouchEvent(ev);
+        if (DEBUG) logTouchEvent("dispatchTouchEvent", rt, ev);
+        return rt;
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        final boolean rt = super.onInterceptTouchEvent(ev);
+        if (DEBUG) logTouchEvent("onInterceptTouchEvent", rt, ev);
+        if (isApplicable()
+                && ev.getAction() == MotionEvent.ACTION_DOWN
+                && ev.getY() > mCloseButton.getBottom()
+                && mPeekable) {
+            return true;
+        }
+        return rt;
+    }
+
+    private static void logTouchEvent(String method, boolean rt, MotionEvent event) {
+        final String action = MotionEvent.actionToString(event.getAction());
+        Log.d(TAG, method + " " + (rt ? "TRUE" : "FALSE") + " " + action);
+    }
+
+    private int getExpandedBottom() {
+        int b = mModeSpinner.getMeasuredHeight() + mUntilPager.getMeasuredHeight();
+        if (mAlarmWarning.getAlpha() == 1) b += mAlarmWarning.getMeasuredHeight();
+        return b;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        boolean rt = super.onTouchEvent(event);
+        if (DEBUG) logTouchEvent("onTouchEvent", rt, event);
+        if (!isApplicable() || !mPeekable) {
+            return rt;
+        }
+        if (event.getAction() == MotionEvent.ACTION_DOWN) {
+            mDownY = event.getY();
+            if (DEBUG) log("  mDownY=" + mDownY);
+            mDownBottom = mBottom;
+            return true;
+        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
+            final float dy = event.getY() - mDownY;
+            if (!mPopped) {
+                mPopped = true;
+                AsyncTask.execute(mPopVibration);
+            }
+            setPeeked(mDownBottom + (int)dy, getExpandedBottom(), false);
+        } else if (event.getAction() == MotionEvent.ACTION_UP
+                || event.getAction() == MotionEvent.ACTION_CANCEL) {
+            final float dy = event.getY() - mDownY;
+            setPeeked(mDownBottom + (int)dy, getExpandedBottom(), true);
+            if (mPeekable) {
+                close();
+            }
+        }
+        return rt;
+    }
+
+    private void setPeeked(int peeked, int max, boolean isDone) {
+        if (DEBUG) log("setPeeked=" + peeked);
+        final int min = mHintText.getBottom();
+        peeked = Math.max(min, Math.min(peeked, max));
+        if (!isDone && mBottom == peeked) {
+            return;
+        }
+        if (peeked == max && isDone) {
+            mPeekable = false;
+            mModeSpinner.setEnabled(true);
+            if (mAdapter != null) {
+                mAdapter.setMode(Adapter.MODE_LIMITED);
+            }
+        }
+        if (peeked == min) {
+            mPeekable = true;
+            mModeSpinner.setEnabled(false);
+        }
+        if (DEBUG) log("  mBottom=" + peeked);
+        mBottom = peeked;
+        final float f = (peeked - min) / (float)(max - min);
+        setExpanded(f);
+        requestLayout();
+    }
+
+    private void setExpanded(float f) {
+        if (DEBUG) log("setExpanded " + f);
+        final int a = (int)(Color.alpha(BACKGROUND) * f);
+        setBackgroundColor(Color.argb(a,
+                Color.red(BACKGROUND), Color.green(BACKGROUND), Color.blue(BACKGROUND)));
+        mHintText.setAlpha(1 - f);
+        mCloseButton.setAlpha(f);
+        mModeSpinner.setAlpha(f);
+        mUntilPager.setAlpha(f);
+        mSettingsButton.setAlpha(f * getSettingsButtonAlpha());
+    }
+
+    private static void log(String msg, Object... args) {
+        Log.d(TAG, args == null || args.length == 0 ? msg : String.format(msg, args));
+    }
+
+    private static ShapeDrawable sd(Path p, int size, Paint pt) {
+        final ShapeDrawable sd = new ShapeDrawable(new PathShape(p, size, size));
+        sd.getPaint().set(pt);
+        sd.setIntrinsicHeight(size);
+        sd.setIntrinsicWidth(size);
+        return sd;
+    }
+
+    public void dispatchExternalTouchEvent(MotionEvent ev) {
+        if (isApplicable()) {
+            onTouchEvent(ev);
+        }
+    }
+
+    private static void bounce(final View v, final Runnable midBounce) {
+        v.animate().scaleX(BOUNCE_SCALE).scaleY(BOUNCE_SCALE).setDuration(DURATION / 3)
+            .setListener(new AnimatorListenerAdapter() {
+                private boolean mFired;
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    if (!mFired) {
+                        mFired = true;
+                        if (midBounce != null) {
+                            midBounce.run();
+                        }
+                        v.animate().scaleX(1).scaleY(1).setListener(null).start();
+                    }
+                }
+            }).start();
+    }
+
+    private final Runnable mPopVibration = new Runnable() {
+        @Override
+        public void run() {
+            Vibrator v = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
+            v.vibrate(mPopDuration);
+        }
+    };
+
+    private final class UntilPager extends RelativeLayout {
+        private final ImageView mPrev;
+        private final ImageView mNext;
+        private final TextView mText1;
+        private final TextView mText2;
+
+        private TextView mText;
+
+        public UntilPager(Context context, Paint pathPaint, int iconSize) {
+            super(context);
+            mText1 = new TextView(mContext);
+            mText1.setTypeface(CONDENSED);
+            mText1.setTextColor(GRAY);
+            mText1.setGravity(Gravity.CENTER);
+            LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, iconSize);
+            addView(mText1, lp);
+            mText = mText1;
+
+            mText2 = new TextView(mContext);
+            mText2.setTypeface(CONDENSED);
+            mText2.setTextColor(GRAY);
+            mText2.setAlpha(0);
+            mText2.setGravity(Gravity.CENTER);
+            addView(mText2, lp);
+
+            lp = new LayoutParams(iconSize, iconSize);
+            final View v = new View(mContext);
+            v.setBackgroundColor(BACKGROUND);
+            addView(v, lp);
+            mPrev = new ImageView(mContext);
+            mPrev.setId(android.R.id.button1);
+            mPrev.setImageDrawable(sd(prevPath(iconSize), iconSize, pathPaint));
+            addView(mPrev, lp);
+            mPrev.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    onNav(v, -1);
+                }
+            });
+
+            lp = new LayoutParams(iconSize, iconSize);
+            lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
+            final View v2 = new View(mContext);
+            v2.setBackgroundColor(BACKGROUND);
+            addView(v2, lp);
+            mNext = new ImageView(mContext);
+            mNext.setId(android.R.id.button2);
+            mNext.setImageDrawable(sd(nextPath(iconSize), iconSize, pathPaint));
+            addView(mNext, lp);
+            mNext.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    onNav(v, 1);
+                }
+            });
+
+            updateState();
+        }
+
+        private void onNav(View v, int d) {
+            bounce(v, null);
+            if (mAdapter == null) {
+                return;
+            }
+            if (mAdapter.getExitConditionCount() == 1) {
+                horBounce(d);
+                return;
+            }
+            final int w = getWidth();
+            final float s = Math.signum(d);
+            final TextView current = mText;
+            final TextView other = mText == mText1 ? mText2 : mText1;
+            final ExitCondition ec = mAdapter.getExitCondition(d);
+            setText(other, ec);
+            other.setTranslationX(-s * w);
+            other.animate().translationX(0).alpha(1).setDuration(DURATION).start();
+            current.animate().translationX(s * w).alpha(0).setDuration(DURATION).start();
+            mText = other;
+            mAdapter.select(ec);
+        }
+
+        private void horBounce(int d) {
+            final int w = getWidth();
+            mText.animate()
+                    .setDuration(BOUNCE_DURATION)
+                    .translationX(Math.signum(d) * w / 20)
+                    .setListener(new AnimatorListenerAdapter() {
+                        @Override
+                        public void onAnimationEnd(Animator animation) {
+                            mText.animate().translationX(0).setListener(null).start();
+                        }
+                    }).start();
+        }
+
+        private void setText(final TextView textView, final ExitCondition ec) {
+            SpannableStringBuilder ss = new SpannableStringBuilder(ec.line1 + "\n" + ec.line2);
+            ss.setSpan(new RelativeSizeSpan(1.5f), (ec.line1 + "\n").length(), ss.length(),
+                    Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
+            if (ec.action != null) {
+                ss.setSpan(new CustomLinkSpan() {
+                    @Override
+                    public void onClick() {
+                        // TODO wire up links
+                        Toast.makeText(mContext, ec.action, Toast.LENGTH_SHORT).show();
+                    }
+                }, (ec.line1 + "\n").length(), ss.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
+                textView.setMovementMethod(LinkMovementMethod.getInstance());
+            } else {
+                textView.setMovementMethod(null);
+            }
+            textView.setText(ss);
+        }
+
+        private void updateState() {
+            if (mAdapter == null) {
+                return;
+            }
+            setText(mText, mAdapter.getExitCondition(0));
+        }
+
+        private Path prevPath(int size) {
+            final int hp = size / 3;
+            final int vp = size / 4;
+            final Path p = new Path();
+            p.moveTo(size - hp, vp);
+            p.lineTo(hp, size / 2);
+            p.lineTo(size - hp, size - vp);
+            return p;
+        }
+
+        private Path nextPath(int size) {
+            final int hp = size / 3;
+            final int vp = size / 4;
+            Path p = new Path();
+            p.moveTo(hp, vp);
+            p.lineTo(size - hp, size / 2);
+            p.lineTo(hp, size - vp);
+            return p;
+        }
+    }
+
+    private abstract static class CustomLinkSpan extends URLSpan {
+        abstract public void onClick();
+
+        public CustomLinkSpan() {
+            super("#");
+        }
+
+        @Override
+        public void updateDrawState(TextPaint ds) {
+            super.updateDrawState(ds);
+            ds.setUnderlineText(false);
+            ds.bgColor = BACKGROUND;
+        }
+
+        @Override
+        public void onClick(View widget) {
+            onClick();
+        }
+    }
+
+    public interface Adapter {
+        public static final int MODE_OFF = 0;
+        public static final int MODE_LIMITED = 1;
+        public static final int MODE_FULL = 2;
+
+        boolean isApplicable();
+        void configure();
+        int getMode();
+        void setMode(int mode);
+        void select(ExitCondition ec);
+        void cancel();
+        void setCallbacks(Callbacks callbacks);
+        ExitCondition getExitCondition(int d);
+        int getExitConditionCount();
+
+        public static class ExitCondition {
+            public String summary;
+            public String line1;
+            public String line2;
+            public String action;
+        }
+
+        public interface Callbacks {
+            void onChanged();
+        }
+    }
+
+    private final class ModeSpinner extends Spinner {
+        public ModeSpinner(final Context context) {
+            super(context);
+            setBackgroundResource(R.drawable.spinner_default_holo_dark_am_no_underline);
+            final ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(mContext, 0) {
+                @Override
+                public View getView(int position, View convertView,  ViewGroup parent) {
+                    if (DEBUG) log("getView %s parent=%s", position, parent);
+                    return getDropDownView(position, convertView, parent);
+                }
+
+                @Override
+                public View getDropDownView(int position, View convertView, ViewGroup parent) {
+                    if (DEBUG) log("getDropDownView %s cv=%s parent=%s",
+                            position, convertView, parent);
+                    final TextView tv = convertView != null ? (TextView) convertView
+                            : new TextView(context);
+                    final int mode = getItem(position);
+                    tv.setText(modeToString(mode));
+                    if (convertView == null) {
+                        if (DEBUG) log(" setting up view");
+                        tv.setTextColor(GRAY);
+                        tv.setTypeface(CONDENSED);
+                        tv.setAllCaps(true);
+                        tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, tv.getTextSize() * 1.5f);
+                        final int p = (int) tv.getTextSize() / 2;
+                        if (parent instanceof ListView) {
+                            tv.setPadding(p, p, p, p);
+                        } else {
+                            tv.setGravity(Gravity.CENTER_HORIZONTAL);
+                            tv.setPadding(p, 0, p, 0);
+                        }
+                    }
+                    tv.setOnTouchListener(new OnTouchListener(){
+                        @Override
+                        public boolean onTouch(View v, MotionEvent event) {
+                            if (DEBUG) log("onTouch %s %s", tv.getText(),
+                                    MotionEvent.actionToString(event.getAction()));
+                            if (mAdapter != null) {
+                                mAdapter.setMode(mode);
+                            }
+                            return false;
+                        }
+
+                    });
+                    return tv;
+                }
+            };
+            adapter.add(Adapter.MODE_LIMITED);
+            adapter.add(Adapter.MODE_FULL);
+            setAdapter(adapter);
+        }
+
+        public void updateState() {
+            int mode = mAdapter != null ? mAdapter.getMode() : Adapter.MODE_LIMITED;
+            if (mode == Adapter.MODE_OFF) {
+                mode = Adapter.MODE_LIMITED;
+            }
+            if (DEBUG) log("setSelectedMode " + mode);
+            for (int i = 0; i < getAdapter().getCount(); i++) {
+                if (getAdapter().getItem(i).equals(mode)) {
+                    if (DEBUG) log("  setting selection = " + i);
+                    setSelection(i, true);
+                    return;
+                }
+            }
+        }
+
+        private String modeToString(int mode) {
+            if (mode == Adapter.MODE_LIMITED) return "Limited interruptions";
+            if (mode == Adapter.MODE_FULL) return "Zero interruptions";
+            throw new UnsupportedOperationException("Unsupported mode: " + mode);
+        }
+    }
+
+    private final class AlarmWarning extends LinearLayout {
+        public AlarmWarning(Context context) {
+            super(context);
+            setOrientation(HORIZONTAL);
+
+            final TextView tv = new TextView(mContext);
+            tv.setTextColor(GRAY);
+            tv.setGravity(Gravity.TOP);
+            tv.setTypeface(CONDENSED);
+            tv.setText(FULL_TEXT);
+            addView(tv);
+
+            final ImageView icon = new ImageView(mContext);
+            icon.setAlpha(.75f);
+            int size = (int)tv.getTextSize();
+            icon.setImageResource(android.R.drawable.ic_dialog_alert);
+            LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(size, size);
+            final int p = size / 4;
+            lp.bottomMargin = lp.topMargin = lp.rightMargin = lp.leftMargin = p;
+            addView(icon, 0, lp);
+            setPadding(p, 0, p, p);
+        }
+
+        public void updateState(boolean animate) {
+            final boolean visible = mAdapter != null && mAdapter.getMode() == Adapter.MODE_FULL;
+            final float alpha = visible ? 1 : 0;
+            if (alpha == getAlpha()) {
+                return;
+            }
+            if (animate) {
+                final boolean in = alpha == 1;
+                animate().alpha(alpha).setUpdateListener(new AnimatorUpdateListener() {
+                    @Override
+                    public void onAnimationUpdate(ValueAnimator animation) {
+                        if (mPeekable || mClosing) {
+                            return;
+                        }
+                        float f = animation.getAnimatedFraction();
+                        if (!in) {
+                            f = 1 - f;
+                        }
+                        ZenModeView.this.mBottom = mUntilPager.getBottom()
+                                + (int)(mAlarmWarning.getMeasuredHeight() * f);
+                        if (DEBUG) log("mBottom (AW) = " + mBottom);
+                        requestLayout();
+                    }
+                }).start();
+            } else {
+                setAlpha(alpha);
+                requestLayout();
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeViewAdapter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeViewAdapter.java
new file mode 100644
index 0000000..39c4faa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeViewAdapter.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.provider.Settings;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.List;
+
+public abstract class ZenModeViewAdapter implements ZenModeView.Adapter {
+    private static final String TAG = "ZenModeViewAdapter";
+
+    private final Context mContext;
+    private final ContentResolver mResolver;
+    private final Handler mHandler = new Handler();
+    private final SettingsObserver mObserver;
+    private final List<ExitCondition> mExits = Arrays.asList(
+            newExit("Until you delete this", "Until", "You delete this"));
+
+    private Callbacks mCallbacks;
+    private int mExitIndex;
+    private boolean mDeviceProvisioned;
+    private int mMode;
+
+    public ZenModeViewAdapter(Context context) {
+        mContext = context;
+        mResolver = mContext.getContentResolver();
+        mObserver = new SettingsObserver(mHandler);
+        mObserver.init();
+    }
+
+    @Override
+    public boolean isApplicable() {
+        return mDeviceProvisioned;
+    }
+
+    @Override
+    public int getMode() {
+        return mMode;
+    }
+
+    @Override
+    public void setMode(int mode) {
+        final int v = mode == MODE_LIMITED ? Settings.Global.ZEN_MODE_LIMITED
+                    : mode == MODE_FULL ? Settings.Global.ZEN_MODE_FULL
+                    : Settings.Global.ZEN_MODE_OFF;
+        AsyncTask.execute(new Runnable() {
+            @Override
+            public void run() {
+                Settings.Global.putInt(mContext.getContentResolver(),
+                        Settings.Global.ZEN_MODE, v);
+            }
+        });
+    }
+
+    @Override
+    public void cancel() {
+        if (mExitIndex != 0) {
+            mExitIndex = 0;
+            mHandler.post(mChange);
+        }
+        setMode(MODE_OFF);
+    }
+
+    @Override
+    public void setCallbacks(final Callbacks callbacks) {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mCallbacks = callbacks;
+            }
+        });
+    }
+
+    @Override
+    public ExitCondition getExitCondition(int d) {
+        final int n = mExits.size();
+        final int i = (n + (mExitIndex + (int)Math.signum(d))) % n;
+        return mExits.get(i);
+    }
+
+    @Override
+    public int getExitConditionCount() {
+        return mExits.size();
+    }
+
+    @Override
+    public void select(ExitCondition ec) {
+        final int i = mExits.indexOf(ec);
+        if (i == -1 || i == mExitIndex) {
+            return;
+        }
+        mExitIndex = i;
+        mHandler.post(mChange);
+    }
+
+    private static ExitCondition newExit(String summary, String line1, String line2) {
+        final ExitCondition rt = new ExitCondition();
+        rt.summary = summary;
+        rt.line1 = line1;
+        rt.line2 = line2;
+        return rt;
+    }
+
+    private final Runnable mChange = new Runnable() {
+        public void run() {
+            if (mCallbacks == null) {
+                return;
+            }
+            try {
+                mCallbacks.onChanged();
+            } catch (Throwable t) {
+                Log.w(TAG, "Error dispatching onChanged to " + mCallbacks, t);
+            }
+        }
+    };
+
+    private final class SettingsObserver extends ContentObserver {
+        public SettingsObserver(Handler handler) {
+            super(handler);
+        }
+
+        public void init() {
+            loadSettings();
+            mResolver.registerContentObserver(
+                    Settings.Global.getUriFor(Settings.Global.ZEN_MODE),
+                    false, this);
+            mResolver.registerContentObserver(
+                    Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
+                    false, this);
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            loadSettings();
+            mChange.run();  // already on handler
+        }
+
+        private void loadSettings() {
+            mDeviceProvisioned = Settings.Global.getInt(mResolver,
+                    Settings.Global.DEVICE_PROVISIONED, 0) != 0;
+            mMode = getMode();
+        }
+
+        private int getMode() {
+            final int v = Settings.Global.getInt(mResolver,
+                    Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
+            if (v == Settings.Global.ZEN_MODE_LIMITED) return MODE_LIMITED;
+            if (v == Settings.Global.ZEN_MODE_FULL) return MODE_FULL;
+            return MODE_OFF;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
index 491c35e..79932a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
@@ -28,6 +28,7 @@
 import android.widget.FrameLayout;
 
 import com.android.systemui.ExpandHelper;
+import com.android.systemui.Gefingerpoken;
 import com.android.systemui.R;
 import com.android.systemui.SwipeHelper;
 import com.android.systemui.statusbar.BaseStatusBar;
@@ -42,13 +43,13 @@
 
     private final int mTouchSensitivityDelay;
     private SwipeHelper mSwipeHelper;
+    private EdgeSwipeHelper mEdgeSwipeHelper;
 
     private BaseStatusBar mBar;
     private ExpandHelper mExpandHelper;
-    private long mStartTouchTime;
 
+    private long mStartTouchTime;
     private ViewGroup mContentHolder;
-    private ViewGroup mContentSlider;
 
     private NotificationData.Entry mHeadsUp;
 
@@ -72,19 +73,24 @@
 
     public boolean setNotification(NotificationData.Entry headsUp) {
         mHeadsUp = headsUp;
-        mHeadsUp.row.setExpanded(false);
-        mHeadsUp.row.setShowingPublic(false);
-        if (mContentHolder == null) {
-            // too soon!
-            return false;
+        if (mContentHolder != null) {
+            mContentHolder.removeAllViews();
         }
-        mContentHolder.setX(0);
-        mContentHolder.setVisibility(View.VISIBLE);
-        mContentHolder.setAlpha(1f);
-        mContentHolder.removeAllViews();
-        mContentHolder.addView(mHeadsUp.row);
-        mSwipeHelper.snapChild(mContentSlider, 1f);
-        mStartTouchTime = System.currentTimeMillis() + mTouchSensitivityDelay;
+
+        if (mHeadsUp != null) {
+            mHeadsUp.row.setExpanded(true);
+            mHeadsUp.row.setShowingPublic(false);
+            if (mContentHolder == null) {
+                // too soon!
+                return false;
+            }
+            mContentHolder.setX(0);
+            mContentHolder.setVisibility(View.VISIBLE);
+            mContentHolder.setAlpha(1f);
+            mContentHolder.addView(mHeadsUp.row);
+            mSwipeHelper.snapChild(mContentHolder, 1f);
+            mStartTouchTime = System.currentTimeMillis() + mTouchSensitivityDelay;
+        }
         return true;
     }
 
@@ -94,10 +100,11 @@
 
     public void setMargin(int notificationPanelMarginPx) {
         if (SPEW) Log.v(TAG, "setMargin() " + notificationPanelMarginPx);
-        if (mContentSlider != null) {
-            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mContentSlider.getLayoutParams();
+        if (mContentHolder != null &&
+                mContentHolder.getLayoutParams() instanceof FrameLayout.LayoutParams) {
+            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mContentHolder.getLayoutParams();
             lp.setMarginStart(notificationPanelMarginPx);
-            mContentSlider.setLayoutParams(lp);
+            mContentHolder.setLayoutParams(lp);
         }
     }
 
@@ -122,15 +129,17 @@
     @Override
     public void onAttachedToWindow() {
         float densityScale = getResources().getDisplayMetrics().density;
-        float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop();
+        final ViewConfiguration viewConfiguration = ViewConfiguration.get(getContext());
+        float pagingTouchSlop = viewConfiguration.getScaledPagingTouchSlop();
+        float touchSlop = viewConfiguration.getScaledTouchSlop();
         mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, pagingTouchSlop);
+        mEdgeSwipeHelper = new EdgeSwipeHelper(touchSlop);
 
         int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_min_height);
         int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_max_height);
         mExpandHelper = new ExpandHelper(getContext(), this, minHeight, maxHeight);
 
         mContentHolder = (ViewGroup) findViewById(R.id.content_holder);
-        mContentSlider = (ViewGroup) findViewById(R.id.content_slider);
 
         if (mHeadsUp != null) {
             // whoops, we're on already!
@@ -144,7 +153,8 @@
         if (System.currentTimeMillis() < mStartTouchTime) {
             return true;
         }
-        return mSwipeHelper.onInterceptTouchEvent(ev)
+        return mEdgeSwipeHelper.onInterceptTouchEvent(ev)
+                || mSwipeHelper.onInterceptTouchEvent(ev)
                 || mExpandHelper.onInterceptTouchEvent(ev)
                 || super.onInterceptTouchEvent(ev);
     }
@@ -157,7 +167,8 @@
             return false;
         }
         mBar.resetHeadsUpDecayTimer();
-        return mSwipeHelper.onTouchEvent(ev)
+        return mEdgeSwipeHelper.onTouchEvent(ev)
+                || mSwipeHelper.onTouchEvent(ev)
                 || mExpandHelper.onTouchEvent(ev)
                 || super.onTouchEvent(ev);
     }
@@ -226,11 +237,65 @@
 
     @Override
     public View getChildAtPosition(MotionEvent ev) {
-        return mContentSlider;
+        return mContentHolder;
     }
 
     @Override
     public View getChildContentView(View v) {
-        return mContentSlider;
+        return mContentHolder;
+    }
+
+    private class EdgeSwipeHelper implements Gefingerpoken {
+        private static final boolean DEBUG_EDGE_SWIPE = false;
+        private final float mTouchSlop;
+        private boolean mConsuming;
+        private float mFirstY;
+        private float mFirstX;
+
+        public EdgeSwipeHelper(float touchSlop) {
+            mTouchSlop = touchSlop;
+        }
+
+        @Override
+        public boolean onInterceptTouchEvent(MotionEvent ev) {
+            switch (ev.getActionMasked()) {
+                case MotionEvent.ACTION_DOWN:
+                    if (DEBUG_EDGE_SWIPE) Log.d(TAG, "action down " + ev.getY());
+                    mFirstX = ev.getX();
+                    mFirstY = ev.getY();
+                    mConsuming = false;
+                    break;
+
+                case MotionEvent.ACTION_MOVE:
+                    if (DEBUG_EDGE_SWIPE) Log.d(TAG, "action move " + ev.getY());
+                    final float dY = ev.getY() - mFirstY;
+                    final float daX = Math.abs(ev.getX() - mFirstX);
+                    final float daY = Math.abs(dY);
+                    if (!mConsuming && (4f * daX) < daY && daY > mTouchSlop) {
+                        if (dY > 0) {
+                            if (DEBUG_EDGE_SWIPE) Log.d(TAG, "found an open");
+                            mBar.animateExpandNotificationsPanel();
+                        }
+                        if (dY < 0) {
+                            if (DEBUG_EDGE_SWIPE) Log.d(TAG, "found a close");
+                            mBar.onHeadsUpDismissed();
+                        }
+                        mConsuming = true;
+                    }
+                    break;
+
+                case MotionEvent.ACTION_UP:
+                case MotionEvent.ACTION_CANCEL:
+                    if (DEBUG_EDGE_SWIPE) Log.d(TAG, "action done" );
+                    mConsuming = false;
+                    break;
+            }
+            return mConsuming;
+        }
+
+        @Override
+        public boolean onTouchEvent(MotionEvent ev) {
+            return mConsuming;
+        }
     }
 }
\ No newline at end of file
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index f82ca22..0120a03 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -363,36 +363,38 @@
     }
 
     private void addUsersToMenu(ArrayList<Action> items) {
-        List<UserInfo> users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE))
-                .getUsers();
-        if (users.size() > 1) {
+        UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        if (um.isUserSwitcherEnabled()) {
+            List<UserInfo> users = um.getUsers();
             UserInfo currentUser = getCurrentUser();
             for (final UserInfo user : users) {
-                boolean isCurrentUser = currentUser == null
-                        ? user.id == 0 : (currentUser.id == user.id);
-                Drawable icon = user.iconPath != null ? Drawable.createFromPath(user.iconPath)
-                        : null;
-                SinglePressAction switchToUser = new SinglePressAction(
-                        com.android.internal.R.drawable.ic_menu_cc, icon,
-                        (user.name != null ? user.name : "Primary")
-                        + (isCurrentUser ? " \u2714" : "")) {
-                    public void onPress() {
-                        try {
-                            ActivityManagerNative.getDefault().switchUser(user.id);
-                        } catch (RemoteException re) {
-                            Log.e(TAG, "Couldn't switch user " + re);
+                if (user.supportsSwitchTo()) {
+                    boolean isCurrentUser = currentUser == null
+                            ? user.id == 0 : (currentUser.id == user.id);
+                    Drawable icon = user.iconPath != null ? Drawable.createFromPath(user.iconPath)
+                            : null;
+                    SinglePressAction switchToUser = new SinglePressAction(
+                            com.android.internal.R.drawable.ic_menu_cc, icon,
+                            (user.name != null ? user.name : "Primary")
+                            + (isCurrentUser ? " \u2714" : "")) {
+                        public void onPress() {
+                            try {
+                                ActivityManagerNative.getDefault().switchUser(user.id);
+                            } catch (RemoteException re) {
+                                Log.e(TAG, "Couldn't switch user " + re);
+                            }
                         }
-                    }
 
-                    public boolean showDuringKeyguard() {
-                        return true;
-                    }
+                        public boolean showDuringKeyguard() {
+                            return true;
+                        }
 
-                    public boolean showBeforeProvisioning() {
-                        return false;
-                    }
-                };
-                items.add(switchToUser);
+                        public boolean showBeforeProvisioning() {
+                            return false;
+                        }
+                    };
+                    items.add(switchToUser);
+                }
             }
         }
     }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index c73d90a..977c2e7 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -29,6 +29,8 @@
 import android.transition.Transition;
 import android.transition.TransitionInflater;
 import android.transition.TransitionManager;
+import android.transition.TransitionSet;
+import android.util.ArrayMap;
 import android.view.ViewConfiguration;
 
 import com.android.internal.R;
@@ -45,6 +47,7 @@
 import com.android.internal.widget.ActionBarContextView;
 import com.android.internal.widget.ActionBarOverlayLayout;
 import com.android.internal.widget.ActionBarView;
+import com.android.internal.widget.SwipeDismissLayout;
 
 import android.app.KeyguardManager;
 import android.content.Context;
@@ -105,6 +108,9 @@
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
 
 /**
  * Android-specific Window.
@@ -120,6 +126,13 @@
     private static final long MAX_TRANSITION_START_WAIT = 500;
     private static final long MAX_TRANSITION_FINISH_WAIT = 1000;
 
+    private static final String KEY_SCREEN_X = "shared_element:screenX";
+    private static final String KEY_SCREEN_Y = "shared_element:screenY";
+    private static final String KEY_TRANSLATION_Z = "shared_element:translationZ";
+    private static final String KEY_WIDTH = "shared_element:width";
+    private static final String KEY_HEIGHT = "shared_element:height";
+    private static final String KEY_NAME = "shared_element:name";
+
     /**
      * Simple callback used by the context menu and its submenus. The options
      * menu submenus do not use this (their behavior is more complex).
@@ -239,7 +252,8 @@
 
     private ActivityOptions mActivityOptions;
     private SceneTransitionListener mSceneTransitionListener;
-    private boolean mFadeEarly = true;
+    private boolean mTriggerEarly = true;
+    private Map<String, String> mSharedElementsMap;
 
     static class WindowManagerHolder {
         static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface(
@@ -282,6 +296,15 @@
             // Remove the action bar feature if we have no title. No title dominates.
             removeFeature(FEATURE_ACTION_BAR);
         }
+
+        if ((features & (1 << FEATURE_ACTION_BAR)) != 0 && featureId == FEATURE_SWIPE_TO_DISMISS) {
+            throw new AndroidRuntimeException(
+                    "You cannot combine swipe dismissal and the action bar.");
+        }
+        if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0 && featureId == FEATURE_ACTION_BAR) {
+            throw new AndroidRuntimeException(
+                    "You cannot combine swipe dismissal and the action bar.");
+        }
         return super.requestFeature(featureId);
     }
 
@@ -2562,6 +2585,11 @@
             return super.fitSystemWindows(insets);
         }
 
+        @Override
+        public boolean isTransitionGroup() {
+            return false;
+        }
+
         private void updateStatusGuard(Rect insets) {
             boolean showStatusGuard = false;
             // Show the status guard when the non-overlay contextual action bar is showing
@@ -2906,6 +2934,10 @@
             requestFeature(FEATURE_ACTION_MODE_OVERLAY);
         }
 
+        if (a.getBoolean(com.android.internal.R.styleable.Window_windowSwipeToDismiss, false)) {
+            requestFeature(FEATURE_SWIPE_TO_DISMISS);
+        }
+
         if (a.getBoolean(com.android.internal.R.styleable.Window_windowFullscreen, false)) {
             setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN & (~getForcedWindowFlags()));
         }
@@ -3035,7 +3067,9 @@
         int layoutResource;
         int features = getLocalFeatures();
         // System.out.println("Features: 0x" + Integer.toHexString(features));
-        if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
+        if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
+            layoutResource = com.android.internal.R.layout.screen_swipe_dismiss;
+        } else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
             if (mIsFloating) {
                 TypedValue res = new TypedValue();
                 getContext().getTheme().resolveAttribute(
@@ -3105,6 +3139,10 @@
             }
         }
 
+        if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
+            registerSwipeCallbacks();
+        }
+
         // Remaining setup -- of background and title -- that only applies
         // to top-level windows.
         if (getContainer() == null) {
@@ -3475,6 +3513,53 @@
         return (mRightIconView = (ImageView)findViewById(com.android.internal.R.id.right_icon));
     }
 
+    private void registerSwipeCallbacks() {
+        SwipeDismissLayout swipeDismiss =
+                (SwipeDismissLayout) findViewById(com.android.internal.R.id.content);
+        swipeDismiss.setOnDismissedListener(new SwipeDismissLayout.OnDismissedListener() {
+            @Override
+            public void onDismissed(SwipeDismissLayout layout) {
+                Callback cb = getCallback();
+                if (cb != null) {
+                    try {
+                        cb.onWindowDismissed();
+                    } catch (AbstractMethodError e) {
+                        Log.e(TAG, "onWindowDismissed not implemented in " +
+                                cb.getClass().getSimpleName(), e);
+                    }
+                }
+            }
+        });
+        swipeDismiss.setOnSwipeProgressChangedListener(
+                new SwipeDismissLayout.OnSwipeProgressChangedListener() {
+                    private boolean mIsTranslucent = false;
+
+                    @Override
+                    public void onSwipeProgressChanged(
+                            SwipeDismissLayout layout, float progress, float translate) {
+                        WindowManager.LayoutParams newParams = getAttributes();
+                        newParams.x = (int) translate;
+                        setAttributes(newParams);
+
+                        int flags = 0;
+                        if (newParams.x == 0) {
+                            flags = FLAG_FULLSCREEN;
+                        } else {
+                            flags = FLAG_LAYOUT_NO_LIMITS;
+                        }
+                        setFlags(flags, FLAG_FULLSCREEN | FLAG_LAYOUT_NO_LIMITS);
+                    }
+
+                    @Override
+                    public void onSwipeCancelled(SwipeDismissLayout layout) {
+                        WindowManager.LayoutParams newParams = getAttributes();
+                        newParams.x = 0;
+                        setAttributes(newParams);
+                        setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN | FLAG_LAYOUT_NO_LIMITS);
+                    }
+                });
+    }
+
     /**
      * Helper method for calling the {@link Callback#onPanelClosed(int, Menu)}
      * callback. This method will grab whatever extra state is needed for the
@@ -3988,78 +4073,214 @@
     }
 
     @Override
-    public void setEarlyBackgroundTransition(boolean fadeEarly) {
-        mFadeEarly = fadeEarly;
+    public void setTriggerEarlyEnterTransition(boolean triggerEarly) {
+        mTriggerEarly = triggerEarly;
     }
 
     @Override
-    public void startExitTransition(ActivityOptions activityOptions) {
-        Transition transition = mTransitionManager.getNamedTransition(getContentScene(), "null");
-        if (transition == null) {
-            transition = TransitionManager.getDefaultTransition().clone();
+    public void mapTransitionTargets(Map<String, String> sharedElementNames) {
+        mSharedElementsMap = sharedElementNames;
+    }
+
+    @Override
+    public Bundle startExitTransition(ActivityOptions activityOptions) {
+        if (mContentScene == null) {
+            return null;
         }
-        activityOptions.setExitTransition(transition, new ActivityOptions.SharedElementSource() {
+        Transition transition = mTransitionManager.getExitTransition(mContentScene);
+        if (transition == null) {
+            return null;
+        }
+
+        ArrayMap<String, View> sharedElements = findSharedElements(activityOptions);
+
+        // Find exiting Views and shared elements
+        final ArrayList<View> transitioningViews = new ArrayList<View>();
+        mDecor.captureTransitioningViews(transitioningViews);
+        transitioningViews.removeAll(sharedElements.values());
+
+        Transition exitTransition = cloneAndSetTransitionTargets(transition,
+                transitioningViews, true);
+        Transition sharedElementTransition = cloneAndSetTransitionTargets(transition,
+                transitioningViews, false);
+
+        // transitionSet is the total exit transition, including hero animation.
+        TransitionSet transitionSet = new TransitionSet();
+        transitionSet.addTransition(exitTransition);
+        transitionSet.addTransition(sharedElementTransition);
+
+        updateExitActivityOptions(activityOptions, sharedElements,
+                sharedElementTransition, exitTransition);
+
+        // Start exiting the Views that need to exit
+        TransitionManager.beginDelayedTransition(mDecor, transitionSet);
+        setViewVisibility(transitioningViews, View.INVISIBLE);
+
+        return activityOptions.toBundle();
+    }
+
+    private ArrayMap<String, View> findSharedElements(ActivityOptions activityOptions) {
+        ArrayMap<String, View> sharedElements = new ArrayMap<String, View>();
+        mDecor.findSharedElements(sharedElements);
+        ArrayList<String> localNames = activityOptions.getLocalElementNames();
+        sharedElements.keySet().retainAll(localNames);
+
+        ArrayList<String> targetNames = activityOptions.getSharedElementNames();
+        for (int i = 0; i < localNames.size(); i++) {
+            String localName = localNames.get(i);
+            View sharedElement = sharedElements.remove(localName);
+            String targetName = targetNames.get(i);
+            sharedElements.put(targetName, sharedElement);
+        }
+        return sharedElements;
+    }
+
+    private void updateExitActivityOptions(ActivityOptions activityOptions,
+            final Map<String, View> sharedElements, Transition sharedElementTransition,
+            Transition exitTransition) {
+
+        // Schedule capturing of the shared element state
+        final Bundle sharedElementArgs = new Bundle();
+        captureTerminalSharedElementState(sharedElements, sharedElementArgs);
+
+        ActivityOptions.SharedElementSource sharedElementSource
+                = new ActivityOptions.SharedElementSource() {
             @Override
-            public int getTextureId() {
-                // TODO: move shared elements to a layer and return the texture id
-                recurseHideExitingSharedElements(mContentParent);
-                return 0;
+            public Bundle getSharedElementExitState() {
+                return sharedElementArgs;
+            }
+
+            @Override
+            public void acceptedSharedElements(ArrayList<String> sharedElementNames) {
+                if (sharedElementNames.size() == sharedElements.size()) {
+                    return; // They were all accepted
+                }
+                Transition transition = mTransitionManager.getExitTransition(mContentScene).clone();
+                TransitionManager.beginDelayedTransition(mDecor, transition);
+                for (String name: sharedElements.keySet()) {
+                    if (!sharedElementNames.contains(name)) {
+                        sharedElements.get(name).setVisibility(View.INVISIBLE);
+                    }
+                }
+                sharedElements.keySet().retainAll(sharedElementNames);
+            }
+
+            @Override
+            public void hideSharedElements() {
+                if (sharedElements != null) {
+                    setViewVisibility(sharedElements.values(), View.INVISIBLE);
+                }
+            }
+        };
+
+        activityOptions.updateSceneTransitionAnimation(
+                exitTransition, sharedElementTransition, sharedElementSource);
+    }
+
+    private void captureTerminalSharedElementState(final Map<String, View> sharedElements,
+            final Bundle sharedElementArgs) {
+        mDecor.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+            @Override
+            public boolean onPreDraw() {
+                mDecor.getViewTreeObserver().removeOnPreDrawListener(this);
+                int[] tempLoc = new int[2];
+                for (String name : sharedElements.keySet()) {
+                    View sharedElement = sharedElements.get(name);
+                    captureSharedElementState(sharedElement, name, sharedElementArgs, tempLoc);
+                }
+                return true;
             }
         });
-        ViewGroup sceneRoot = getContentScene().getSceneRoot();
-        TransitionManager.beginDelayedTransition(sceneRoot, transition);
-        recurseExitNonSharedElements(mContentParent);
     }
 
-    private static void recurseExitNonSharedElements(ViewGroup viewGroup) {
-        int numChildren = viewGroup.getChildCount();
-        for (int i = 0; i < numChildren; i++) {
-            View child = viewGroup.getChildAt(i);
-            if (child.getSharedElementName() != null || (child.getVisibility() != View.VISIBLE)) {
-                continue;
-            }
-            if (child instanceof ViewGroup && !((ViewGroup)child).isTransitionGroup()) {
-                recurseExitNonSharedElements((ViewGroup) child);
+    private static Transition cloneAndSetTransitionTargets(Transition transition,
+            List<View> views, boolean add) {
+        transition = transition.clone();
+        if (!transition.getTargetIds().isEmpty() || !transition.getTargets().isEmpty()) {
+            TransitionSet set = new TransitionSet();
+            set.addTransition(transition);
+            transition = set;
+        }
+        for (View view: views) {
+            if (add) {
+                transition.addTarget(view);
             } else {
-                child.setVisibility(View.INVISIBLE);
+                transition.excludeTarget(view, true);
             }
         }
+        return transition;
+    }
+
+    private static void setViewVisibility(Collection<View> views, int visibility) {
+        for (View view : views) {
+            view.setVisibility(visibility);
+        }
     }
 
-    private static void recurseHideViews(ViewGroup viewGroup, ArrayList<View> nonSharedElements,
-            ArrayList<View> sharedElements) {
-        int numChildren = viewGroup.getChildCount();
-        for (int i = 0; i < numChildren; i++) {
-            View child = viewGroup.getChildAt(i);
-            if (child.getVisibility() != View.VISIBLE) {
-                continue;
-            }
-            if (child.getSharedElementName() != null) {
-                sharedElements.add(child);
-                child.setVisibility(View.INVISIBLE);
-            } else if (child instanceof ViewGroup && !((ViewGroup)child).isTransitionGroup()) {
-                recurseHideViews((ViewGroup) child, nonSharedElements, sharedElements);
-            } else {
-                nonSharedElements.add(child);
-                child.setVisibility(View.INVISIBLE);
-            }
+    /**
+     * Sets the captured values from a previous
+     * {@link #captureSharedElementState(android.view.View, String, android.os.Bundle, int[])}
+     * @param view The View to apply placement changes to.
+     * @param name The shared element name given from the source Activity.
+     * @param transitionArgs A <code>Bundle</code> containing all placementinformation for named
+     *                       shared elements in the scene.
+     * @param tempLoc A temporary int[2] for capturing the current location of views.
+     */
+    private static void setSharedElementState(View view, String name, Bundle transitionArgs,
+            int[] tempLoc) {
+        Bundle sharedElementBundle = transitionArgs.getBundle(name);
+        if (sharedElementBundle == null) {
+            return;
         }
+
+        int x = sharedElementBundle.getInt(KEY_SCREEN_X);
+        view.getLocationOnScreen(tempLoc);
+        int offsetX = x - tempLoc[0];
+        view.offsetLeftAndRight(offsetX);
+
+        int width = sharedElementBundle.getInt(KEY_WIDTH);
+        view.setRight(view.getLeft() + width);
+
+        int y = sharedElementBundle.getInt(KEY_SCREEN_Y);
+        int offsetY = y - tempLoc[1];
+        view.offsetTopAndBottom(offsetY);
+
+        int height = sharedElementBundle.getInt(KEY_HEIGHT);
+        view.setBottom(view.getTop() + height);
+
+        float z = sharedElementBundle.getFloat(KEY_TRANSLATION_Z);
+        view.setTranslationZ(z);
     }
 
-    private static void recurseHideExitingSharedElements(ViewGroup viewGroup) {
-        int numChildren = viewGroup.getChildCount();
-        for (int i = 0; i < numChildren; i++) {
-            View child = viewGroup.getChildAt(i);
-            if (child.getVisibility() != View.VISIBLE) {
-                continue;
-            }
-            if (child.getSharedElementName() != null) {
-                child.setVisibility(View.INVISIBLE);
-            } else if (child instanceof ViewGroup) {
-                ViewGroup childViewGroup = (ViewGroup) child;
-                recurseHideExitingSharedElements(childViewGroup);
-            }
-        }
+    /**
+     * Captures placement information for Views with a shared element name for
+     * Activity Transitions.
+     * @param view The View to capture the placement information for.
+     * @param name The shared element name in the target Activity to apply the placement
+     *             information for.
+     * @param transitionArgs Bundle to store shared element placement information.
+     * @param tempLoc A temporary int[2] for capturing the current location of views.
+     * @see #setSharedElementState(android.view.View, String, android.os.Bundle, int[])
+     */
+    private static void captureSharedElementState(View view, String name, Bundle transitionArgs,
+            int[] tempLoc) {
+        Bundle sharedElementBundle = new Bundle();
+        view.getLocationOnScreen(tempLoc);
+        float scaleX = view.getScaleX();
+        sharedElementBundle.putInt(KEY_SCREEN_X, tempLoc[0]);
+        int width = Math.round(view.getWidth() * scaleX);
+        sharedElementBundle.putInt(KEY_WIDTH, width);
+
+        float scaleY = view.getScaleY();
+        sharedElementBundle.putInt(KEY_SCREEN_Y, tempLoc[1]);
+        int height= Math.round(view.getHeight() * scaleY);
+        sharedElementBundle.putInt(KEY_HEIGHT, height);
+
+        sharedElementBundle.putFloat(KEY_TRANSLATION_Z, view.getTranslationZ());
+
+        sharedElementBundle.putString(KEY_NAME, view.getSharedElementName());
+
+        transitionArgs.putBundle(name, sharedElementBundle);
     }
 
     /**
@@ -4080,46 +4301,57 @@
         private boolean mAllDone;
         private Handler mHandler = new Handler();
         private boolean mEnterTransitionStarted;
-        private ArrayList<View> mSharedElements = new ArrayList<View>();
+        private ArrayMap<String, View> mSharedElementTargets = new ArrayMap<String, View>();
+        private ArrayList<View> mEnteringViews = new ArrayList<View>();
 
         public EnterScene() {
             mSceneTransitionListener.nullPendingTransition();
             Drawable background = getDecorView().getBackground();
             if (background != null) {
-                setBackgroundDrawable(null);
                 background.setAlpha(0);
-                setBackgroundDrawable(background);
+                mDecor.drawableChanged();
             }
             mSceneTransitionListener.convertToTranslucent();
         }
 
         @Override
         public boolean onPreDraw() {
-            ViewTreeObserver observer = mContentParent.getViewTreeObserver();
+            ViewTreeObserver observer = mDecor.getViewTreeObserver();
             observer.removeOnPreDrawListener(this);
             if (!mEnterTransitionStarted && mSceneTransitionListener != null) {
                 mEnterTransitionStarted = true;
-                ArrayList<View> enteringViews = new ArrayList<View>();
-                recurseHideViews(mContentParent, enteringViews, mSharedElements);
-                Transition transition = getTransitionManager().getNamedTransition("null",
-                        mContentScene);
-                if (transition == null) {
-                    transition = TransitionManager.getDefaultTransition().clone();
+                mDecor.captureTransitioningViews(mEnteringViews);
+                ArrayList<String> sharedElementNames = mActivityOptions.getSharedElementNames();
+                if (sharedElementNames != null) {
+                    mDecor.findSharedElements(mSharedElementTargets);
+                    if (mSharedElementsMap != null) {
+                        for (Map.Entry<String, String> entry : mSharedElementsMap.entrySet()) {
+                            View sharedElement = mSharedElementTargets.remove(entry.getValue());
+                            if (sharedElement != null) {
+                                mSharedElementTargets.put(entry.getKey(), sharedElement);
+                            }
+                        }
+                    }
+                    mSharedElementTargets.keySet().retainAll(sharedElementNames);
+                    mEnteringViews.removeAll(mSharedElementTargets.values());
                 }
-                TransitionManager.beginDelayedTransition(mContentParent, transition);
-                for (View hidden : enteringViews) {
-                    hidden.setVisibility(View.VISIBLE);
+
+                setViewVisibility(mEnteringViews, View.INVISIBLE);
+                setViewVisibility(mSharedElementTargets.values(), View.INVISIBLE);
+                if (mTriggerEarly) {
+                    beginEnterScene();
                 }
                 observer.addOnPreDrawListener(this);
             } else {
                 mHandler.postDelayed(this, MAX_TRANSITION_START_WAIT);
-                mActivityOptions.dispatchSceneTransitionStarted(this);
+                mActivityOptions.dispatchSceneTransitionStarted(this,
+                        new ArrayList<String>(mSharedElementTargets.keySet()));
             }
             return true;
         }
 
         public void start() {
-            ViewTreeObserver observer = mContentParent.getViewTreeObserver();
+            ViewTreeObserver observer = mDecor.getViewTreeObserver();
             observer.addOnPreDrawListener(this);
         }
 
@@ -4129,25 +4361,43 @@
         }
 
         @Override
-        public void sharedElementTransitionComplete() {
+        public void sharedElementTransitionComplete(Bundle transitionArgs) {
             if (!mSharedElementReadyReceived) {
                 mSharedElementReadyReceived = true;
                 mHandler.removeCallbacks(this);
                 mHandler.postDelayed(this, MAX_TRANSITION_FINISH_WAIT);
-                for (View sharedElement: mSharedElements) {
-                    sharedElement.setVisibility(View.VISIBLE);
-                }
-                mSharedElements.clear();
-                mContentParent.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
-                    @Override
-                    public boolean onPreDraw() {
-                        mContentParent.getViewTreeObserver().removeOnPreDrawListener(this);
-                        mSceneTransitionListener.enterSharedElement(
-                                mActivityOptions.getSceneTransitionArgs());
-                        return false;
+                if (!mSharedElementTargets.isEmpty()) {
+                    Transition transition = getTransitionManager().getEnterTransition(
+                            mContentScene);
+                    if (transition == null) {
+                        transition = TransitionManager.getDefaultTransition();
                     }
-                });
-                if (mFadeEarly) {
+                    transition = transition.clone();
+                    if (transitionArgs == null) {
+                        TransitionManager.beginDelayedTransition(mDecor, transition);
+                        setViewVisibility(mSharedElementTargets.values(), View.VISIBLE);
+                    } else {
+                        int[] tempLoc = new int[2];
+                        for (Map.Entry<String, View> entry: mSharedElementTargets.entrySet()) {
+                            setSharedElementState(entry.getValue(), entry.getKey(), transitionArgs,
+                                    tempLoc);
+                        }
+                        setViewVisibility(mSharedElementTargets.values(), View.VISIBLE);
+                        mSceneTransitionListener.sharedElementStart(transition);
+                        mDecor.getViewTreeObserver().addOnPreDrawListener(
+                                new ViewTreeObserver.OnPreDrawListener() {
+                                    @Override
+                                    public boolean onPreDraw() {
+                                        mDecor.getViewTreeObserver().removeOnPreDrawListener(this);
+                                        mSceneTransitionListener.sharedElementEnd();
+                                        mActivityOptions.dispatchSharedElementsReady();
+                                        return true;
+                                    }
+                                });
+                        TransitionManager.beginDelayedTransition(mDecor, transition);
+                    }
+                }
+                if (mTriggerEarly) {
                     fadeInBackground();
                 }
             }
@@ -4170,9 +4420,10 @@
                 return;
             }
             mAllDone = true;
-            sharedElementTransitionComplete();
+            sharedElementTransitionComplete(null);
             mHandler.removeCallbacks(this);
-            if (!mFadeEarly) {
+            if (!mTriggerEarly) {
+                beginEnterScene();
                 fadeInBackground();
             }
         }
@@ -4193,5 +4444,14 @@
         @Override
         public void onAnimationRepeat(Animator animation) {
         }
+
+        private void beginEnterScene() {
+            Transition transition = getTransitionManager().getEnterTransition(mContentScene);
+            if (transition == null) {
+                transition = TransitionManager.getDefaultTransition().clone();
+            }
+            TransitionManager.beginDelayedTransition(mDecor, transition);
+            setViewVisibility(mEnteringViews, View.VISIBLE);
+        }
     }
 }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 7886f5d..9ecb917 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -286,6 +286,7 @@
     int mUserRotation = Surface.ROTATION_0;
     boolean mAccelerometerDefault;
 
+    boolean mSupportAutoRotation;
     int mAllowAllRotations = -1;
     boolean mCarDockEnablesAccelerometer;
     boolean mDeskDockEnablesAccelerometer;
@@ -372,6 +373,7 @@
     static final Rect mTmpNavigationFrame = new Rect();
 
     WindowState mTopFullscreenOpaqueWindowState;
+    boolean mHideWindowBehindKeyguard;
     boolean mTopIsFullscreen;
     boolean mForceStatusBar;
     boolean mForceStatusBarFromKeyguard;
@@ -585,13 +587,15 @@
      * screen is switched off.
      */
     boolean needSensorRunningLp() {
-        if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
-                || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
-                || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
-                || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
-            // If the application has explicitly requested to follow the
-            // orientation, then we need to turn the sensor or.
-            return true;
+        if (mSupportAutoRotation) {
+            if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
+                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
+                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
+                    || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
+                // If the application has explicitly requested to follow the
+                // orientation, then we need to turn the sensor on.
+                return true;
+            }
         }
         if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
                 (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
@@ -612,7 +616,7 @@
             // still be turned off when the screen is off.)
             return false;
         }
-        return true;
+        return mSupportAutoRotation;
     }
 
     /*
@@ -877,6 +881,8 @@
         mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                 "PhoneWindowManager.mBroadcastWakeLock");
         mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
+        mSupportAutoRotation = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_supportAutoRotation);
         mLidOpenRotation = readRotation(
                 com.android.internal.R.integer.config_lidOpenRotation);
         mCarDockRotation = readRotation(
@@ -1661,7 +1667,8 @@
             return view.getParent() != null ? view : null;
         } catch (WindowManager.BadTokenException e) {
             // ignore
-            Log.w(TAG, appToken + " already running, starting window not displayed");
+            Log.w(TAG, appToken + " already running, starting window not displayed. " +
+                    e.getMessage());
         } catch (RuntimeException e) {
             // don't crash if something else bad happens, for example a
             // failure loading resources because we are loading from an app
@@ -3354,6 +3361,7 @@
     @Override
     public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
         mTopFullscreenOpaqueWindowState = null;
+        mHideWindowBehindKeyguard = false;
         mForceStatusBar = false;
         mForceStatusBarFromKeyguard = false;
         mForcingShowNavBar = false;
@@ -3390,7 +3398,7 @@
             if (attrs.type == TYPE_KEYGUARD) {
                 mShowingLockscreen = true;
             }
-            boolean applyWindow = attrs.type >= FIRST_APPLICATION_WINDOW
+            boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
                     && attrs.type <= LAST_APPLICATION_WINDOW;
             if (attrs.type == TYPE_DREAM) {
                 // If the lockscreen was showing when the dream started then wait
@@ -3398,30 +3406,35 @@
                 if (!mDreamingLockscreen
                         || (win.isVisibleLw() && win.hasDrawnLw())) {
                     mShowingDream = true;
-                    applyWindow = true;
+                    appWindow = true;
                 }
             }
-            if (applyWindow
-                    && attrs.x == 0 && attrs.y == 0
-                    && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
-                    && attrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
-                if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
-                mTopFullscreenOpaqueWindowState = win;
-                if ((fl & FLAG_SHOW_WHEN_LOCKED) != 0) {
-                    if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mHideLockScreen to true by win " + win);
-                    mHideLockScreen = true;
-                    mForceStatusBarFromKeyguard = false;
-                }
-                if ((fl & FLAG_DISMISS_KEYGUARD) != 0
-                        && mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
-                    if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mDismissKeyguard true by win " + win);
-                    mDismissKeyguard = mWinDismissingKeyguard == win ?
-                            DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
-                    mWinDismissingKeyguard = win;
-                    mForceStatusBarFromKeyguard = mShowingLockscreen && isKeyguardSecure();
-                }
-                if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
-                    mAllowLockscreenWhenOn = true;
+
+            final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0;
+            if (appWindow) {
+                if (attrs.x == 0 && attrs.y == 0
+                        && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
+                        && attrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
+                    if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
+                    mTopFullscreenOpaqueWindowState = win;
+                    if (showWhenLocked && !mHideWindowBehindKeyguard) {
+                        if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mHideLockScreen to true by win " + win);
+                        mHideLockScreen = true;
+                        mForceStatusBarFromKeyguard = false;
+                    }
+                    if ((fl & FLAG_DISMISS_KEYGUARD) != 0
+                            && mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
+                        if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mDismissKeyguard true by win " + win);
+                        mDismissKeyguard = mWinDismissingKeyguard == win ?
+                                DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
+                        mWinDismissingKeyguard = win;
+                        mForceStatusBarFromKeyguard = mShowingLockscreen && isKeyguardSecure();
+                    }
+                    if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
+                        mAllowLockscreenWhenOn = true;
+                    }
+                } else if (!showWhenLocked) {
+                    mHideWindowBehindKeyguard = true;
                 }
             }
         }
@@ -3508,7 +3521,7 @@
         if (mKeyguard != null) {
             if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
                     + mHideLockScreen);
-            if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardDelegate.isSecure()) {
+            if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !isKeyguardSecure()) {
                 if (mKeyguard.hideLw(true)) {
                     changes |= FINISH_LAYOUT_REDO_LAYOUT
                             | FINISH_LAYOUT_REDO_CONFIG
@@ -3796,7 +3809,9 @@
                                                 mKeyguardDelegate.isShowingAndNotHidden() :
                                                 mKeyguardDelegate.isShowing()));
 
-        if (keyCode == KeyEvent.KEYCODE_POWER) {
+        if (keyCode == KeyEvent.KEYCODE_POWER
+                || keyCode == KeyEvent.KEYCODE_SLEEP
+                || keyCode == KeyEvent.KEYCODE_WAKEUP) {
             policyFlags |= WindowManagerPolicy.FLAG_WAKE;
         }
 
@@ -3996,6 +4011,18 @@
                 break;
             }
 
+            case KeyEvent.KEYCODE_SLEEP: {
+                result &= ~ACTION_PASS_TO_USER;
+                mPowerManager.goToSleep(event.getEventTime());
+                isWakeKey = false;
+                break;
+            }
+
+            case KeyEvent.KEYCODE_WAKEUP: {
+                result &= ~ACTION_PASS_TO_USER;
+                break;
+            }
+
             case KeyEvent.KEYCODE_MEDIA_PLAY:
             case KeyEvent.KEYCODE_MEDIA_PAUSE:
             case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
@@ -4480,6 +4507,10 @@
             } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
                 // Application just wants to remain locked in the last rotation.
                 preferredRotation = lastRotation;
+            } else if (!mSupportAutoRotation) {
+                // If we don't support auto-rotation then bail out here and ignore
+                // the sensor and any rotation lock settings.
+                preferredRotation = -1;
             } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
                             && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
                                     || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
@@ -5296,6 +5327,7 @@
             pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
                     pw.println(mLastFocusNeedsMenu);
         }
+        pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation);
         pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
                 pw.print(" mDockMode="); pw.print(mDockMode);
                 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
diff --git a/preloaded-classes b/preloaded-classes
index 4d79e4b..35c52ad 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -400,7 +400,6 @@
 android.ddm.DdmHandleThread
 android.ddm.DdmHandleViewDebug
 android.ddm.DdmRegister
-android.debug.JNITest
 android.drm.DrmManagerClient
 android.emoji.EmojiFactory
 android.graphics.AvoidXfermode
@@ -661,7 +660,6 @@
 android.net.wifi.IWifiManager$Stub$Proxy
 android.net.wifi.WifiManager
 android.net.wifi.WifiManager$ServiceHandler
-android.net.wifi.WifiNative
 android.nfc.IAppCallback
 android.nfc.IAppCallback$Stub
 android.nfc.INfcAdapter
@@ -984,10 +982,7 @@
 android.view.FocusFinder$SequentialFocusComparator
 android.view.GLES20Canvas
 android.view.GLES20Canvas$CanvasFinalizer
-android.view.GLES20Layer
-android.view.GLES20Layer$Finalizer
 android.view.GLES20RecordingCanvas
-android.view.GLES20RenderLayer
 android.view.GestureDetector
 android.view.GestureDetector$GestureHandler
 android.view.GestureDetector$OnDoubleTapListener
@@ -997,12 +992,6 @@
 android.view.HardwareCanvas
 android.view.HardwareLayer
 android.view.HardwareRenderer
-android.view.HardwareRenderer$Gl20Renderer
-android.view.HardwareRenderer$Gl20Renderer$1
-android.view.HardwareRenderer$Gl20Renderer$2
-android.view.HardwareRenderer$Gl20Renderer$Gl20RendererEglContext
-android.view.HardwareRenderer$GlRenderer
-android.view.HardwareRenderer$GlRenderer$FunctorsRunnable
 android.view.HardwareRenderer$HardwareDrawCallbacks
 android.view.IRotationWatcher
 android.view.IRotationWatcher$Stub
@@ -1113,7 +1102,6 @@
 android.view.ViewParent
 android.view.ViewRootImpl
 android.view.ViewRootImpl$3
-android.view.ViewRootImpl$4
 android.view.ViewRootImpl$AccessibilityInteractionConnectionManager
 android.view.ViewRootImpl$AsyncInputStage
 android.view.ViewRootImpl$ConsumeBatchedInputRunnable
@@ -1452,14 +1440,6 @@
 com.android.internal.view.RootViewSurfaceTaker
 com.android.internal.view.menu.ActionMenuItem
 com.android.internal.view.menu.ActionMenuItemView
-com.android.internal.view.menu.ActionMenuPresenter
-com.android.internal.view.menu.ActionMenuPresenter$OverflowMenuButton
-com.android.internal.view.menu.ActionMenuPresenter$PopupPresenterCallback
-com.android.internal.view.menu.ActionMenuPresenter$SavedState
-com.android.internal.view.menu.ActionMenuPresenter$SavedState$1
-com.android.internal.view.menu.ActionMenuView
-com.android.internal.view.menu.ActionMenuView$ActionMenuChildView
-com.android.internal.view.menu.ActionMenuView$LayoutParams
 com.android.internal.view.menu.BaseMenuPresenter
 com.android.internal.view.menu.ListMenuItemView
 com.android.internal.view.menu.MenuBuilder
@@ -1700,7 +1680,6 @@
 com.android.org.conscrypt.OpenSSLX509CertificateFactory$Parser
 com.android.org.conscrypt.ProtocolVersion
 com.android.org.conscrypt.SSLClientSessionCache
-com.android.org.conscrypt.SSLContextImpl
 com.android.org.conscrypt.SSLParametersImpl
 com.android.org.conscrypt.ServerSessionContext
 com.android.org.conscrypt.TrustManagerFactoryImpl
@@ -1887,7 +1866,6 @@
 java.lang.ThreadLocal$Values
 java.lang.Throwable
 java.lang.TypeNotPresentException
-java.lang.UnsafeByteSequence
 java.lang.UnsatisfiedLinkError
 java.lang.UnsupportedOperationException
 java.lang.VMClassLoader
@@ -2196,8 +2174,6 @@
 java.util.concurrent.Callable
 java.util.concurrent.CancellationException
 java.util.concurrent.ConcurrentHashMap
-java.util.concurrent.ConcurrentHashMap$HashEntry
-java.util.concurrent.ConcurrentHashMap$HashIterator
 java.util.concurrent.ConcurrentHashMap$Segment
 java.util.concurrent.ConcurrentLinkedQueue
 java.util.concurrent.ConcurrentLinkedQueue$Node
@@ -2257,7 +2233,6 @@
 java.util.jar.Attributes$Name
 java.util.jar.JarEntry
 java.util.jar.JarFile
-java.util.jar.JarFile$1JarFileEnumerator
 java.util.jar.JarVerifier
 java.util.jar.Manifest
 java.util.logging.ConsoleHandler
@@ -2382,7 +2357,6 @@
 libcore.io.StructUtsname
 libcore.math.MathUtils
 libcore.net.MimeUtils
-libcore.net.RawSocket
 libcore.net.UriCodec
 libcore.net.http.HttpDate
 libcore.net.http.HttpDate$1
diff --git a/rs/java/android/renderscript/BaseObj.java b/rs/java/android/renderscript/BaseObj.java
index b386dd7..1372ab7 100644
--- a/rs/java/android/renderscript/BaseObj.java
+++ b/rs/java/android/renderscript/BaseObj.java
@@ -181,6 +181,10 @@
         if (this == obj)
             return true;
 
+        if (obj == null) {
+            return false;
+        }
+
         if (getClass() != obj.getClass()) {
             return false;
         }
diff --git a/rs/java/android/renderscript/Element.java b/rs/java/android/renderscript/Element.java
index 93e839e..55b671d 100644
--- a/rs/java/android/renderscript/Element.java
+++ b/rs/java/android/renderscript/Element.java
@@ -800,8 +800,6 @@
     void updateFromNative() {
         super.updateFromNative();
 
-        // FIXME: updateFromNative is broken in JNI for 64-bit
-
         // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements
         int[] dataBuffer = new int[5];
         mRS.nElementGetNativeData(getID(mRS), dataBuffer);
@@ -828,7 +826,7 @@
             mArraySizes = new int[numSubElements];
             mOffsetInBytes = new int[numSubElements];
 
-            int[] subElementIds = new int[numSubElements];
+            long[] subElementIds = new long[numSubElements];
             mRS.nElementGetSubElements(getID(mRS), subElementIds, mElementNames, mArraySizes);
             for(int i = 0; i < numSubElements; i ++) {
                 mElements[i] = new Element(subElementIds[i], mRS);
@@ -1087,10 +1085,9 @@
             java.lang.System.arraycopy(mElementNames, 0, sin, 0, mCount);
             java.lang.System.arraycopy(mArraySizes, 0, asin, 0, mCount);
 
-            // FIXME: broken for 64-bit
-            int[] ids = new int[ein.length];
+            long[] ids = new long[ein.length];
             for (int ct = 0; ct < ein.length; ct++ ) {
-                ids[ct] = (int)ein[ct].getID(mRS);
+                ids[ct] = ein[ct].getID(mRS);
             }
             long id = mRS.nElementCreate2(ids, sin, asin);
             return new Element(id, mRS, ein, sin, asin);
diff --git a/rs/java/android/renderscript/Mesh.java b/rs/java/android/renderscript/Mesh.java
index a4ecc38..1a5dc9e 100644
--- a/rs/java/android/renderscript/Mesh.java
+++ b/rs/java/android/renderscript/Mesh.java
@@ -152,8 +152,8 @@
         int vtxCount = mRS.nMeshGetVertexBufferCount(getID(mRS));
         int idxCount = mRS.nMeshGetIndexCount(getID(mRS));
 
-        int[] vtxIDs = new int[vtxCount];
-        int[] idxIDs = new int[idxCount];
+        long[] vtxIDs = new long[vtxCount];
+        long[] idxIDs = new long[idxCount];
         int[] primitives = new int[idxCount];
 
         mRS.nMeshGetVertices(getID(mRS), vtxIDs, vtxCount);
@@ -348,8 +348,8 @@
         **/
         public Mesh create() {
             mRS.validate();
-            int[] vtx = new int[mVertexTypeCount];
-            int[] idx = new int[mIndexTypes.size()];
+            long[] vtx = new long[mVertexTypeCount];
+            long[] idx = new long[mIndexTypes.size()];
             int[] prim = new int[mIndexTypes.size()];
 
             Allocation[] vertexBuffers = new Allocation[mVertexTypeCount];
@@ -365,7 +365,7 @@
                     alloc = Allocation.createSized(mRS, entry.e, entry.size, mUsage);
                 }
                 vertexBuffers[ct] = alloc;
-                vtx[ct] = (int)alloc.getID(mRS);
+                vtx[ct] = alloc.getID(mRS);
             }
 
             for(int ct = 0; ct < mIndexTypes.size(); ct ++) {
@@ -380,7 +380,7 @@
                 indexBuffers[ct] = alloc;
                 primitives[ct] = entry.prim;
 
-                idx[ct] = (int)allocID;
+                idx[ct] = allocID;
                 prim[ct] = entry.prim.mID;
             }
 
@@ -504,8 +504,8 @@
         public Mesh create() {
             mRS.validate();
 
-            int[] vtx = new int[mVertexTypeCount];
-            int[] idx = new int[mIndexTypes.size()];
+            long[] vtx = new long[mVertexTypeCount];
+            long[] idx = new long[mIndexTypes.size()];
             int[] prim = new int[mIndexTypes.size()];
 
             Allocation[] indexBuffers = new Allocation[mIndexTypes.size()];
@@ -515,7 +515,7 @@
             for(int ct = 0; ct < mVertexTypeCount; ct ++) {
                 Entry entry = mVertexTypes[ct];
                 vertexBuffers[ct] = entry.a;
-                vtx[ct] = (int)entry.a.getID(mRS);
+                vtx[ct] = entry.a.getID(mRS);
             }
 
             for(int ct = 0; ct < mIndexTypes.size(); ct ++) {
@@ -524,7 +524,7 @@
                 indexBuffers[ct] = entry.a;
                 primitives[ct] = entry.prim;
 
-                idx[ct] = (int)allocID;
+                idx[ct] = allocID;
                 prim[ct] = entry.prim.mID;
             }
 
diff --git a/rs/java/android/renderscript/ProgramFragment.java b/rs/java/android/renderscript/ProgramFragment.java
index 2704130..5f71bd1 100644
--- a/rs/java/android/renderscript/ProgramFragment.java
+++ b/rs/java/android/renderscript/ProgramFragment.java
@@ -62,25 +62,25 @@
          */
         public ProgramFragment create() {
             mRS.validate();
-            int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
+            long[] tmp = new long[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
             String[] texNames = new String[mTextureCount];
             int idx = 0;
 
             for (int i=0; i < mInputCount; i++) {
                 tmp[idx++] = ProgramParam.INPUT.mID;
-                tmp[idx++] = (int)mInputs[i].getID(mRS);
+                tmp[idx++] = mInputs[i].getID(mRS);
             }
             for (int i=0; i < mOutputCount; i++) {
                 tmp[idx++] = ProgramParam.OUTPUT.mID;
-                tmp[idx++] = (int)mOutputs[i].getID(mRS);
+                tmp[idx++] = mOutputs[i].getID(mRS);
             }
             for (int i=0; i < mConstantCount; i++) {
                 tmp[idx++] = ProgramParam.CONSTANT.mID;
-                tmp[idx++] = (int)mConstants[i].getID(mRS);
+                tmp[idx++] = mConstants[i].getID(mRS);
             }
             for (int i=0; i < mTextureCount; i++) {
                 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
-                tmp[idx++] = (int)mTextureTypes[i].mID;
+                tmp[idx++] = mTextureTypes[i].mID;
                 texNames[i] = mTextureNames[i];
             }
 
diff --git a/rs/java/android/renderscript/ProgramFragmentFixedFunction.java b/rs/java/android/renderscript/ProgramFragmentFixedFunction.java
index e1c35c5..2b647c76 100644
--- a/rs/java/android/renderscript/ProgramFragmentFixedFunction.java
+++ b/rs/java/android/renderscript/ProgramFragmentFixedFunction.java
@@ -49,25 +49,25 @@
          */
         public ProgramFragmentFixedFunction create() {
             mRS.validate();
-            int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
+            long[] tmp = new long[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
             String[] texNames = new String[mTextureCount];
             int idx = 0;
 
             for (int i=0; i < mInputCount; i++) {
                 tmp[idx++] = ProgramParam.INPUT.mID;
-                tmp[idx++] = (int)mInputs[i].getID(mRS);
+                tmp[idx++] = mInputs[i].getID(mRS);
             }
             for (int i=0; i < mOutputCount; i++) {
                 tmp[idx++] = ProgramParam.OUTPUT.mID;
-                tmp[idx++] = (int)mOutputs[i].getID(mRS);
+                tmp[idx++] = mOutputs[i].getID(mRS);
             }
             for (int i=0; i < mConstantCount; i++) {
                 tmp[idx++] = ProgramParam.CONSTANT.mID;
-                tmp[idx++] = (int)mConstants[i].getID(mRS);
+                tmp[idx++] = mConstants[i].getID(mRS);
             }
             for (int i=0; i < mTextureCount; i++) {
                 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
-                tmp[idx++] = (int)mTextureTypes[i].mID;
+                tmp[idx++] = mTextureTypes[i].mID;
                 texNames[i] = mTextureNames[i];
             }
 
diff --git a/rs/java/android/renderscript/ProgramVertex.java b/rs/java/android/renderscript/ProgramVertex.java
index d194ba9..0d7e2d9 100644
--- a/rs/java/android/renderscript/ProgramVertex.java
+++ b/rs/java/android/renderscript/ProgramVertex.java
@@ -122,25 +122,25 @@
          */
         public ProgramVertex create() {
             mRS.validate();
-            int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
+            long[] tmp = new long[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
             String[] texNames = new String[mTextureCount];
             int idx = 0;
 
             for (int i=0; i < mInputCount; i++) {
                 tmp[idx++] = ProgramParam.INPUT.mID;
-                tmp[idx++] = (int)mInputs[i].getID(mRS);
+                tmp[idx++] = mInputs[i].getID(mRS);
             }
             for (int i=0; i < mOutputCount; i++) {
                 tmp[idx++] = ProgramParam.OUTPUT.mID;
-                tmp[idx++] = (int)mOutputs[i].getID(mRS);
+                tmp[idx++] = mOutputs[i].getID(mRS);
             }
             for (int i=0; i < mConstantCount; i++) {
                 tmp[idx++] = ProgramParam.CONSTANT.mID;
-                tmp[idx++] = (int)mConstants[i].getID(mRS);
+                tmp[idx++] = mConstants[i].getID(mRS);
             }
             for (int i=0; i < mTextureCount; i++) {
                 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
-                tmp[idx++] = (int)mTextureTypes[i].mID;
+                tmp[idx++] = mTextureTypes[i].mID;
                 texNames[i] = mTextureNames[i];
             }
 
diff --git a/rs/java/android/renderscript/ProgramVertexFixedFunction.java b/rs/java/android/renderscript/ProgramVertexFixedFunction.java
index 2d281b8..5173af2 100644
--- a/rs/java/android/renderscript/ProgramVertexFixedFunction.java
+++ b/rs/java/android/renderscript/ProgramVertexFixedFunction.java
@@ -75,25 +75,25 @@
          */
         public ProgramVertexFixedFunction create() {
             mRS.validate();
-            int[] tmp = new int[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
+            long[] tmp = new long[(mInputCount + mOutputCount + mConstantCount + mTextureCount) * 2];
             String[] texNames = new String[mTextureCount];
             int idx = 0;
 
             for (int i=0; i < mInputCount; i++) {
                 tmp[idx++] = ProgramParam.INPUT.mID;
-                tmp[idx++] = (int)mInputs[i].getID(mRS);
+                tmp[idx++] = mInputs[i].getID(mRS);
             }
             for (int i=0; i < mOutputCount; i++) {
                 tmp[idx++] = ProgramParam.OUTPUT.mID;
-                tmp[idx++] = (int)mOutputs[i].getID(mRS);
+                tmp[idx++] = mOutputs[i].getID(mRS);
             }
             for (int i=0; i < mConstantCount; i++) {
                 tmp[idx++] = ProgramParam.CONSTANT.mID;
-                tmp[idx++] = (int)mConstants[i].getID(mRS);
+                tmp[idx++] = mConstants[i].getID(mRS);
             }
             for (int i=0; i < mTextureCount; i++) {
                 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
-                tmp[idx++] = (int)mTextureTypes[i].mID;
+                tmp[idx++] = mTextureTypes[i].mID;
                 texNames[i] = mTextureNames[i];
             }
 
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 89dba9f..d4fa5a7 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -303,8 +303,8 @@
         validate();
         return rsnElementCreate(mContext, type, kind, norm, vecSize);
     }
-    native long rsnElementCreate2(long con, int[]elements, String[] names, int[] arraySizes);
-    synchronized long nElementCreate2(int[] elements, String[] names, int[] arraySizes) {
+    native long rsnElementCreate2(long con, long[] elements, String[] names, int[] arraySizes);
+    synchronized long nElementCreate2(long[] elements, String[] names, int[] arraySizes) {
         validate();
         return rsnElementCreate2(mContext, elements, names, arraySizes);
     }
@@ -314,8 +314,8 @@
         rsnElementGetNativeData(mContext, id, elementData);
     }
     native void rsnElementGetSubElements(long con, long id,
-                                         int[] IDs, String[] names, int[] arraySizes);
-    synchronized void nElementGetSubElements(long id, int[] IDs, String[] names, int[] arraySizes) {
+                                         long[] IDs, String[] names, int[] arraySizes);
+    synchronized void nElementGetSubElements(long id, long[] IDs, String[] names, int[] arraySizes) {
         validate();
         rsnElementGetSubElements(mContext, id, IDs, names, arraySizes);
     }
@@ -325,14 +325,14 @@
         validate();
         return rsnTypeCreate(mContext, eid, x, y, z, mips, faces, yuv);
     }
-    native void rsnTypeGetNativeData(long con, long id, int[] typeData);
-    synchronized void nTypeGetNativeData(long id, int[] typeData) {
+    native void rsnTypeGetNativeData(long con, long id, long[] typeData);
+    synchronized void nTypeGetNativeData(long id, long[] typeData) {
         validate();
         rsnTypeGetNativeData(mContext, id, typeData);
     }
 
-    native long rsnAllocationCreateTyped(long con, long type, int mip, int usage, int pointer);
-    synchronized long nAllocationCreateTyped(long type, int mip, int usage, int pointer) {
+    native long rsnAllocationCreateTyped(long con, long type, int mip, int usage, long pointer);
+    synchronized long nAllocationCreateTyped(long type, int mip, int usage, long pointer) {
         validate();
         return rsnAllocationCreateTyped(mContext, type, mip, usage, pointer);
     }
@@ -700,8 +700,8 @@
         return rsnScriptFieldIDCreate(mContext, sid, slot);
     }
 
-    native long rsnScriptGroupCreate(long con, int[] kernels, int[] src, int[] dstk, int[] dstf, int[] types);
-    synchronized long nScriptGroupCreate(int[] kernels, int[] src, int[] dstk, int[] dstf, int[] types) {
+    native long rsnScriptGroupCreate(long con, long[] kernels, long[] src, long[] dstk, long[] dstf, long[] types);
+    synchronized long nScriptGroupCreate(long[] kernels, long[] src, long[] dstk, long[] dstf, long[] types) {
         validate();
         return rsnScriptGroupCreate(mContext, kernels, src, dstk, dstf, types);
     }
@@ -764,19 +764,19 @@
         validate();
         rsnProgramBindSampler(mContext, vpf, slot, s);
     }
-    native long rsnProgramFragmentCreate(long con, String shader, String[] texNames, int[] params);
-    synchronized long nProgramFragmentCreate(String shader, String[] texNames, int[] params) {
+    native long rsnProgramFragmentCreate(long con, String shader, String[] texNames, long[] params);
+    synchronized long nProgramFragmentCreate(String shader, String[] texNames, long[] params) {
         validate();
         return rsnProgramFragmentCreate(mContext, shader, texNames, params);
     }
-    native long rsnProgramVertexCreate(long con, String shader, String[] texNames, int[] params);
-    synchronized long nProgramVertexCreate(String shader, String[] texNames, int[] params) {
+    native long rsnProgramVertexCreate(long con, String shader, String[] texNames, long[] params);
+    synchronized long nProgramVertexCreate(String shader, String[] texNames, long[] params) {
         validate();
         return rsnProgramVertexCreate(mContext, shader, texNames, params);
     }
 
-    native long rsnMeshCreate(long con, int[] vtx, int[] idx, int[] prim);
-    synchronized long nMeshCreate(int[] vtx, int[] idx, int[] prim) {
+    native long rsnMeshCreate(long con, long[] vtx, long[] idx, int[] prim);
+    synchronized long nMeshCreate(long[] vtx, long[] idx, int[] prim) {
         validate();
         return rsnMeshCreate(mContext, vtx, idx, prim);
     }
@@ -790,13 +790,13 @@
         validate();
         return rsnMeshGetIndexCount(mContext, id);
     }
-    native void rsnMeshGetVertices(long con, long id, int[] vtxIds, int vtxIdCount);
-    synchronized void nMeshGetVertices(long id, int[] vtxIds, int vtxIdCount) {
+    native void rsnMeshGetVertices(long con, long id, long[] vtxIds, int vtxIdCount);
+    synchronized void nMeshGetVertices(long id, long[] vtxIds, int vtxIdCount) {
         validate();
         rsnMeshGetVertices(mContext, id, vtxIds, vtxIdCount);
     }
-    native void rsnMeshGetIndices(long con, long id, int[] idxIds, int[] primitives, int vtxIdCount);
-    synchronized void nMeshGetIndices(long id, int[] idxIds, int[] primitives, int vtxIdCount) {
+    native void rsnMeshGetIndices(long con, long id, long[] idxIds, int[] primitives, int vtxIdCount);
+    synchronized void nMeshGetIndices(long id, long[] idxIds, int[] primitives, int vtxIdCount) {
         validate();
         rsnMeshGetIndices(mContext, id, idxIds, primitives, vtxIdCount);
     }
@@ -1000,6 +1000,14 @@
         }
     }
 
+    void validateObject(BaseObj o) {
+        if (o != null) {
+            if (o.mRS != this) {
+                throw new RSIllegalArgumentException("Attempting to use an object across contexts.");
+            }
+        }
+    }
+
     void validate() {
         if (mContext == 0) {
             throw new RSInvalidStateException("Calling RS with no Context active.");
diff --git a/rs/java/android/renderscript/Script.java b/rs/java/android/renderscript/Script.java
index a1f2287..0e46f94 100644
--- a/rs/java/android/renderscript/Script.java
+++ b/rs/java/android/renderscript/Script.java
@@ -128,6 +128,9 @@
      *
      */
     protected void forEach(int slot, Allocation ain, Allocation aout, FieldPacker v) {
+        mRS.validate();
+        mRS.validateObject(ain);
+        mRS.validateObject(aout);
         if (ain == null && aout == null) {
             throw new RSIllegalArgumentException(
                 "At least one of ain or aout is required to be non-null.");
@@ -152,6 +155,9 @@
      *
      */
     protected void forEach(int slot, Allocation ain, Allocation aout, FieldPacker v, LaunchOptions sc) {
+        mRS.validate();
+        mRS.validateObject(ain);
+        mRS.validateObject(aout);
         if (ain == null && aout == null) {
             throw new RSIllegalArgumentException(
                 "At least one of ain or aout is required to be non-null.");
@@ -187,6 +193,7 @@
      */
     public void bindAllocation(Allocation va, int slot) {
         mRS.validate();
+        mRS.validateObject(va);
         if (va != null) {
             if (mRS.getApplicationContext().getApplicationInfo().targetSdkVersion >= 20) {
                 final Type t = va.mType;
@@ -263,6 +270,8 @@
      *
      */
     public void setVar(int index, BaseObj o) {
+        mRS.validate();
+        mRS.validateObject(o);
         mRS.nScriptSetVarObj(getID(mRS), index, (o == null) ? 0 : o.getID(mRS));
     }
 
diff --git a/rs/java/android/renderscript/ScriptGroup.java b/rs/java/android/renderscript/ScriptGroup.java
index f1a7273..51c838f 100644
--- a/rs/java/android/renderscript/ScriptGroup.java
+++ b/rs/java/android/renderscript/ScriptGroup.java
@@ -379,7 +379,6 @@
          * @return ScriptGroup The new ScriptGroup
          */
         public ScriptGroup create() {
-            // FIXME: this is broken for 64-bit
 
             if (mNodes.size() == 0) {
                 throw new RSInvalidStateException("Empty script groups are not allowed");
@@ -394,13 +393,13 @@
             ArrayList<IO> inputs = new ArrayList<IO>();
             ArrayList<IO> outputs = new ArrayList<IO>();
 
-            int[] kernels = new int[mKernelCount];
+            long[] kernels = new long[mKernelCount];
             int idx = 0;
             for (int ct=0; ct < mNodes.size(); ct++) {
                 Node n = mNodes.get(ct);
                 for (int ct2=0; ct2 < n.mKernels.size(); ct2++) {
                     final Script.KernelID kid = n.mKernels.get(ct2);
-                    kernels[idx++] = (int)kid.getID(mRS);
+                    kernels[idx++] = kid.getID(mRS);
 
                     boolean hasInput = false;
                     boolean hasOutput = false;
@@ -427,21 +426,21 @@
                 throw new RSRuntimeException("Count mismatch, should not happen.");
             }
 
-            int[] src = new int[mLines.size()];
-            int[] dstk = new int[mLines.size()];
-            int[] dstf = new int[mLines.size()];
-            int[] types = new int[mLines.size()];
+            long[] src = new long[mLines.size()];
+            long[] dstk = new long[mLines.size()];
+            long[] dstf = new long[mLines.size()];
+            long[] types = new long[mLines.size()];
 
             for (int ct=0; ct < mLines.size(); ct++) {
                 ConnectLine cl = mLines.get(ct);
-                src[ct] = (int)cl.mFrom.getID(mRS);
+                src[ct] = cl.mFrom.getID(mRS);
                 if (cl.mToK != null) {
-                    dstk[ct] = (int)cl.mToK.getID(mRS);
+                    dstk[ct] = cl.mToK.getID(mRS);
                 }
                 if (cl.mToF != null) {
-                    dstf[ct] = (int)cl.mToF.getID(mRS);
+                    dstf[ct] = cl.mToF.getID(mRS);
                 }
-                types[ct] = (int)cl.mAllocationType.getID(mRS);
+                types[ct] = cl.mAllocationType.getID(mRS);
             }
 
             long id = mRS.nScriptGroupCreate(kernels, src, dstk, dstf, types);
diff --git a/rs/java/android/renderscript/Type.java b/rs/java/android/renderscript/Type.java
index 83bf4a5..98aeaa9 100644
--- a/rs/java/android/renderscript/Type.java
+++ b/rs/java/android/renderscript/Type.java
@@ -190,20 +190,18 @@
 
     @Override
     void updateFromNative() {
-        // FIXME: rsaTypeGetNativeData needs 32-bit and 64-bit paths
-
-        // We have 6 integer to obtain mDimX; mDimY; mDimZ;
+        // We have 6 integer/long to obtain mDimX; mDimY; mDimZ;
         // mDimLOD; mDimFaces; mElement;
-        int[] dataBuffer = new int[6];
-        mRS.nTypeGetNativeData((int)getID(mRS), dataBuffer);
+        long[] dataBuffer = new long[6];
+        mRS.nTypeGetNativeData(getID(mRS), dataBuffer);
 
-        mDimX = dataBuffer[0];
-        mDimY = dataBuffer[1];
-        mDimZ = dataBuffer[2];
+        mDimX = (int)dataBuffer[0];
+        mDimY = (int)dataBuffer[1];
+        mDimZ = (int)dataBuffer[2];
         mDimMipmaps = dataBuffer[3] == 1 ? true : false;
         mDimFaces = dataBuffer[4] == 1 ? true : false;
 
-        int elementID = dataBuffer[5];
+        long elementID = dataBuffer[5];
         if(elementID != 0) {
             mElement = new Element(elementID, mRS);
             mElement.updateFromNative();
diff --git a/rs/jni/Android.mk b/rs/jni/Android.mk
index cbb5b3b..07933b4 100644
--- a/rs/jni/Android.mk
+++ b/rs/jni/Android.mk
@@ -23,8 +23,7 @@
 LOCAL_C_INCLUDES += \
 	$(JNI_H_INCLUDE) \
 	frameworks/rs \
-	$(rs_generated_include_dir) \
-	$(call include-path-for, corecg graphics)
+	$(rs_generated_include_dir)
 
 LOCAL_CFLAGS += -Wno-unused-parameter
 
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 80a5da2..b547706 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -23,10 +23,7 @@
 #include <math.h>
 #include <utils/misc.h>
 
-#include <core/SkBitmap.h>
-#include <core/SkPixelRef.h>
-#include <core/SkStream.h>
-#include <core/SkTemplates.h>
+#include <SkBitmap.h>
 
 #include <androidfw/Asset.h>
 #include <androidfw/AssetManager.h>
@@ -412,13 +409,21 @@
 
 static jlong
 nElementCreate2(JNIEnv *_env, jobject _this, jlong con,
-                jintArray _ids, jobjectArray _names, jintArray _arraySizes)
+                jlongArray _ids, jobjectArray _names, jintArray _arraySizes)
 {
     int fieldCount = _env->GetArrayLength(_ids);
     LOG_API("nElementCreate2, con(%p)", (RsContext)con);
 
-    jint *ids = _env->GetIntArrayElements(_ids, NULL);
-    jint *arraySizes = _env->GetIntArrayElements(_arraySizes, NULL);
+    jlong *jIds = _env->GetLongArrayElements(_ids, NULL);
+    jint *jArraySizes = _env->GetIntArrayElements(_arraySizes, NULL);
+
+    RsElement *ids = (RsElement*)malloc(fieldCount * sizeof(RsElement));
+    uint32_t *arraySizes = (uint32_t *)malloc(fieldCount * sizeof(uint32_t));
+
+    for(int i = 0; i < fieldCount; i ++) {
+        ids[i] = (RsElement)jIds[i];
+        arraySizes[i] = (uint32_t)jArraySizes[i];
+    }
 
     AutoJavaStringArrayToUTF8 names(_env, _names, fieldCount);
 
@@ -426,12 +431,15 @@
     size_t *sizeArray = names.c_str_len();
 
     jlong id = (jlong)rsElementCreate2((RsContext)con,
-                                     (RsElement *)ids, fieldCount,
+                                     (const RsElement *)ids, fieldCount,
                                      nameArray, fieldCount * sizeof(size_t),  sizeArray,
                                      (const uint32_t *)arraySizes, fieldCount);
 
-    _env->ReleaseIntArrayElements(_ids, ids, JNI_ABORT);
-    _env->ReleaseIntArrayElements(_arraySizes, arraySizes, JNI_ABORT);
+    free(ids);
+    free(arraySizes);
+    _env->ReleaseLongArrayElements(_ids, jIds, JNI_ABORT);
+    _env->ReleaseIntArrayElements(_arraySizes, jArraySizes, JNI_ABORT);
+
     return (jlong)id;
 }
 
@@ -448,30 +456,33 @@
     rsaElementGetNativeData((RsContext)con, (RsElement)id, elementData, dataSize);
 
     for(jint i = 0; i < dataSize; i ++) {
-        _env->SetIntArrayRegion(_elementData, i, 1, (const jint*)&elementData[i]);
+        const jint data = (jint)elementData[i];
+        _env->SetIntArrayRegion(_elementData, i, 1, &data);
     }
 }
 
 
 static void
 nElementGetSubElements(JNIEnv *_env, jobject _this, jlong con, jlong id,
-                       jintArray _IDs,
+                       jlongArray _IDs,
                        jobjectArray _names,
                        jintArray _arraySizes)
 {
-    int dataSize = _env->GetArrayLength(_IDs);
+    uint32_t dataSize = _env->GetArrayLength(_IDs);
     LOG_API("nElementGetSubElements, con(%p)", (RsContext)con);
 
-    uint32_t *ids = (uint32_t *)malloc((uint32_t)dataSize * sizeof(uint32_t));
-    const char **names = (const char **)malloc((uint32_t)dataSize * sizeof(const char *));
-    uint32_t *arraySizes = (uint32_t *)malloc((uint32_t)dataSize * sizeof(uint32_t));
+    uintptr_t *ids = (uintptr_t*)malloc(dataSize * sizeof(uintptr_t));
+    const char **names = (const char **)malloc(dataSize * sizeof(const char *));
+    size_t *arraySizes = (size_t *)malloc(dataSize * sizeof(size_t));
 
     rsaElementGetSubElements((RsContext)con, (RsElement)id, ids, names, arraySizes, (uint32_t)dataSize);
 
-    for(jint i = 0; i < dataSize; i++) {
+    for(uint32_t i = 0; i < dataSize; i++) {
+        const jlong id = (jlong)ids[i];
+        const jint arraySize = (jint)arraySizes[i];
         _env->SetObjectArrayElement(_names, i, _env->NewStringUTF(names[i]));
-        _env->SetIntArrayRegion(_IDs, i, 1, (const jint*)&ids[i]);
-        _env->SetIntArrayRegion(_arraySizes, i, 1, (const jint*)&arraySizes[i]);
+        _env->SetLongArrayRegion(_IDs, i, 1, &id);
+        _env->SetIntArrayRegion(_arraySizes, i, 1, &arraySize);
     }
 
     free(ids);
@@ -492,7 +503,7 @@
 }
 
 static void
-nTypeGetNativeData(JNIEnv *_env, jobject _this, jlong con, jlong id, jintArray _typeData)
+nTypeGetNativeData(JNIEnv *_env, jobject _this, jlong con, jlong id, jlongArray _typeData)
 {
     // We are packing 6 items: mDimX; mDimY; mDimZ;
     // mDimLOD; mDimFaces; mElement; into typeData
@@ -501,21 +512,22 @@
     assert(elementCount == 6);
     LOG_API("nTypeGetNativeData, con(%p)", (RsContext)con);
 
-    uint32_t typeData[6];
+    uintptr_t typeData[6];
     rsaTypeGetNativeData((RsContext)con, (RsType)id, typeData, 6);
 
     for(jint i = 0; i < elementCount; i ++) {
-        _env->SetIntArrayRegion(_typeData, i, 1, (const jint*)&typeData[i]);
+        const jlong data = (jlong)typeData[i];
+        _env->SetLongArrayRegion(_typeData, i, 1, &data);
     }
 }
 
 // -----------------------------------
 
 static jlong
-nAllocationCreateTyped(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mips, jint usage, jint pointer)
+nAllocationCreateTyped(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mips, jint usage, jlong pointer)
 {
     LOG_API("nAllocationCreateTyped, con(%p), type(%p), mip(%i), usage(%i), ptr(%p)", (RsContext)con, (RsElement)type, mips, usage, (void *)pointer);
-    return (jlong) rsAllocationCreateTyped((RsContext)con, (RsType)type, (RsAllocationMipmapControl)mips, (uint32_t)usage, (uint32_t)pointer);
+    return (jlong) rsAllocationCreateTyped((RsContext)con, (RsType)type, (RsAllocationMipmapControl)mips, (uint32_t)usage, (uintptr_t)pointer);
 }
 
 static void
@@ -601,7 +613,7 @@
     const void* ptr = bitmap.getPixels();
     jlong id = (jlong)rsAllocationCreateTyped((RsContext)con,
                                             (RsType)type, (RsAllocationMipmapControl)mip,
-                                            (uint32_t)usage, (size_t)ptr);
+                                            (uint32_t)usage, (uintptr_t)ptr);
     bitmap.unlockPixels();
     return id;
 }
@@ -1196,34 +1208,63 @@
 }
 
 static jlong
-nScriptGroupCreate(JNIEnv *_env, jobject _this, jlong con, jintArray _kernels, jintArray _src,
-    jintArray _dstk, jintArray _dstf, jintArray _types)
+nScriptGroupCreate(JNIEnv *_env, jobject _this, jlong con, jlongArray _kernels, jlongArray _src,
+    jlongArray _dstk, jlongArray _dstf, jlongArray _types)
 {
     LOG_API("nScriptGroupCreate, con(%p)", (RsContext)con);
 
-    jint kernelsLen = _env->GetArrayLength(_kernels) * sizeof(int);
-    jint *kernelsPtr = _env->GetIntArrayElements(_kernels, NULL);
-    jint srcLen = _env->GetArrayLength(_src) * sizeof(int);
-    jint *srcPtr = _env->GetIntArrayElements(_src, NULL);
-    jint dstkLen = _env->GetArrayLength(_dstk) * sizeof(int);
-    jint *dstkPtr = _env->GetIntArrayElements(_dstk, NULL);
-    jint dstfLen = _env->GetArrayLength(_dstf) * sizeof(int);
-    jint *dstfPtr = _env->GetIntArrayElements(_dstf, NULL);
-    jint typesLen = _env->GetArrayLength(_types) * sizeof(int);
-    jint *typesPtr = _env->GetIntArrayElements(_types, NULL);
+    jint kernelsLen = _env->GetArrayLength(_kernels);
+    jlong *jKernelsPtr = _env->GetLongArrayElements(_kernels, NULL);
+    RsScriptKernelID* kernelsPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * kernelsLen);
+    for(int i = 0; i < kernelsLen; ++i) {
+        kernelsPtr[i] = (RsScriptKernelID)jKernelsPtr[i];
+    }
 
-    int id = (int)rsScriptGroupCreate((RsContext)con,
-                               (RsScriptKernelID *)kernelsPtr, kernelsLen,
-                               (RsScriptKernelID *)srcPtr, srcLen,
-                               (RsScriptKernelID *)dstkPtr, dstkLen,
-                               (RsScriptFieldID *)dstfPtr, dstfLen,
-                               (RsType *)typesPtr, typesLen);
+    jint srcLen = _env->GetArrayLength(_src);
+    jlong *jSrcPtr = _env->GetLongArrayElements(_src, NULL);
+    RsScriptKernelID* srcPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * srcLen);
+    for(int i = 0; i < srcLen; ++i) {
+        srcPtr[i] = (RsScriptKernelID)jSrcPtr[i];
+    }
 
-    _env->ReleaseIntArrayElements(_kernels, kernelsPtr, 0);
-    _env->ReleaseIntArrayElements(_src, srcPtr, 0);
-    _env->ReleaseIntArrayElements(_dstk, dstkPtr, 0);
-    _env->ReleaseIntArrayElements(_dstf, dstfPtr, 0);
-    _env->ReleaseIntArrayElements(_types, typesPtr, 0);
+    jint dstkLen = _env->GetArrayLength(_dstk);
+    jlong *jDstkPtr = _env->GetLongArrayElements(_dstk, NULL);
+    RsScriptKernelID* dstkPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * dstkLen);
+    for(int i = 0; i < dstkLen; ++i) {
+        dstkPtr[i] = (RsScriptKernelID)jDstkPtr[i];
+    }
+
+    jint dstfLen = _env->GetArrayLength(_dstf);
+    jlong *jDstfPtr = _env->GetLongArrayElements(_dstf, NULL);
+    RsScriptKernelID* dstfPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * dstfLen);
+    for(int i = 0; i < dstfLen; ++i) {
+        dstfPtr[i] = (RsScriptKernelID)jDstfPtr[i];
+    }
+
+    jint typesLen = _env->GetArrayLength(_types);
+    jlong *jTypesPtr = _env->GetLongArrayElements(_types, NULL);
+    RsType* typesPtr = (RsType*) malloc(sizeof(RsType) * typesLen);
+    for(int i = 0; i < typesLen; ++i) {
+        typesPtr[i] = (RsType)jTypesPtr[i];
+    }
+
+    jlong id = (jlong)rsScriptGroupCreate((RsContext)con,
+                               (RsScriptKernelID *)kernelsPtr, kernelsLen * sizeof(RsScriptKernelID),
+                               (RsScriptKernelID *)srcPtr, srcLen * sizeof(RsScriptKernelID),
+                               (RsScriptKernelID *)dstkPtr, dstkLen * sizeof(RsScriptKernelID),
+                               (RsScriptFieldID *)dstfPtr, dstfLen * sizeof(RsScriptKernelID),
+                               (RsType *)typesPtr, typesLen * sizeof(RsType));
+
+    free(kernelsPtr);
+    free(srcPtr);
+    free(dstkPtr);
+    free(dstfPtr);
+    free(typesPtr);
+    _env->ReleaseLongArrayElements(_kernels, jKernelsPtr, 0);
+    _env->ReleaseLongArrayElements(_src, jSrcPtr, 0);
+    _env->ReleaseLongArrayElements(_dstk, jDstkPtr, 0);
+    _env->ReleaseLongArrayElements(_dstf, jDstfPtr, 0);
+    _env->ReleaseLongArrayElements(_types, jTypesPtr, 0);
     return id;
 }
 
@@ -1292,10 +1333,10 @@
 
 static jlong
 nProgramFragmentCreate(JNIEnv *_env, jobject _this, jlong con, jstring shader,
-                       jobjectArray texNames, jintArray params)
+                       jobjectArray texNames, jlongArray params)
 {
     AutoJavaStringToUTF8 shaderUTF(_env, shader);
-    jint *paramPtr = _env->GetIntArrayElements(params, NULL);
+    jlong *jParamPtr = _env->GetLongArrayElements(params, NULL);
     jint paramLen = _env->GetArrayLength(params);
 
     int texCount = _env->GetArrayLength(texNames);
@@ -1305,11 +1346,16 @@
 
     LOG_API("nProgramFragmentCreate, con(%p), paramLen(%i)", (RsContext)con, paramLen);
 
+    uintptr_t * paramPtr = (uintptr_t*) malloc(sizeof(uintptr_t) * paramLen);
+    for(int i = 0; i < paramLen; ++i) {
+        paramPtr[i] = (uintptr_t)jParamPtr[i];
+    }
     jlong ret = (jlong)rsProgramFragmentCreate((RsContext)con, shaderUTF.c_str(), shaderUTF.length(),
                                              nameArray, texCount, sizeArray,
-                                             (uint32_t *)paramPtr, paramLen);
+                                             paramPtr, paramLen);
 
-    _env->ReleaseIntArrayElements(params, paramPtr, JNI_ABORT);
+    free(paramPtr);
+    _env->ReleaseLongArrayElements(params, jParamPtr, JNI_ABORT);
     return ret;
 }
 
@@ -1318,10 +1364,10 @@
 
 static jlong
 nProgramVertexCreate(JNIEnv *_env, jobject _this, jlong con, jstring shader,
-                     jobjectArray texNames, jintArray params)
+                     jobjectArray texNames, jlongArray params)
 {
     AutoJavaStringToUTF8 shaderUTF(_env, shader);
-    jint *paramPtr = _env->GetIntArrayElements(params, NULL);
+    jlong *jParamPtr = _env->GetLongArrayElements(params, NULL);
     jint paramLen = _env->GetArrayLength(params);
 
     LOG_API("nProgramVertexCreate, con(%p), paramLen(%i)", (RsContext)con, paramLen);
@@ -1331,11 +1377,17 @@
     const char ** nameArray = names.c_str();
     size_t* sizeArray = names.c_str_len();
 
+    uintptr_t * paramPtr = (uintptr_t*) malloc(sizeof(uintptr_t) * paramLen);
+    for(int i = 0; i < paramLen; ++i) {
+        paramPtr[i] = (uintptr_t)jParamPtr[i];
+    }
+
     jlong ret = (jlong)rsProgramVertexCreate((RsContext)con, shaderUTF.c_str(), shaderUTF.length(),
                                            nameArray, texCount, sizeArray,
-                                           (uint32_t *)paramPtr, paramLen);
+                                           paramPtr, paramLen);
 
-    _env->ReleaseIntArrayElements(params, paramPtr, JNI_ABORT);
+    free(paramPtr);
+    _env->ReleaseLongArrayElements(params, jParamPtr, JNI_ABORT);
     return ret;
 }
 
@@ -1416,24 +1468,36 @@
 }
 
 static jlong
-nMeshCreate(JNIEnv *_env, jobject _this, jlong con, jintArray _vtx, jintArray _idx, jintArray _prim)
+nMeshCreate(JNIEnv *_env, jobject _this, jlong con, jlongArray _vtx, jlongArray _idx, jintArray _prim)
 {
     LOG_API("nMeshCreate, con(%p)", (RsContext)con);
 
     jint vtxLen = _env->GetArrayLength(_vtx);
-    jint *vtxPtr = _env->GetIntArrayElements(_vtx, NULL);
+    jlong *jVtxPtr = _env->GetLongArrayElements(_vtx, NULL);
+    RsAllocation* vtxPtr = (RsAllocation*) malloc(sizeof(RsAllocation) * vtxLen);
+    for(int i = 0; i < vtxLen; ++i) {
+        vtxPtr[i] = (RsAllocation)(uintptr_t)jVtxPtr[i];
+    }
+
     jint idxLen = _env->GetArrayLength(_idx);
-    jint *idxPtr = _env->GetIntArrayElements(_idx, NULL);
+    jlong *jIdxPtr = _env->GetLongArrayElements(_idx, NULL);
+    RsAllocation* idxPtr = (RsAllocation*) malloc(sizeof(RsAllocation) * idxLen);
+    for(int i = 0; i < idxLen; ++i) {
+        idxPtr[i] = (RsAllocation)(uintptr_t)jIdxPtr[i];
+    }
+
     jint primLen = _env->GetArrayLength(_prim);
     jint *primPtr = _env->GetIntArrayElements(_prim, NULL);
 
-    int id = (int)rsMeshCreate((RsContext)con,
+    jlong id = (jlong)rsMeshCreate((RsContext)con,
                                (RsAllocation *)vtxPtr, vtxLen,
                                (RsAllocation *)idxPtr, idxLen,
                                (uint32_t *)primPtr, primLen);
 
-    _env->ReleaseIntArrayElements(_vtx, vtxPtr, 0);
-    _env->ReleaseIntArrayElements(_idx, idxPtr, 0);
+    free(vtxPtr);
+    free(idxPtr);
+    _env->ReleaseLongArrayElements(_vtx, jVtxPtr, 0);
+    _env->ReleaseLongArrayElements(_idx, jIdxPtr, 0);
     _env->ReleaseIntArrayElements(_prim, primPtr, 0);
     return id;
 }
@@ -1457,7 +1521,7 @@
 }
 
 static void
-nMeshGetVertices(JNIEnv *_env, jobject _this, jlong con, jlong mesh, jintArray _ids, int numVtxIDs)
+nMeshGetVertices(JNIEnv *_env, jobject _this, jlong con, jlong mesh, jlongArray _ids, jint numVtxIDs)
 {
     LOG_API("nMeshGetVertices, con(%p), Mesh(%p)", (RsContext)con, (RsMesh)mesh);
 
@@ -1465,14 +1529,15 @@
     rsaMeshGetVertices((RsContext)con, (RsMesh)mesh, allocs, (uint32_t)numVtxIDs);
 
     for(jint i = 0; i < numVtxIDs; i ++) {
-        _env->SetIntArrayRegion(_ids, i, 1, (const jint*)&allocs[i]);
+        const jlong alloc = (jlong)allocs[i];
+        _env->SetLongArrayRegion(_ids, i, 1, &alloc);
     }
 
     free(allocs);
 }
 
 static void
-nMeshGetIndices(JNIEnv *_env, jobject _this, jlong con, jlong mesh, jintArray _idxIds, jintArray _primitives, int numIndices)
+nMeshGetIndices(JNIEnv *_env, jobject _this, jlong con, jlong mesh, jlongArray _idxIds, jintArray _primitives, jint numIndices)
 {
     LOG_API("nMeshGetVertices, con(%p), Mesh(%p)", (RsContext)con, (RsMesh)mesh);
 
@@ -1482,8 +1547,10 @@
     rsaMeshGetIndices((RsContext)con, (RsMesh)mesh, allocs, prims, (uint32_t)numIndices);
 
     for(jint i = 0; i < numIndices; i ++) {
-        _env->SetIntArrayRegion(_idxIds, i, 1, (const jint*)&allocs[i]);
-        _env->SetIntArrayRegion(_primitives, i, 1, (const jint*)&prims[i]);
+        const jlong alloc = (jlong)allocs[i];
+        const jint prim = (jint)prims[i];
+        _env->SetLongArrayRegion(_idxIds, i, 1, &alloc);
+        _env->SetIntArrayRegion(_primitives, i, 1, &prim);
     }
 
     free(allocs);
@@ -1536,14 +1603,14 @@
 {"rsnFontCreateFromAsset",        "(JLandroid/content/res/AssetManager;Ljava/lang/String;FI)J",            (void*)nFontCreateFromAsset },
 
 {"rsnElementCreate",                 "(JJIZI)J",                              (void*)nElementCreate },
-{"rsnElementCreate2",                "(J[I[Ljava/lang/String;[I)J",           (void*)nElementCreate2 },
+{"rsnElementCreate2",                "(J[J[Ljava/lang/String;[I)J",           (void*)nElementCreate2 },
 {"rsnElementGetNativeData",          "(JJ[I)V",                               (void*)nElementGetNativeData },
-{"rsnElementGetSubElements",         "(JJ[I[Ljava/lang/String;[I)V",          (void*)nElementGetSubElements },
+{"rsnElementGetSubElements",         "(JJ[J[Ljava/lang/String;[I)V",          (void*)nElementGetSubElements },
 
 {"rsnTypeCreate",                    "(JJIIIZZI)J",                           (void*)nTypeCreate },
-{"rsnTypeGetNativeData",             "(JJ[I)V",                               (void*)nTypeGetNativeData },
+{"rsnTypeGetNativeData",             "(JJ[J)V",                               (void*)nTypeGetNativeData },
 
-{"rsnAllocationCreateTyped",         "(JJIII)J",                               (void*)nAllocationCreateTyped },
+{"rsnAllocationCreateTyped",         "(JJIIJ)J",                               (void*)nAllocationCreateTyped },
 {"rsnAllocationCreateFromBitmap",    "(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCreateFromBitmap },
 {"rsnAllocationCreateBitmapBackedAllocation",    "(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCreateBitmapBackedAllocation },
 {"rsnAllocationCubeCreateFromBitmap","(JJILandroid/graphics/Bitmap;I)J",      (void*)nAllocationCubeCreateFromBitmap },
@@ -1594,7 +1661,7 @@
 {"rsnScriptIntrinsicCreate",         "(JIJ)J",                                (void*)nScriptIntrinsicCreate },
 {"rsnScriptKernelIDCreate",          "(JJII)J",                               (void*)nScriptKernelIDCreate },
 {"rsnScriptFieldIDCreate",           "(JJI)J",                                (void*)nScriptFieldIDCreate },
-{"rsnScriptGroupCreate",             "(J[I[I[I[I[I)J",                        (void*)nScriptGroupCreate },
+{"rsnScriptGroupCreate",             "(J[J[J[J[J[J)J",                        (void*)nScriptGroupCreate },
 {"rsnScriptGroupSetInput",           "(JJJJ)V",                               (void*)nScriptGroupSetInput },
 {"rsnScriptGroupSetOutput",          "(JJJJ)V",                               (void*)nScriptGroupSetOutput },
 {"rsnScriptGroupExecute",            "(JJ)V",                                 (void*)nScriptGroupExecute },
@@ -1605,9 +1672,9 @@
 {"rsnProgramBindTexture",            "(JJIJ)V",                               (void*)nProgramBindTexture },
 {"rsnProgramBindSampler",            "(JJIJ)V",                               (void*)nProgramBindSampler },
 
-{"rsnProgramFragmentCreate",         "(JLjava/lang/String;[Ljava/lang/String;[I)J",              (void*)nProgramFragmentCreate },
+{"rsnProgramFragmentCreate",         "(JLjava/lang/String;[Ljava/lang/String;[J)J",              (void*)nProgramFragmentCreate },
 {"rsnProgramRasterCreate",           "(JZI)J",                                (void*)nProgramRasterCreate },
-{"rsnProgramVertexCreate",           "(JLjava/lang/String;[Ljava/lang/String;[I)J",              (void*)nProgramVertexCreate },
+{"rsnProgramVertexCreate",           "(JLjava/lang/String;[Ljava/lang/String;[J)J",              (void*)nProgramVertexCreate },
 
 {"rsnContextBindRootScript",         "(JI)V",                                 (void*)nContextBindRootScript },
 {"rsnContextBindProgramStore",       "(JI)V",                                 (void*)nContextBindProgramStore },
@@ -1618,12 +1685,12 @@
 {"rsnSamplerCreate",                 "(JIIIIIF)J",                            (void*)nSamplerCreate },
 
 {"rsnPathCreate",                    "(JIZJJF)J",                             (void*)nPathCreate },
-{"rsnMeshCreate",                    "(J[I[I[I)J",                            (void*)nMeshCreate },
+{"rsnMeshCreate",                    "(J[J[J[I)J",                            (void*)nMeshCreate },
 
 {"rsnMeshGetVertexBufferCount",      "(JJ)I",                                 (void*)nMeshGetVertexBufferCount },
 {"rsnMeshGetIndexCount",             "(JJ)I",                                 (void*)nMeshGetIndexCount },
-{"rsnMeshGetVertices",               "(JJ[II)V",                              (void*)nMeshGetVertices },
-{"rsnMeshGetIndices",                "(JJ[I[II)V",                            (void*)nMeshGetIndices },
+{"rsnMeshGetVertices",               "(JJ[JI)V",                              (void*)nMeshGetVertices },
+{"rsnMeshGetIndices",                "(JJ[J[II)V",                            (void*)nMeshGetIndices },
 
 };
 
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 43e1f12..959d4a9 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -2722,7 +2722,8 @@
             | AccessibilityNodeInfo.ACTION_SET_SELECTION
             | AccessibilityNodeInfo.ACTION_EXPAND
             | AccessibilityNodeInfo.ACTION_COLLAPSE
-            | AccessibilityNodeInfo.ACTION_DISMISS;
+            | AccessibilityNodeInfo.ACTION_DISMISS
+            | AccessibilityNodeInfo.ACTION_SET_TEXT;
 
         private static final int RETRIEVAL_ALLOWING_EVENT_TYPES =
             AccessibilityEvent.TYPE_VIEW_CLICKED
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 186ae1b..8eaefef 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -5803,19 +5803,25 @@
             return;
         }
 
+        boolean skip = false;
+
         long restoreSet = getAvailableRestoreToken(packageName);
         if (DEBUG) Slog.v(TAG, "restoreAtInstall pkg=" + packageName
                 + " token=" + Integer.toHexString(token)
                 + " restoreSet=" + Long.toHexString(restoreSet));
+        if (restoreSet == 0) {
+            if (MORE_DEBUG) Slog.i(TAG, "No restore set");
+            skip = true;
+        }
 
-        if (mAutoRestore && mProvisioned && restoreSet != 0) {
-            // Do we have a transport to fetch data for us?
-            IBackupTransport transport = getTransport(mCurrentTransport);
-            if (transport == null) {
-                if (DEBUG) Slog.w(TAG, "No transport for install-time restore");
-                return;
-            }
+        // Do we have a transport to fetch data for us?
+        IBackupTransport transport = getTransport(mCurrentTransport);
+        if (transport == null) {
+            if (DEBUG) Slog.w(TAG, "No transport");
+            skip = true;
+        }
 
+        if (!skip && mAutoRestore && mProvisioned) {
             try {
                 // okay, we're going to attempt a restore of this package from this restore set.
                 // The eventual message back into the Package Manager to run the post-install
@@ -5837,12 +5843,15 @@
                 mBackupHandler.sendMessage(msg);
             } catch (RemoteException e) {
                 // Binding to the transport broke; back off and proceed with the installation.
-                Slog.e(TAG, "Unable to contact transport for install-time restore");
+                Slog.e(TAG, "Unable to contact transport");
+                skip = true;
             }
-        } else {
+        }
+
+        if (skip) {
             // Auto-restore disabled or no way to attempt a restore; just tell the Package
             // Manager to proceed with the post-install handling for this package.
-            if (DEBUG) Slog.v(TAG, "No restore set -- skipping restore");
+            if (DEBUG) Slog.v(TAG, "Skipping");
             try {
                 mPackageManagerBinder.finishPackageInstall(token);
             } catch (RemoteException e) { /* can't happen */ }
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 5d86b38..bda0183 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -492,7 +492,7 @@
 
         PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*alarm*");
-        
+
         mTimeTickSender = PendingIntent.getBroadcastAsUser(getContext(), 0,
                 new Intent(Intent.ACTION_TIME_TICK).addFlags(
                         Intent.FLAG_RECEIVER_REGISTERED_ONLY
@@ -673,12 +673,19 @@
         }
 
         @Override
-        public void setTime(long millis) {
+        public boolean setTime(long millis) {
             getContext().enforceCallingOrSelfPermission(
                     "android.permission.SET_TIME",
                     "setTime");
 
-            SystemClock.setCurrentTimeMillis(millis);
+            if (mNativeData == 0) {
+                Slog.w(TAG, "Not setting time since no alarm driver is available.");
+                return false;
+            }
+
+            synchronized (mLock) {
+                return setKernelTime(mNativeData, millis) == 0;
+            }
         }
 
         @Override
@@ -1063,6 +1070,7 @@
     private native void close(long nativeData);
     private native void set(long nativeData, int type, long seconds, long nanoseconds);
     private native int waitForAlarm(long nativeData);
+    private native int setKernelTime(long nativeData, long millis);
     private native int setKernelTimezone(long nativeData, int minuteswest);
 
     void triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
@@ -1275,13 +1283,10 @@
                                 setWakelockWorkSource(alarm.operation, alarm.workSource);
                                 mWakeLock.setUnimportantForLogging(
                                         alarm.operation == mTimeTickSender);
-                                // XXX debugging
-                                /*
-                                Intent intent = alarm.operation.getIntent();
-                                mWakeLock.setTag(intent.getAction() != null ? intent.getAction()
-                                        : (intent.getComponent() != null
-                                                ? intent.getComponent().toShortString() : TAG));
-                                */
+                                mWakeLock.setHistoryTag(alarm.operation.getTag(
+                                        alarm.type == ELAPSED_REALTIME_WAKEUP
+                                                || alarm.type == RTC_WAKEUP
+                                                ? "*walarm*:" : "*alarm*:"));
                                 mWakeLock.acquire();
                             }
                             final InFlight inflight = new InFlight(AlarmManagerService.this,
diff --git a/services/core/java/com/android/server/AssetAtlasService.java b/services/core/java/com/android/server/AssetAtlasService.java
index 3fb006b..fc4838c 100644
--- a/services/core/java/com/android/server/AssetAtlasService.java
+++ b/services/core/java/com/android/server/AssetAtlasService.java
@@ -114,12 +114,11 @@
 
     // Describes how bitmaps are placed in the atlas. Each bitmap is
     // represented by several entries in the array:
-    // int0: SkBitmap*, the native bitmap object
-    // int1: x position
-    // int2: y position
-    // int3: rotated, 1 if the bitmap must be rotated, 0 otherwise
-    // NOTE: This will need to be handled differently to support 64 bit pointers
-    private int[] mAtlasMap;
+    // long0: SkBitmap*, the native bitmap object
+    // long1: x position
+    // long2: y position
+    // long3: rotated, 1 if the bitmap must be rotated, 0 otherwise
+    private long[] mAtlasMap;
 
     /**
      * Creates a new service. Upon creating, the service will gather the list of
@@ -196,7 +195,7 @@
         private final ArrayList<Bitmap> mBitmaps;
         private final int mPixelCount;
 
-        private int mNativeBitmap;
+        private long mNativeBitmap;
 
         // Used for debugging only
         private Bitmap mAtlasBitmap;
@@ -260,8 +259,8 @@
 
             final Atlas.Entry entry = new Atlas.Entry();
 
-            mAtlasMap = new int[packCount * ATLAS_MAP_ENTRY_FIELD_COUNT];
-            int[] atlasMap = mAtlasMap;
+            mAtlasMap = new long[packCount * ATLAS_MAP_ENTRY_FIELD_COUNT];
+            long[] atlasMap = mAtlasMap;
             int mapIndex = 0;
 
             boolean result = false;
@@ -288,8 +287,7 @@
                         }
                         canvas.drawBitmap(bitmap, 0.0f, 0.0f, null);
                         canvas.restore();
-                        // TODO: Change mAtlasMap to long[] to support 64-bit systems
-                        atlasMap[mapIndex++] = (int) bitmap.mNativeBitmap;
+                        atlasMap[mapIndex++] = bitmap.mNativeBitmap;
                         atlasMap[mapIndex++] = entry.x;
                         atlasMap[mapIndex++] = entry.y;
                         atlasMap[mapIndex++] = entry.rotated ? 1 : 0;
@@ -365,9 +363,9 @@
         }
     }
 
-    private static native int nAcquireAtlasCanvas(Canvas canvas, int width, int height);
-    private static native void nReleaseAtlasCanvas(Canvas canvas, int bitmap);
-    private static native boolean nUploadAtlas(GraphicBuffer buffer, int bitmap);
+    private static native long nAcquireAtlasCanvas(Canvas canvas, int width, int height);
+    private static native void nReleaseAtlasCanvas(Canvas canvas, long bitmap);
+    private static native boolean nUploadAtlas(GraphicBuffer buffer, long bitmap);
 
     @Override
     public boolean isCompatible(int ppid) {
@@ -380,7 +378,7 @@
     }
 
     @Override
-    public int[] getMap() throws RemoteException {
+    public long[] getMap() throws RemoteException {
         return mAtlasReady.get() ? mAtlasMap : null;
     }
 
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 6e72e24..cb5946a 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -108,6 +108,7 @@
     private final Object mLock = new Object();
 
     private BatteryProperties mBatteryProps;
+    private final BatteryProperties mLastBatteryProps = new BatteryProperties();
     private boolean mBatteryLevelCritical;
     private int mLastBatteryStatus;
     private int mLastBatteryHealth;
@@ -281,6 +282,8 @@
                 mBatteryProps = props;
                 // Process the new values.
                 processValuesLocked();
+            } else {
+                mLastBatteryProps.set(props);
             }
         }
     }
@@ -617,6 +620,9 @@
                 String key = args[1];
                 String value = args[2];
                 try {
+                    if (!mUpdatesStopped) {
+                        mLastBatteryProps.set(mBatteryProps);
+                    }
                     boolean update = true;
                     if ("ac".equals(key)) {
                         mBatteryProps.chargerAcOnline = Integer.parseInt(value) != 0;
@@ -649,13 +655,17 @@
             } else if (args.length == 1 && "reset".equals(args[0])) {
                 long ident = Binder.clearCallingIdentity();
                 try {
-                    mUpdatesStopped = false;
+                    if (mUpdatesStopped) {
+                        mUpdatesStopped = false;
+                        mBatteryProps.set(mLastBatteryProps);
+                        processValuesLocked();
+                    }
                 } finally {
                     Binder.restoreCallingIdentity(ident);
                 }
             } else {
                 pw.println("Dump current battery state, or:");
-                pw.println("  set ac|usb|wireless|status|level|invalid <value>");
+                pw.println("  set [ac|usb|wireless|status|level|invalid] <value>");
                 pw.println("  reset");
             }
         }
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 546324a..0d6f548 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -1005,7 +1005,7 @@
                         mState = BluetoothAdapter.STATE_OFF;
                         // enable
                         handleEnable(mQuietEnable);
-		    } else if (mBinding || mBluetooth != null) {
+                    } else if (mBinding || mBluetooth != null) {
                         Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED);
                         userMsg.arg2 = 1 + msg.arg2;
                         // if user is switched when service is being binding
@@ -1014,7 +1014,7 @@
                         if (DBG) {
                             Log.d(TAG, "delay MESSAGE_USER_SWITCHED " + userMsg.arg2);
                         }
-		    }
+                    }
                     break;
                 }
             }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index b56923f..ffc748f 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -33,6 +33,7 @@
 import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
 
 import android.app.AlarmManager;
+import android.app.AppOpsManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -44,7 +45,9 @@
 import android.content.ContextWrapper;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.ContentObserver;
@@ -169,9 +172,9 @@
     private static final String TAG = "ConnectivityService";
 
     private static final boolean DBG = true;
-    private static final boolean VDBG = true;
+    private static final boolean VDBG = false;
 
-    private static final boolean LOGD_RULES = true;
+    private static final boolean LOGD_RULES = false;
 
     // TODO: create better separation between radio types and network types
 
@@ -414,6 +417,8 @@
 
     private SettingsObserver mSettingsObserver;
 
+    private AppOpsManager mAppOpsManager;
+
     NetworkConfig[] mNetConfigs;
     int mNetworksDefined;
 
@@ -697,6 +702,8 @@
         filter = new IntentFilter();
         filter.addAction(CONNECTED_TO_PROVISIONING_NETWORK_ACTION);
         mContext.registerReceiver(mProvisioningReceiver, filter);
+
+        mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
     }
 
     /**
@@ -1531,6 +1538,40 @@
     }
 
     /**
+     * Check if the address falls into any of currently running VPN's route's.
+     */
+    private boolean isAddressUnderVpn(InetAddress address) {
+        synchronized (mVpns) {
+            synchronized (mRoutesLock) {
+                int uid = UserHandle.getCallingUserId();
+                Vpn vpn = mVpns.get(uid);
+                if (vpn == null) {
+                    return false;
+                }
+
+                // Check if an exemption exists for this address.
+                for (LinkAddress destination : mExemptAddresses) {
+                    if (!NetworkUtils.addressTypeMatches(address, destination.getAddress())) {
+                        continue;
+                    }
+
+                    int prefix = destination.getNetworkPrefixLength();
+                    InetAddress addrMasked = NetworkUtils.getNetworkPart(address, prefix);
+                    InetAddress destMasked = NetworkUtils.getNetworkPart(destination.getAddress(),
+                            prefix);
+
+                    if (addrMasked.equals(destMasked)) {
+                        return false;
+                    }
+                }
+
+                // Finally check if the address is covered by the VPN.
+                return vpn.isAddressCovered(address);
+            }
+        }
+    }
+
+    /**
      * @deprecated use requestRouteToHostAddress instead
      *
      * Ensure that a network route exists to deliver traffic to the specified
@@ -1541,14 +1582,14 @@
      * desired
      * @return {@code true} on success, {@code false} on failure
      */
-    public boolean requestRouteToHost(int networkType, int hostAddress) {
+    public boolean requestRouteToHost(int networkType, int hostAddress, String packageName) {
         InetAddress inetAddress = NetworkUtils.intToInetAddress(hostAddress);
 
         if (inetAddress == null) {
             return false;
         }
 
-        return requestRouteToHostAddress(networkType, inetAddress.getAddress());
+        return requestRouteToHostAddress(networkType, inetAddress.getAddress(), packageName);
     }
 
     /**
@@ -1560,11 +1601,40 @@
      * desired
      * @return {@code true} on success, {@code false} on failure
      */
-    public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) {
+    public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress,
+            String packageName) {
         enforceChangePermission();
         if (mProtectedNetworks.contains(networkType)) {
             enforceConnectivityInternalPermission();
         }
+        boolean exempt;
+        InetAddress addr;
+        try {
+            addr = InetAddress.getByAddress(hostAddress);
+        } catch (UnknownHostException e) {
+            if (DBG) log("requestRouteToHostAddress got " + e.toString());
+            return false;
+        }
+        // System apps may request routes bypassing the VPN to keep other networks working.
+        if (Binder.getCallingUid() == Process.SYSTEM_UID) {
+            exempt = true;
+        } else {
+            mAppOpsManager.checkPackage(Binder.getCallingUid(), packageName);
+            try {
+                ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(packageName,
+                        0);
+                exempt = (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+            } catch (NameNotFoundException e) {
+                throw new IllegalArgumentException("Failed to find calling package details", e);
+            }
+        }
+
+        // Non-exempt routeToHost's can only be added if the host is not covered by the VPN.
+        // This can be either because the VPN's routes do not cover the destination or a
+        // system application added an exemption that covers this destination.
+        if (!exempt && isAddressUnderVpn(addr)) {
+            return false;
+        }
 
         if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
             if (DBG) log("requestRouteToHostAddress on invalid network: " + networkType);
@@ -1591,18 +1661,13 @@
         }
         final long token = Binder.clearCallingIdentity();
         try {
-            InetAddress addr = InetAddress.getByAddress(hostAddress);
             LinkProperties lp = tracker.getLinkProperties();
-            boolean ok = addRouteToAddress(lp, addr, EXEMPT);
+            boolean ok = addRouteToAddress(lp, addr, exempt);
             if (DBG) log("requestRouteToHostAddress ok=" + ok);
             return ok;
-        } catch (UnknownHostException e) {
-            if (DBG) log("requestRouteToHostAddress got " + e.toString());
         } finally {
             Binder.restoreCallingIdentity(token);
         }
-        if (DBG) log("requestRouteToHostAddress X bottom return false");
-        return false;
     }
 
     private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable,
@@ -1921,7 +1986,9 @@
         mNetTrackers[prevNetType].setTeardownRequested(false);
 
         // Remove idletimer previously setup in {@code handleConnect}
-        removeDataActivityTracking(prevNetType);
+        if (mNetConfigs[prevNetType].isDefault()) {
+            removeDataActivityTracking(prevNetType);
+        }
 
         /*
          * If the disconnected network is not the active one, then don't report
@@ -2253,8 +2320,6 @@
     private void handleConnect(NetworkInfo info) {
         final int newNetType = info.getType();
 
-        setupDataActivityTracking(newNetType);
-
         // snapshot isFailover, because sendConnectedBroadcast() resets it
         boolean isFailover = info.isFailover();
         final NetworkStateTracker thisNet = mNetTrackers[newNetType];
@@ -2292,6 +2357,7 @@
                         return;
                 }
             }
+            setupDataActivityTracking(newNetType);
             synchronized (ConnectivityService.this) {
                 // have a new default network, release the transition wakelock in a second
                 // if it's held.  The second pause is to allow apps to reconnect over the
@@ -2312,9 +2378,9 @@
             mInetConditionChangeInFlight = false;
             // Don't do this - if we never sign in stay, grey
             //reportNetworkCondition(mActiveDefaultNetwork, 100);
+            updateNetworkSettings(thisNet);
         }
         thisNet.setTeardownRequested(false);
-        updateNetworkSettings(thisNet);
         updateMtuSizeSettings(thisNet);
         handleConnectivityChange(newNetType, false);
         sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay());
@@ -2341,7 +2407,7 @@
      * Setup data activity tracking for the given network interface.
      *
      * Every {@code setupDataActivityTracking} should be paired with a
-     * {@link removeDataActivityTracking} for cleanup.
+     * {@link #removeDataActivityTracking} for cleanup.
      */
     private void setupDataActivityTracking(int type) {
         final NetworkStateTracker thisNet = mNetTrackers[type];
@@ -2366,7 +2432,7 @@
 
         if (timeout > 0 && iface != null) {
             try {
-                mNetd.addIdleTimer(iface, timeout, Integer.toString(type));
+                mNetd.addIdleTimer(iface, timeout, type);
             } catch (RemoteException e) {
             }
         }
@@ -2669,6 +2735,15 @@
             }
             setBufferSize(bufferSizes);
         }
+
+        final String defaultRwndKey = "net.tcp.default_init_rwnd";
+        int defaultRwndValue = SystemProperties.getInt(defaultRwndKey, 0);
+        Integer rwndValue = Settings.Global.getInt(mContext.getContentResolver(),
+            Settings.Global.TCP_DEFAULT_INIT_RWND, defaultRwndValue);
+        final String sysctlKey = "sys.sysctl.tcp_def_init_rwnd";
+        if (rwndValue != 0) {
+            SystemProperties.set(sysctlKey, rwndValue.toString());
+        }
     }
 
     /**
@@ -2870,6 +2945,9 @@
             }
         }
 
+        pw.print("Active default network: "); pw.println(getNetworkTypeName(mActiveDefaultNetwork));
+        pw.println();
+
         pw.println("Network Requester Pids:");
         pw.increaseIndent();
         for (int net : mPriorityList) {
@@ -3008,7 +3086,7 @@
                 case NetworkStateTracker.EVENT_NETWORK_SUBTYPE_CHANGED: {
                     info = (NetworkInfo) msg.obj;
                     int type = info.getType();
-                    updateNetworkSettings(mNetTrackers[type]);
+                    if (mNetConfigs[type].isDefault()) updateNetworkSettings(mNetTrackers[type]);
                     break;
                 }
             }
@@ -3567,8 +3645,7 @@
             int user = UserHandle.getUserId(Binder.getCallingUid());
             if (ConnectivityManager.isNetworkTypeValid(type) && mNetTrackers[type] != null) {
                 synchronized(mVpns) {
-                    mVpns.get(user).protect(socket,
-                            mNetTrackers[type].getLinkProperties().getInterfaceName());
+                    mVpns.get(user).protect(socket);
                 }
                 return true;
             }
@@ -4325,7 +4402,7 @@
 
                             // Make a route to host so we check the specific interface.
                             if (mCs.requestRouteToHostAddress(ConnectivityManager.TYPE_MOBILE_HIPRI,
-                                    hostAddr.getAddress())) {
+                                    hostAddr.getAddress(), null)) {
                                 // Wait a short time to be sure the route is established ??
                                 log("isMobileOk:"
                                         + " wait to establish route to hostAddr=" + hostAddr);
@@ -4495,7 +4572,6 @@
          * @param seconds
          */
         private static void sleep(int seconds) {
-            log("XXXXX sleeping for " + seconds + " sec");
             long stopTime = System.nanoTime() + (seconds * 1000000000);
             long sleepTime;
             while ((sleepTime = stopTime - System.nanoTime()) > 0) {
@@ -4504,7 +4580,6 @@
                 } catch (InterruptedException ignored) {
                 }
             }
-            log("XXXXX returning from sleep");
         }
 
         private static void log(String s) {
diff --git a/services/core/java/com/android/server/INativeDaemonConnectorCallbacks.java b/services/core/java/com/android/server/INativeDaemonConnectorCallbacks.java
index 6fbf713..0cf9dcd 100644
--- a/services/core/java/com/android/server/INativeDaemonConnectorCallbacks.java
+++ b/services/core/java/com/android/server/INativeDaemonConnectorCallbacks.java
@@ -20,5 +20,6 @@
 interface INativeDaemonConnectorCallbacks {
 
     void onDaemonConnected();
+    boolean onCheckHoldWakeLock(int code);
     boolean onEvent(int code, String raw, String[] cooked);
 }
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index fc68205..3dcb488 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -1790,10 +1790,6 @@
 
     @Override
     public boolean isProviderEnabled(String provider) {
-        // TODO: remove this check in next release, see b/10696351
-        checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
-                provider);
-
         // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
         // so we discourage its use
         if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
@@ -2231,6 +2227,13 @@
     public void removeTestProvider(String provider) {
         checkMockPermissionsSafe();
         synchronized (mLock) {
+
+            // These methods can't be called after removing the test provider, so first make sure
+            // we don't leave anything dangling.
+            clearTestProviderEnabled(provider);
+            clearTestProviderLocation(provider);
+            clearTestProviderStatus(provider);
+
             MockProvider mockProvider = mMockProviders.remove(provider);
             if (mockProvider == null) {
                 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 607def6..a7ef424 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -817,6 +817,13 @@
     /**
      * Callback from NativeDaemonConnector
      */
+    public boolean onCheckHoldWakeLock(int code) {
+        return false;
+    }
+
+    /**
+     * Callback from NativeDaemonConnector
+     */
     public boolean onEvent(int code, String raw, String[] cooked) {
         if (DEBUG_EVENTS) {
             StringBuilder builder = new StringBuilder();
@@ -1407,7 +1414,8 @@
          * amount of containers we'd ever expect to have. This keeps an
          * "asec list" from blocking a thread repeatedly.
          */
-        mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25);
+        mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25,
+                null);
 
         Thread thread = new Thread(mConnector, VOLD_TAG);
         thread.start();
diff --git a/services/core/java/com/android/server/NativeDaemonConnector.java b/services/core/java/com/android/server/NativeDaemonConnector.java
index 417d6d8..265b957 100644
--- a/services/core/java/com/android/server/NativeDaemonConnector.java
+++ b/services/core/java/com/android/server/NativeDaemonConnector.java
@@ -21,6 +21,7 @@
 import android.os.Build;
 import android.os.Handler;
 import android.os.Message;
+import android.os.PowerManager;
 import android.os.SystemClock;
 import android.util.LocalLog;
 import android.util.Slog;
@@ -56,6 +57,8 @@
 
     private final ResponseQueue mResponseQueue;
 
+    private final PowerManager.WakeLock mWakeLock;
+
     private INativeDaemonConnectorCallbacks mCallbacks;
     private Handler mCallbackHandler;
 
@@ -70,10 +73,14 @@
     private final int BUFFER_SIZE = 4096;
 
     NativeDaemonConnector(INativeDaemonConnectorCallbacks callbacks, String socket,
-            int responseQueueSize, String logTag, int maxLogSize) {
+            int responseQueueSize, String logTag, int maxLogSize, PowerManager.WakeLock wl) {
         mCallbacks = callbacks;
         mSocket = socket;
         mResponseQueue = new ResponseQueue(responseQueueSize);
+        mWakeLock = wl;
+        if (mWakeLock != null) {
+            mWakeLock.setReferenceCounted(true);
+        }
         mSequenceNumber = new AtomicInteger(0);
         TAG = logTag != null ? logTag : "NativeDaemonConnector";
         mLocalLog = new LocalLog(maxLogSize);
@@ -102,6 +109,10 @@
             }
         } catch (Exception e) {
             loge("Error handling '" + event + "': " + e);
+        } finally {
+            if (mCallbacks.onCheckHoldWakeLock(msg.what)) {
+                mWakeLock.release();
+            }
         }
         return true;
     }
@@ -154,18 +165,29 @@
                                 buffer, start, i - start, StandardCharsets.UTF_8);
                         log("RCV <- {" + rawEvent + "}");
 
+                        boolean releaseWl = false;
                         try {
                             final NativeDaemonEvent event = NativeDaemonEvent.parseRawEvent(
                                     rawEvent);
                             if (event.isClassUnsolicited()) {
                                 // TODO: migrate to sending NativeDaemonEvent instances
-                                mCallbackHandler.sendMessage(mCallbackHandler.obtainMessage(
-                                        event.getCode(), event.getRawEvent()));
+                                if (mCallbacks.onCheckHoldWakeLock(event.getCode())) {
+                                    mWakeLock.acquire();
+                                    releaseWl = true;
+                                }
+                                if (mCallbackHandler.sendMessage(mCallbackHandler.obtainMessage(
+                                        event.getCode(), event.getRawEvent()))) {
+                                    releaseWl = false;
+                                }
                             } else {
                                 mResponseQueue.add(event.getCmdNumber(), event);
                             }
                         } catch (IllegalArgumentException e) {
                             log("Problem parsing message: " + rawEvent + " - " + e);
+                        } finally {
+                            if (releaseWl) {
+                                mWakeLock.acquire();
+                            }
                         }
 
                         start = i + 1;
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 3924fe8..bfc966b 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -20,6 +20,7 @@
 import static android.Manifest.permission.DUMP;
 import static android.Manifest.permission.SHUTDOWN;
 import static android.net.NetworkStats.SET_DEFAULT;
+import static android.net.NetworkStats.TAG_ALL;
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
 import static android.net.TrafficStats.UID_TETHERING;
@@ -36,6 +37,7 @@
 import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
 
 import android.content.Context;
+import android.net.ConnectivityManager;
 import android.net.INetworkManagementEventObserver;
 import android.net.InterfaceConfiguration;
 import android.net.LinkAddress;
@@ -47,7 +49,9 @@
 import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.Handler;
+import android.os.INetworkActivityListener;
 import android.os.INetworkManagementService;
+import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
@@ -80,7 +84,6 @@
 import java.net.NetworkInterface;
 import java.net.SocketException;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -174,12 +177,12 @@
     /** Set of interfaces with active idle timers. */
     private static class IdleTimerParams {
         public final int timeout;
-        public final String label;
+        public final int type;
         public int networkCount;
 
-        IdleTimerParams(int timeout, String label) {
+        IdleTimerParams(int timeout, int type) {
             this.timeout = timeout;
-            this.label = label;
+            this.type = type;
             this.networkCount = 1;
         }
     }
@@ -188,6 +191,10 @@
     private volatile boolean mBandwidthControlEnabled;
     private volatile boolean mFirewallEnabled;
 
+    private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners =
+            new RemoteCallbackList<INetworkActivityListener>();
+    private boolean mNetworkActive;
+
     /**
      * Constructs a new NetworkManagementService instance
      *
@@ -200,8 +207,11 @@
             return;
         }
 
+        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+        PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NETD_TAG);
+
         mConnector = new NativeDaemonConnector(
-                new NetdCallbackReceiver(), socket, 10, NETD_TAG, 160);
+                new NetdCallbackReceiver(), socket, 10, NETD_TAG, 160, wl);
         mThread = new Thread(mConnector, NETD_TAG);
 
         // Add ourself to the Watchdog monitors.
@@ -336,20 +346,38 @@
     /**
      * Notify our observers of a change in the data activity state of the interface
      */
-    private void notifyInterfaceClassActivity(String label, boolean active) {
+    private void notifyInterfaceClassActivity(int type, boolean active) {
         try {
-            getBatteryStats().noteDataConnectionActive(label, active);
+            getBatteryStats().noteDataConnectionActive(type, active);
         } catch (RemoteException e) {
         }
+
         final int length = mObservers.beginBroadcast();
         for (int i = 0; i < length; i++) {
             try {
-                mObservers.getBroadcastItem(i).interfaceClassDataActivityChanged(label, active);
+                mObservers.getBroadcastItem(i).interfaceClassDataActivityChanged(
+                        Integer.toString(type), active);
             } catch (RemoteException e) {
             } catch (RuntimeException e) {
             }
         }
         mObservers.finishBroadcast();
+
+        boolean report = false;
+        synchronized (mIdleTimerLock) {
+            if (mActiveIdleTimers.isEmpty()) {
+                // If there are no idle times, we are not monitoring activity, so we
+                // are always considered active.
+                active = true;
+            }
+            if (mNetworkActive != active) {
+                mNetworkActive = active;
+                report = active;
+            }
+        }
+        if (report) {
+            reportNetworkActive();
+        }
     }
 
     /**
@@ -487,6 +515,11 @@
         }
 
         @Override
+        public boolean onCheckHoldWakeLock(int code) {
+            return code == NetdResponseCode.InterfaceClassActivity;
+        }
+
+        @Override
         public boolean onEvent(int code, String raw, String[] cooked) {
             String errorMessage = String.format("Invalid event from daemon (%s)", raw);
             switch (code) {
@@ -539,7 +572,7 @@
                         throw new IllegalStateException(errorMessage);
                     }
                     boolean isActive = cooked[2].equals("active");
-                    notifyInterfaceClassActivity(cooked[3], isActive);
+                    notifyInterfaceClassActivity(Integer.parseInt(cooked[3]), isActive);
                     return true;
                     // break;
             case NetdResponseCode.InterfaceAddressChange:
@@ -1201,7 +1234,7 @@
     }
 
     @Override
-    public void addIdleTimer(String iface, int timeout, String label) {
+    public void addIdleTimer(String iface, int timeout, final int type) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
         if (DBG) Slog.d(TAG, "Adding idletimer");
@@ -1215,13 +1248,22 @@
             }
 
             try {
-                mConnector.execute("idletimer", "add", iface, Integer.toString(timeout), label);
+                mConnector.execute("idletimer", "add", iface, Integer.toString(timeout),
+                        Integer.toString(type));
             } catch (NativeDaemonConnectorException e) {
                 throw e.rethrowAsParcelableException();
             }
-            mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, label));
+            mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type));
+
             // Networks start up.
-            notifyInterfaceClassActivity(label, true);
+            if (ConnectivityManager.isNetworkTypeMobile(type)) {
+                mNetworkActive = false;
+            }
+            mMainHandler.post(new Runnable() {
+                @Override public void run() {
+                    notifyInterfaceClassActivity(type, true);
+                }
+            });
         }
     }
 
@@ -1232,18 +1274,23 @@
         if (DBG) Slog.d(TAG, "Removing idletimer");
 
         synchronized (mIdleTimerLock) {
-            IdleTimerParams params = mActiveIdleTimers.get(iface);
+            final IdleTimerParams params = mActiveIdleTimers.get(iface);
             if (params == null || --(params.networkCount) > 0) {
                 return;
             }
 
             try {
                 mConnector.execute("idletimer", "remove", iface,
-                        Integer.toString(params.timeout), params.label);
+                        Integer.toString(params.timeout), Integer.toString(params.type));
             } catch (NativeDaemonConnectorException e) {
                 throw e.rethrowAsParcelableException();
             }
             mActiveIdleTimers.remove(iface);
+            mMainHandler.post(new Runnable() {
+                @Override public void run() {
+                    notifyInterfaceClassActivity(params.type, false);
+                }
+            });
         }
     }
 
@@ -1271,7 +1318,7 @@
     public NetworkStats getNetworkStatsDetail() {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         try {
-            return mStatsFactory.readNetworkStatsDetail(UID_ALL);
+            return mStatsFactory.readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null);
         } catch (IOException e) {
             throw new IllegalStateException(e);
         }
@@ -1432,7 +1479,7 @@
     public NetworkStats getNetworkStatsUidDetail(int uid) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         try {
-            return mStatsFactory.readNetworkStatsDetail(uid);
+            return mStatsFactory.readNetworkStatsDetail(uid, null, TAG_ALL, null);
         } catch (IOException e) {
             throw new IllegalStateException(e);
         }
@@ -1802,6 +1849,35 @@
         return event.getMessage().endsWith("started");
     }
 
+    @Override
+    public void registerNetworkActivityListener(INetworkActivityListener listener) {
+        mNetworkActivityListeners.register(listener);
+    }
+
+    @Override
+    public void unregisterNetworkActivityListener(INetworkActivityListener listener) {
+        mNetworkActivityListeners.unregister(listener);
+    }
+
+    @Override
+    public boolean isNetworkActive() {
+        synchronized (mNetworkActivityListeners) {
+            return mNetworkActive || mActiveIdleTimers.isEmpty();
+        }
+    }
+
+    private void reportNetworkActive() {
+        final int length = mNetworkActivityListeners.beginBroadcast();
+        for (int i = 0; i < length; i++) {
+            try {
+                mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive();
+            } catch (RemoteException e) {
+            } catch (RuntimeException e) {
+            }
+        }
+        mNetworkActivityListeners.finishBroadcast();
+    }
+
     /** {@inheritDoc} */
     @Override
     public void monitor() {
@@ -1835,6 +1911,17 @@
             pw.println("]");
         }
 
+        synchronized (mIdleTimerLock) {
+            pw.println("Idle timers:");
+            for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) {
+                pw.print("  "); pw.print(ent.getKey()); pw.println(":");
+                IdleTimerParams params = ent.getValue();
+                pw.print("    timeout="); pw.print(params.timeout);
+                pw.print(" type="); pw.print(params.type);
+                pw.print(" networkCount="); pw.println(params.networkCount);
+            }
+        }
+
         pw.print("Firewall enabled: "); pw.println(mFirewallEnabled);
     }
 }
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index 74633ae..c9f9a25 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -534,7 +534,7 @@
         mContentResolver = context.getContentResolver();
 
         mNativeConnector = new NativeDaemonConnector(new NativeCallbackReceiver(), "mdns", 10,
-                MDNS_TAG, 25);
+                MDNS_TAG, 25, null);
 
         mNsdStateMachine = new NsdStateMachine(TAG);
         mNsdStateMachine.start();
@@ -622,6 +622,10 @@
             mNativeDaemonConnected.countDown();
         }
 
+        public boolean onCheckHoldWakeLock(int code) {
+            return false;
+        }
+
         public boolean onEvent(int code, String raw, String[] cooked) {
             // TODO: NDC translates a message to a callback, we could enhance NDC to
             // directly interact with a state machine through messages
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7b2fc50..d910861 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1073,6 +1073,8 @@
     static final int IMMERSIVE_MODE_LOCK_MSG = 37;
     static final int PERSIST_URI_GRANTS_MSG = 38;
     static final int REQUEST_ALL_PSS_MSG = 39;
+    static final int START_RELATED_USERS_MSG = 40;
+    static final int UPDATE_TIME = 41;
 
     static final int FIRST_ACTIVITY_STACK_MSG = 100;
     static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1686,6 +1688,27 @@
                 requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false);
                 break;
             }
+            case START_RELATED_USERS_MSG: {
+                synchronized (ActivityManagerService.this) {
+                    startRelatedUsersLocked();
+                }
+                break;
+            }
+            case UPDATE_TIME: {
+                synchronized (ActivityManagerService.this) {
+                    for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
+                        ProcessRecord r = mLruProcesses.get(i);
+                        if (r.thread != null) {
+                            try {
+                                r.thread.updateTimePrefs(msg.arg1 == 0 ? false : true);
+                            } catch (RemoteException ex) {
+                                Slog.w(TAG, "Failed to update preferences for: " + r.info.processName);
+                            }
+                        }
+                    }
+                }
+                break;
+            }
             }
         }
     };
@@ -5164,10 +5187,11 @@
                                 userId);
                     }
                 }
+                scheduleStartRelatedUsersLocked();
             }
         }
     }
-    
+
     final void ensureBootCompleted() {
         boolean booting;
         boolean enableScreen;
@@ -5177,7 +5201,7 @@
             enableScreen = !mBooted;
             mBooted = true;
         }
-        
+
         if (booting) {
             finishBooting();
         }
@@ -5547,6 +5571,38 @@
     }
 
     @Override
+    public String getTagForIntentSender(IIntentSender pendingResult, String prefix) {
+        if (!(pendingResult instanceof PendingIntentRecord)) {
+            return null;
+        }
+        try {
+            PendingIntentRecord res = (PendingIntentRecord)pendingResult;
+            Intent intent = res.key.requestIntent;
+            if (intent != null) {
+                if (res.lastTag != null && res.lastTagPrefix == prefix && (res.lastTagPrefix == null
+                        || res.lastTagPrefix.equals(prefix))) {
+                    return res.lastTag;
+                }
+                res.lastTagPrefix = prefix;
+                StringBuilder sb = new StringBuilder(128);
+                if (prefix != null) {
+                    sb.append(prefix);
+                }
+                if (intent.getAction() != null) {
+                    sb.append(intent.getAction());
+                } else if (intent.getComponent() != null) {
+                    intent.getComponent().appendShortString(sb);
+                } else {
+                    sb.append("?");
+                }
+                return res.lastTag = sb.toString();
+            }
+        } catch (ClassCastException e) {
+        }
+        return null;
+    }
+
+    @Override
     public void setProcessLimit(int max) {
         enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
                 "setProcessLimit()");
@@ -7107,6 +7163,15 @@
     }
 
     @Override
+    public void deleteActivityContainer(IActivityContainer container) throws RemoteException {
+        enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+                "deleteActivityContainer()");
+        synchronized (this) {
+            mStackSupervisor.deleteActivityContainer(container);
+        }
+    }
+
+    @Override
     public IActivityContainer getEnclosingActivityContainer(IBinder activityToken)
             throws RemoteException {
         synchronized (this) {
@@ -9163,8 +9228,13 @@
                         ActivityInfo ai = ris.get(i).activityInfo;
                         ComponentName comp = new ComponentName(ai.packageName, ai.name);
                         if (lastDoneReceivers.contains(comp)) {
+                            // We already did the pre boot receiver for this app with the current
+                            // platform version, so don't do it again...
                             ris.remove(i);
                             i--;
+                            // ...however, do keep it as one that has been done, so we don't
+                            // forget about it when rewriting the file of last done receivers.
+                            doneReceivers.add(comp);
                         }
                     }
 
@@ -13392,11 +13462,20 @@
          * of all currently running processes. This message will get queued up before the broadcast
          * happens.
          */
-        if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
+        if (Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
             mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
         }
 
-        if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
+        /*
+         * If the user set the time, let all running processes know.
+         */
+        if (Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) {
+            final int is24Hour = intent.getBooleanExtra(
+                    Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, false) ? 1 : 0;
+            mHandler.sendMessage(mHandler.obtainMessage(UPDATE_TIME, is24Hour, 0));
+        }
+
+        if (Intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
             mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG);
         }
 
@@ -16040,8 +16119,20 @@
 
     // Multi-user methods
 
+    /**
+     * Start user, if its not already running, but don't bring it to foreground.
+     */
+    @Override
+    public boolean startUserInBackground(final int userId) {
+        return startUser(userId, /* foreground */ false);
+    }
+
     @Override
     public boolean switchUser(final int userId) {
+        return startUser(userId, /* foregound */ true);
+    }
+
+    private boolean startUser(final int userId, boolean foreground) {
         if (checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
                 != PackageManager.PERMISSION_GRANTED) {
             String msg = "Permission Denial: switchUser() from pid="
@@ -16052,6 +16143,8 @@
             throw new SecurityException(msg);
         }
 
+        if (DEBUG_MU) Slog.i(TAG_MU, "starting userid:" + userId + " fore:" + foreground);
+
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized (this) {
@@ -16066,8 +16159,10 @@
                     return false;
                 }
 
-                mWindowManager.startFreezingScreen(R.anim.screen_user_exit,
-                        R.anim.screen_user_enter);
+                if (foreground) {
+                    mWindowManager.startFreezingScreen(R.anim.screen_user_exit,
+                            R.anim.screen_user_enter);
+                }
 
                 boolean needStart = false;
 
@@ -16079,16 +16174,21 @@
                     needStart = true;
                 }
 
-                mCurrentUserId = userId;
                 final Integer userIdInt = Integer.valueOf(userId);
                 mUserLru.remove(userIdInt);
                 mUserLru.add(userIdInt);
 
-                mWindowManager.setCurrentUser(userId);
-
-                // Once the internal notion of the active user has switched, we lock the device
-                // with the option to show the user switcher on the keyguard.
-                mWindowManager.lockNow(null);
+                if (foreground) {
+                    mCurrentUserId = userId;
+                    mWindowManager.setCurrentUser(userId);
+                    // Once the internal notion of the active user has switched, we lock the device
+                    // with the option to show the user switcher on the keyguard.
+                    mWindowManager.lockNow(null);
+                } else {
+                    final Integer currentUserIdInt = Integer.valueOf(mCurrentUserId);
+                    mUserLru.remove(currentUserIdInt);
+                    mUserLru.add(currentUserIdInt);
+                }
 
                 final UserStartedState uss = mStartedUsers.get(userId);
 
@@ -16109,12 +16209,15 @@
                     needStart = true;
                 }
 
-                mHandler.removeMessages(REPORT_USER_SWITCH_MSG);
-                mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG);
-                mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_MSG,
-                        oldUserId, userId, uss));
-                mHandler.sendMessageDelayed(mHandler.obtainMessage(USER_SWITCH_TIMEOUT_MSG,
-                        oldUserId, userId, uss), USER_SWITCH_TIMEOUT);
+                if (foreground) {
+                    mHandler.removeMessages(REPORT_USER_SWITCH_MSG);
+                    mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG);
+                    mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_MSG,
+                            oldUserId, userId, uss));
+                    mHandler.sendMessageDelayed(mHandler.obtainMessage(USER_SWITCH_TIMEOUT_MSG,
+                            oldUserId, userId, uss), USER_SWITCH_TIMEOUT);
+                }
+
                 if (needStart) {
                     Intent intent = new Intent(Intent.ACTION_USER_STARTED);
                     intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
@@ -16145,16 +16248,18 @@
                     }
                 }
 
-                boolean homeInFront = mStackSupervisor.switchUserLocked(userId, uss);
-                if (homeInFront) {
-                    startHomeActivityLocked(userId);
-                } else {
-                    mStackSupervisor.resumeTopActivitiesLocked();
+                if (foreground) {
+                    boolean homeInFront = mStackSupervisor.switchUserLocked(userId, uss);
+                    if (homeInFront) {
+                        startHomeActivityLocked(userId);
+                    } else {
+                        mStackSupervisor.resumeTopActivitiesLocked();
+                    }
+                    EventLogTags.writeAmSwitchUser(userId);
+                    getUserManagerLocked().userForeground(userId);
+                    sendUserSwitchBroadcastsLocked(oldUserId, userId);
                 }
 
-                EventLogTags.writeAmSwitchUser(userId);
-                getUserManagerLocked().userForeground(userId);
-                sendUserSwitchBroadcastsLocked(oldUserId, userId);
                 if (needStart) {
                     Intent intent = new Intent(Intent.ACTION_USER_STARTING);
                     intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
@@ -16300,6 +16405,32 @@
         }
     }
 
+    void scheduleStartRelatedUsersLocked() {
+        if (!mHandler.hasMessages(START_RELATED_USERS_MSG)) {
+            mHandler.sendMessageDelayed(mHandler.obtainMessage(START_RELATED_USERS_MSG),
+                    DateUtils.SECOND_IN_MILLIS);
+        }
+    }
+
+    void startRelatedUsersLocked() {
+        if (DEBUG_MU) Slog.i(TAG_MU, "startRelatedUsersLocked");
+        List<UserInfo> relatedUsers = getUserManagerLocked().getRelatedUsers(mCurrentUserId);
+        List<UserInfo> toStart = new ArrayList<UserInfo>(relatedUsers.size());
+        for (UserInfo relatedUser : relatedUsers) {
+            if ((relatedUser.flags & UserInfo.FLAG_INITIALIZED) == UserInfo.FLAG_INITIALIZED) {
+                toStart.add(relatedUser);
+            }
+        }
+        final int n = toStart.size();
+        int i = 0;
+        for (; i < n && i < (MAX_RUNNING_USERS - 1); ++i) {
+            startUserInBackground(toStart.get(i).id);
+        }
+        if (i < n) {
+            Slog.w(TAG_MU, "More related users than MAX_RUNNING_USERS");
+        }
+    }
+
     void finishUserSwitch(UserStartedState uss) {
         synchronized (this) {
             if (uss.mState == UserStartedState.STATE_BOOTING
@@ -16314,6 +16445,9 @@
                         android.Manifest.permission.RECEIVE_BOOT_COMPLETED, AppOpsManager.OP_NONE,
                         true, false, MY_PID, Process.SYSTEM_UID, userId);
             }
+
+            startRelatedUsersLocked();
+
             int num = mUserLru.size();
             int i = 0;
             while (num > MAX_RUNNING_USERS && i < mUserLru.size()) {
@@ -16365,6 +16499,7 @@
     }
 
     private int stopUserLocked(final int userId, final IStopUserCallback callback) {
+        if (DEBUG_MU) Slog.i(TAG_MU, "stopUserLocked userId=" + userId);
         if (mCurrentUserId == userId) {
             return ActivityManager.USER_OP_IS_CURRENT;
         }
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 98bb357..5d23fc3 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -598,7 +598,7 @@
             int requestCode, int resultCode,
             Intent resultData) {
         ActivityResult r = new ActivityResult(from, resultWho,
-        		requestCode, resultCode, resultData);
+                requestCode, resultCode, resultData);
         if (results == null) {
             results = new ArrayList<ResultInfo>();
         }
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 77bb1a9..922cef4 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1235,12 +1235,14 @@
             mUndrawnActivitiesBelowTopTranslucent.clear();
             mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG);
 
-            if (waitingActivity != null && waitingActivity.app != null &&
-                    waitingActivity.app.thread != null) {
-                try {
-                    waitingActivity.app.thread.scheduleTranslucentConversionComplete(
-                            waitingActivity.appToken, r != null);
-                } catch (RemoteException e) {
+            if (waitingActivity != null) {
+                mWindowManager.setWindowOpaque(waitingActivity.appToken, false);
+                if (waitingActivity.app != null && waitingActivity.app.thread != null) {
+                    try {
+                        waitingActivity.app.thread.scheduleTranslucentConversionComplete(
+                                waitingActivity.appToken, r != null);
+                    } catch (RemoteException e) {
+                    }
                 }
             }
         }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 6ed30d9..9636de7 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -523,7 +523,7 @@
     }
 
     void pauseChildStacks(ActivityRecord parent, boolean userLeaving, boolean uiSleeping) {
-		// TODO: Put all stacks in supervisor and iterate through them instead.
+        // TODO: Put all stacks in supervisor and iterate through them instead.
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
@@ -1376,8 +1376,15 @@
 
     void setFocusedStack(ActivityRecord r) {
         if (r != null) {
-            final boolean isHomeActivity =
-                    !r.isApplicationActivity() || (r.task != null && !r.task.isApplicationTask());
+            final TaskRecord task = r.task;
+            boolean isHomeActivity = !r.isApplicationActivity();
+            if (!isHomeActivity && task != null) {
+                isHomeActivity = !task.isApplicationTask();
+            }
+            if (!isHomeActivity && task != null) {
+                final ActivityRecord parent = task.stack.mActivityContainer.mParentActivity;
+                isHomeActivity = parent != null && parent.isHomeActivity();
+            }
             moveHomeStack(isHomeActivity);
         }
     }
@@ -2059,17 +2066,21 @@
         if (targetStack == null) {
             targetStack = getFocusedStack();
         }
+        // Do targetStack first.
         boolean result = false;
+        if (isFrontStack(targetStack)) {
+            result = targetStack.resumeTopActivityLocked(target, targetOptions);
+        }
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
             final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 final ActivityStack stack = stacks.get(stackNdx);
+                if (stack == targetStack) {
+                    // Already started above.
+                    continue;
+                }
                 if (isFrontStack(stack)) {
-                    if (stack == targetStack) {
-                        result = stack.resumeTopActivityLocked(target, targetOptions);
-                    } else {
-                        stack.resumeTopActivityLocked(null);
-                    }
+                    stack.resumeTopActivityLocked(null);
                 }
             }
         }
@@ -2169,13 +2180,28 @@
             ActivityRecord top = stack.topRunningNonDelayedActivityLocked(null);
             if (top != null) {
                 // TODO: Make sure the next activity doesn't start up when top is destroyed.
-                stack.destroyActivityLocked(top, true, true, "stack removal");
+                stack.destroyActivityLocked(top, true, true, "stack parent destroyed");
             }
             mActivityContainers.removeAt(ndx);
             container.detachLocked();
         }
     }
 
+    void deleteActivityContainer(IActivityContainer container) {
+        ActivityContainer activityContainer = (ActivityContainer)container;
+        if (activityContainer != null) {
+            activityContainer.mStack.destroyActivitiesLocked(null, true,
+                    "deleteActivityContainer");
+            final ActivityRecord parent = activityContainer.mParentActivity;
+            if (parent != null) {
+                parent.mChildContainers.remove(activityContainer);
+            }
+            final int stackId = activityContainer.mStackId;
+            mActivityContainers.remove(stackId);
+            mWindowManager.removeStack(stackId);
+        }
+    }
+
     private int createStackOnDisplay(ActivityRecord parentActivity, int stackId, int displayId) {
         ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
         if (activityDisplay == null) {
@@ -2546,6 +2572,7 @@
         pw.print(prefix); pw.println("mSleepTimeout=" + mSleepTimeout);
         pw.print(prefix); pw.println("mCurTaskId=" + mCurTaskId);
         pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront);
+        pw.print(prefix); pw.println("mActivityContainers=" + mActivityContainers);
     }
 
     ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 059aa2b..39bfc23 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -48,6 +48,8 @@
  * battery life.
  */
 public final class BatteryStatsService extends IBatteryStats.Stub {
+    static final String TAG = "BatteryStatsService";
+
     static IBatteryStats sService;
     
     final BatteryStatsImpl mStats;
@@ -66,7 +68,8 @@
         mStats.setRadioScanningTimeout(mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_radioScanningTimeout)
                 * 1000L);
-    }
+        (new WakeupReasonThread()).start();
+     }
     
     public void shutdown() {
         Slog.w("BatteryStats", "Writing battery stats before shutdown...");
@@ -126,11 +129,11 @@
         }
     }
 
-    public void noteStartWakelock(int uid, int pid, String name, int type,
+    public void noteStartWakelock(int uid, int pid, String name, String historyName, int type,
             boolean unimportantForLogging) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteStartWakeLocked(uid, pid, name, type, unimportantForLogging);
+            mStats.noteStartWakeLocked(uid, pid, name, historyName, type, unimportantForLogging);
         }
     }
 
@@ -141,11 +144,12 @@
         }
     }
 
-    public void noteStartWakelockFromSource(WorkSource ws, int pid, String name, int type,
-            boolean unimportantForLogging) {
+    public void noteStartWakelockFromSource(WorkSource ws, int pid, String name,
+            String historyName, int type, boolean unimportantForLogging) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteStartWakeFromSourceLocked(ws, pid, name, type, unimportantForLogging);
+            mStats.noteStartWakeFromSourceLocked(ws, pid, name, historyName,
+                    type, unimportantForLogging);
         }
     }
 
@@ -231,10 +235,10 @@
         }
     }
 
-    public void noteDataConnectionActive(String label, boolean active) {
+    public void noteDataConnectionActive(int type, boolean active) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteDataConnectionActive(label, active);
+            mStats.noteDataConnectionActive(type, active);
         }
     }
 
@@ -537,14 +541,45 @@
         mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
                 Binder.getCallingPid(), Binder.getCallingUid(), null);
     }
-    
+
+    final class WakeupReasonThread extends Thread {
+        final int[] mIrqs = new int[32];
+        final String[] mReasons = new String[32];
+
+        WakeupReasonThread() {
+            super("BatteryStats_wakeupReason");
+        }
+
+        public void run() {
+            Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
+
+            try {
+                int num;
+                while ((num=nativeWaitWakeup(mIrqs, mReasons)) >= 0) {
+                    synchronized (mStats) {
+                        for (int i=0; i<num; i++) {
+                            //Slog.i(TAG, "Wakeup: irq #" + mIrqs[i] + " reason=" + mReasons[i]);
+                            mStats.noteWakeupReasonLocked(mIrqs[i], mReasons[i]);
+                        }
+                    }
+                }
+            } catch (RuntimeException e) {
+                Slog.e(TAG, "Failure reading wakeup reasons", e);
+            }
+        }
+    }
+
+    private static native int nativeWaitWakeup(int[] outIrqs, String[] outReasons);
+
     private void dumpHelp(PrintWriter pw) {
         pw.println("Battery stats (batterystats) dump options:");
-        pw.println("  [--checkin] [--history] [-c] [--unplugged] [--reset] [--write]");
-        pw.println("  [-h] [<package.name>]");
+        pw.println("  [--checkin] [--history] [--history-start] [--unplugged] [--charged] [-c]");
+        pw.println("  [--reset] [--write] [-h] [<package.name>]");
         pw.println("  --checkin: format output for a checkin report.");
         pw.println("  --history: show only history data.");
+        pw.println("  --history-start <num>: show only history data starting at given time offset.");
         pw.println("  --unplugged: only output data since last unplugged.");
+        pw.println("  --charged: only output data since last charged.");
         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.");
@@ -561,23 +596,34 @@
             return;
         }
 
+        int flags = 0;
         boolean isCheckin = false;
-        boolean includeHistory = false;
-        boolean historyOnly = false;
-        boolean isUnpluggedOnly = false;
         boolean noOutput = false;
+        long historyStart = -1;
         int reqUid = -1;
         if (args != null) {
-            for (String arg : args) {
+            for (int i=0; i<args.length; i++) {
+                String arg = args[i];
                 if ("--checkin".equals(arg)) {
                     isCheckin = true;
                 } else if ("--history".equals(arg)) {
-                    historyOnly = true;
+                    flags |= BatteryStats.DUMP_HISTORY_ONLY;
+                } else if ("--history-start".equals(arg)) {
+                    flags |= BatteryStats.DUMP_HISTORY_ONLY;
+                    i++;
+                    if (i >= args.length) {
+                        pw.println("Missing time argument for --history-since");
+                        dumpHelp(pw);
+                        return;
+                    }
+                    historyStart = Long.parseLong(args[i]);
                 } else if ("-c".equals(arg)) {
                     isCheckin = true;
-                    includeHistory = true;
+                    flags |= BatteryStats.DUMP_INCLUDE_HISTORY;
                 } else if ("--unplugged".equals(arg)) {
-                    isUnpluggedOnly = true;
+                    flags |= BatteryStats.DUMP_UNPLUGGED_ONLY;
+                } else if ("--charged".equals(arg)) {
+                    flags |= BatteryStats.DUMP_CHARGED_ONLY;
                 } else if ("--reset".equals(arg)) {
                     synchronized (mStats) {
                         mStats.resetAllStatsCmdLocked();
@@ -618,12 +664,11 @@
         if (isCheckin) {
             List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0);
             synchronized (mStats) {
-                mStats.dumpCheckinLocked(mContext, pw, apps, isUnpluggedOnly, includeHistory,
-                        historyOnly);
+                mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart);
             }
         } else {
             synchronized (mStats) {
-                mStats.dumpLocked(mContext, pw, isUnpluggedOnly, reqUid, historyOnly);
+                mStats.dumpLocked(mContext, pw, flags, reqUid, historyStart);
             }
         }
     }
diff --git a/services/core/java/com/android/server/am/CompatModePackages.java b/services/core/java/com/android/server/am/CompatModePackages.java
index 207d630..ec500c2 100644
--- a/services/core/java/com/android/server/am/CompatModePackages.java
+++ b/services/core/java/com/android/server/am/CompatModePackages.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2014 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.am;
 
 import java.io.File;
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 10ea67c..4c887dd 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -37,11 +37,16 @@
     private static final String LOG_TAG = CoreSettingsObserver.class.getSimpleName();
 
     // mapping form property name to its type
-    private static final Map<String, Class<?>> sCoreSettingToTypeMap = new HashMap<
+    private static final Map<String, Class<?>> sSecureSettingToTypeMap = new HashMap<
+            String, Class<?>>();
+    private static final Map<String, Class<?>> sSystemSettingToTypeMap = new HashMap<
             String, Class<?>>();
     static {
-        sCoreSettingToTypeMap.put(Settings.Secure.LONG_PRESS_TIMEOUT, int.class);
-        // add other core settings here...
+        sSecureSettingToTypeMap.put(Settings.Secure.LONG_PRESS_TIMEOUT, int.class);
+        // add other secure settings here...
+
+        sSystemSettingToTypeMap.put(Settings.System.TIME_12_24, String.class);
+        // add other system settings here...
     }
 
     private final Bundle mCoreSettings = new Bundle();
@@ -67,39 +72,62 @@
     }
 
     private void sendCoreSettings() {
-        populateCoreSettings(mCoreSettings);
+        populateSettings(mCoreSettings, sSecureSettingToTypeMap);
+        populateSettings(mCoreSettings, sSystemSettingToTypeMap);
         mActivityManagerService.onCoreSettingsChange(mCoreSettings);
     }
 
     private void beginObserveCoreSettings() {
-        for (String setting : sCoreSettingToTypeMap.keySet()) {
+        for (String setting : sSecureSettingToTypeMap.keySet()) {
             Uri uri = Settings.Secure.getUriFor(setting);
             mActivityManagerService.mContext.getContentResolver().registerContentObserver(
                     uri, false, this);
         }
+
+        for (String setting : sSystemSettingToTypeMap.keySet()) {
+            Uri uri = Settings.System.getUriFor(setting);
+            mActivityManagerService.mContext.getContentResolver().registerContentObserver(
+                    uri, false, this);
+        }
     }
 
-    private void populateCoreSettings(Bundle snapshot) {
+    private void populateSettings(Bundle snapshot, Map<String, Class<?>> map) {
         Context context = mActivityManagerService.mContext;
-        for (Map.Entry<String, Class<?>> entry : sCoreSettingToTypeMap.entrySet()) {
+        for (Map.Entry<String, Class<?>> entry : map.entrySet()) {
             String setting = entry.getKey();
             Class<?> type = entry.getValue();
             try {
                 if (type == String.class) {
-                    String value = Settings.Secure.getString(context.getContentResolver(),
-                            setting);
+                    final String value;
+                    if (map == sSecureSettingToTypeMap) {
+                        value = Settings.Secure.getString(context.getContentResolver(), setting);
+                    } else {
+                        value = Settings.System.getString(context.getContentResolver(), setting);
+                    }
                     snapshot.putString(setting, value);
                 } else if (type == int.class) {
-                    int value = Settings.Secure.getInt(context.getContentResolver(),
-                            setting);
+                    final int value;
+                    if (map == sSecureSettingToTypeMap) {
+                        value = Settings.Secure.getInt(context.getContentResolver(), setting);
+                    } else {
+                        value = Settings.System.getInt(context.getContentResolver(), setting);
+                    }
                     snapshot.putInt(setting, value);
                 } else if (type == float.class) {
-                    float value = Settings.Secure.getFloat(context.getContentResolver(),
-                            setting);
+                    final float value;
+                    if (map == sSecureSettingToTypeMap) {
+                        value = Settings.Secure.getFloat(context.getContentResolver(), setting);
+                    } else {
+                        value = Settings.System.getFloat(context.getContentResolver(), setting);
+                    }
                     snapshot.putFloat(setting, value);
                 } else if (type == long.class) {
-                    long value = Settings.Secure.getLong(context.getContentResolver(),
-                            setting);
+                    final long value;
+                    if (map == sSecureSettingToTypeMap) {
+                        value = Settings.Secure.getLong(context.getContentResolver(), setting);
+                    } else {
+                        value = Settings.System.getLong(context.getContentResolver(), setting);
+                    }
                     snapshot.putLong(setting, value);
                 }
             } catch (SettingNotFoundException snfe) {
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index 00fa216..98999e9 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -41,6 +41,8 @@
     boolean canceled = false;
 
     String stringName;
+    String lastTagPrefix;
+    String lastTag;
     
     final static class Key {
         final int type;
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index d87387f..f4bad73 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -44,6 +44,7 @@
 import android.net.LocalSocket;
 import android.net.LocalSocketAddress;
 import android.net.NetworkInfo;
+import android.net.NetworkUtils;
 import android.net.RouteInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.os.Binder;
@@ -74,6 +75,7 @@
 import java.io.File;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.net.InetAddress;
 import java.net.Inet4Address;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
@@ -277,13 +279,12 @@
     }
 
     /**
-     * Protect a socket from routing changes by binding it to the given
-     * interface. The socket is NOT closed by this method.
+     * Protect a socket from VPN rules by binding it to the main routing table.
+     * The socket is NOT closed by this method.
      *
      * @param socket The socket to be bound.
-     * @param interfaze The name of the interface.
      */
-    public void protect(ParcelFileDescriptor socket, String interfaze) throws Exception {
+    public void protect(ParcelFileDescriptor socket) throws Exception {
 
         PackageManager pm = mContext.getPackageManager();
         int appUid = pm.getPackageUid(mPackage, mUserId);
@@ -297,8 +298,6 @@
         } finally {
             Binder.restoreCallingIdentity(token);
         }
-        // bind the socket to the interface
-        jniProtect(socket.getFd(), interfaze);
 
     }
 
@@ -430,6 +429,18 @@
         return tun;
     }
 
+    /**
+     * Check if a given address is covered by the VPN's routing rules.
+     */
+    public boolean isAddressCovered(InetAddress address) {
+        synchronized (Vpn.this) {
+            if (!isRunningLocked()) {
+                return false;
+            }
+            return RouteInfo.selectBestRoute(mConfig.routes, address) != null;
+        }
+    }
+
     private boolean isRunningLocked() {
         return mVpnUsers != null;
     }
@@ -665,7 +676,6 @@
     private native int jniSetRoutes(String interfaze, String routes);
     private native void jniReset(String interfaze);
     private native int jniCheck(String interfaze);
-    private native void jniProtect(int socket, String interfaze);
 
     private static RouteInfo findIPv4DefaultRoute(LinkProperties prop) {
         for (RouteInfo route : prop.getAllRoutes()) {
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 0185a21..e43dea9 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -53,6 +53,7 @@
 import android.content.pm.UserInfo;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
+import android.os.BatteryStats;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -60,6 +61,7 @@
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UserHandle;
@@ -75,6 +77,7 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.app.IBatteryStats;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.accounts.AccountManagerService;
@@ -151,7 +154,7 @@
 
     private static final int INITIALIZATION_UNBIND_DELAY_MS = 5000;
 
-    private static final String SYNC_WAKE_LOCK_PREFIX = "*sync*";
+    private static final String SYNC_WAKE_LOCK_PREFIX = "*sync*/";
     private static final String HANDLE_SYNC_ALARM_WAKE_LOCK = "SyncManagerHandleSyncAlarm";
     private static final String SYNC_LOOP_WAKE_LOCK = "SyncLoopWakeLock";
 
@@ -172,6 +175,7 @@
 
     private final NotificationManager mNotificationMgr;
     private AlarmManager mAlarmService = null;
+    private final IBatteryStats mBatteryStats;
 
     private SyncStorageEngine mSyncStorageEngine;
 
@@ -435,6 +439,8 @@
         }
         mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
+                BatteryStats.SERVICE_NAME));
 
         // This WakeLock is used to ensure that we stay awake between the time that we receive
         // a sync alarm notification and when we finish processing it. We need to do this
@@ -1123,6 +1129,7 @@
         final int mSyncAdapterUid;
         SyncInfo mSyncInfo;
         boolean mIsLinkedToDeath = false;
+        String mEventName;
 
         /**
          * Create an ActiveSyncContext for an impending sync and grab the wakelock for that
@@ -1201,6 +1208,13 @@
                     new UserHandle(mSyncOperation.target.userId));
             if (!bindResult) {
                 mBound = false;
+            } else {
+                try {
+                    mEventName = mSyncOperation.wakeLockName();
+                    mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_SYNC_START,
+                            mEventName, mSyncAdapterUid);
+                } catch (RemoteException e) {
+                }
             }
             return bindResult;
         }
@@ -1216,6 +1230,11 @@
             if (mBound) {
                 mBound = false;
                 mContext.unbindService(this);
+                try {
+                    mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_SYNC_FINISH,
+                            mEventName, mSyncAdapterUid);
+                } catch (RemoteException e) {
+                }
             }
             mSyncWakeLock.release();
             mSyncWakeLock.setWorkSource(null);
@@ -1908,10 +1927,10 @@
         }
 
         private PowerManager.WakeLock getSyncWakeLock(SyncOperation operation) {
-            final String wakeLockKey = operation.wakeLockKey();
+            final String wakeLockKey = operation.wakeLockName();
             PowerManager.WakeLock wakeLock = mWakeLocks.get(wakeLockKey);
             if (wakeLock == null) {
-                final String name = SYNC_WAKE_LOCK_PREFIX + operation.wakeLockName();
+                final String name = SYNC_WAKE_LOCK_PREFIX + wakeLockKey;
                 wakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, name);
                 wakeLock.setReferenceCounted(false);
                 mWakeLocks.put(wakeLockKey, wakeLock);
diff --git a/services/core/java/com/android/server/content/SyncOperation.java b/services/core/java/com/android/server/content/SyncOperation.java
index 036b21f..5233014 100644
--- a/services/core/java/com/android/server/content/SyncOperation.java
+++ b/services/core/java/com/android/server/content/SyncOperation.java
@@ -86,6 +86,9 @@
     /** Amount of time before {@link #effectiveRunTime} from which this sync can run. */
     public long flexTime;
 
+    /** Descriptive string key for this operation */
+    public String wakeLockName;
+
     public SyncOperation(Account account, int userId, int reason, int source, String provider,
             Bundle extras, long runTimeFromNow, long flexTime, long backoff,
             long delayUntil, boolean allowParallelSyncs) {
@@ -308,25 +311,17 @@
         sb.append("]");
     }
 
-    public String wakeLockKey() {
-        if (target.target_provider) {
-            return target.account.name + "/" + target.account.type + ":" + target.provider;
-        } else if (target.target_service) {
-            return target.service.getPackageName() + "/" + target.service.getClassName();
-        } else {
-            Log.wtf(TAG, "Invalid target getting wakelock for operation - " + key);
-            return null;
-        }
-    }
-
     public String wakeLockName() {
+        if (wakeLockName != null) {
+            return wakeLockName;
+        }
         if (target.target_provider) {
-            return "/" + target.provider
+            return (wakeLockName = target.provider
                     + "/" + target.account.type
-                    + "/" + target.account.name;
+                    + "/" + target.account.name);
         } else if (target.target_service) {
-            return "/" + target.service.getPackageName()
-                    + "/" + target.service.getClassName();
+            return (wakeLockName = target.service.getPackageName()
+                    + "/" + target.service.getClassName());
         } else {
             Log.wtf(TAG, "Invalid target getting wakelock name for operation - " + key);
             return null;
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 0d3fa84..89acec9 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -17,10 +17,10 @@
 package com.android.server.media;
 
 import android.content.Intent;
-import android.media.IMediaController;
-import android.media.IMediaControllerCallback;
-import android.media.IMediaSession;
-import android.media.IMediaSessionCallback;
+import android.media.session.IMediaController;
+import android.media.session.IMediaControllerCallback;
+import android.media.session.IMediaSession;
+import android.media.session.IMediaSessionCallback;
 import android.media.RemoteControlClient;
 import android.os.Bundle;
 import android.os.IBinder;
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 9c96c35..a7ff926 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -17,9 +17,9 @@
 package com.android.server.media;
 
 import android.content.Context;
-import android.media.IMediaSession;
-import android.media.IMediaSessionCallback;
-import android.media.IMediaSessionManager;
+import android.media.session.IMediaSession;
+import android.media.session.IMediaSessionCallback;
+import android.media.session.IMediaSessionManager;
 import android.os.Binder;
 import android.os.RemoteException;
 import android.text.TextUtils;
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index df2aaca..243bd74 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -16,6 +16,8 @@
 
 package com.android.server.notification;
 
+import android.os.IBinder;
+
 public interface NotificationDelegate {
     void onSetDisabled(int status);
     void onClearAll();
@@ -24,4 +26,5 @@
     void onNotificationError(String pkg, String tag, int id,
             int uid, int initialPid, String message);
     void onPanelRevealed();
+    boolean allowDisable(int what, IBinder token, String pkg);
 }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerInternal.java b/services/core/java/com/android/server/notification/NotificationManagerInternal.java
index 92ffdcc..b695b68 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerInternal.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerInternal.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2014 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.notification;
 
 import android.app.Notification;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ab46dfe..ce13a7a 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -154,7 +154,7 @@
     private long[] mFallbackVibrationPattern;
     boolean mSystemReady;
 
-    int mDisabledNotifications;
+    private boolean mDisableNotificationAlerts;
     NotificationRecord mSoundNotification;
     NotificationRecord mVibrateNotification;
 
@@ -202,6 +202,21 @@
 
     final ArrayList<NotificationScorer> mScorers = new ArrayList<NotificationScorer>();
 
+    private int mZenMode;
+    private int mPreZenAlarmVolume = -1;
+    private int mPreZenRingerMode = -1;
+    private boolean mZenMutingAlarm;
+    private boolean mZenMutingRinger;
+    // temporary, until we update apps to provide metadata
+    private static final Set<String> CALL_PACKAGES = new HashSet<String>(Arrays.asList(
+            "com.google.android.dialer",
+            "com.android.phone"
+            ));
+    private static final Set<String> ALARM_PACKAGES = new HashSet<String>(Arrays.asList(
+            "com.google.android.deskclock"
+            ));
+    private static final String EXTRA_INTERCEPT = "android.intercept";
+
     private class NotificationListenerInfo implements IBinder.DeathRecipient {
         INotificationListener listener;
         ComponentName component;
@@ -258,10 +273,11 @@
 
         @Override
         public void binderDied() {
-            if (connection == null) {
-                // This is not a service; it won't be recreated. We can give up this connection.
-                unregisterListenerImpl(this.listener, this.userid);
-            }
+            // Remove the listener, but don't unbind from the service. The system will bring the
+            // service back up, and the onServiceConnected handler will readd the listener with the
+            // new binding. If this isn't a bound service, and is just a registered
+            // INotificationListener, just removing it from the list is all we need to do anyway.
+            removeListenerImpl(this.listener, this.userid);
         }
 
         /** convenience method for looking in mEnabledListenersForCurrentUser */
@@ -869,8 +885,8 @@
         @Override
         public void onSetDisabled(int status) {
             synchronized (mNotificationList) {
-                mDisabledNotifications = status;
-                if ((mDisabledNotifications & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) {
+                mDisableNotificationAlerts = (status & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0;
+                if (mDisableNotificationAlerts) {
                     // cancel whatever's going on
                     long identity = Binder.clearCallingIdentity();
                     try {
@@ -968,6 +984,14 @@
             }
             Binder.restoreCallingIdentity(ident);
         }
+
+        @Override
+        public boolean allowDisable(int what, IBinder token, String pkg) {
+            if (isCall(pkg, null)) {
+                return mZenMode == Settings.Global.ZEN_MODE_OFF;
+            }
+            return true;
+        }
     };
 
     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@@ -1077,6 +1101,12 @@
         private final Uri ENABLED_NOTIFICATION_LISTENERS_URI
                 = Settings.Secure.getUriFor(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
 
+        private final Uri ZEN_MODE
+                = Settings.Global.getUriFor(Settings.Global.ZEN_MODE);
+
+        private final Uri MODE_RINGER
+                = Settings.Global.getUriFor(Settings.Global.MODE_RINGER);
+
         SettingsObserver(Handler handler) {
             super(handler);
         }
@@ -1087,6 +1117,10 @@
                     false, this, UserHandle.USER_ALL);
             resolver.registerContentObserver(ENABLED_NOTIFICATION_LISTENERS_URI,
                     false, this, UserHandle.USER_ALL);
+            resolver.registerContentObserver(ZEN_MODE,
+                    false, this);
+            resolver.registerContentObserver(MODE_RINGER,
+                    false, this);
             update(null);
         }
 
@@ -1107,6 +1141,12 @@
             if (uri == null || ENABLED_NOTIFICATION_LISTENERS_URI.equals(uri)) {
                 rebindListenerServices();
             }
+            if (ZEN_MODE.equals(uri)) {
+                updateZenMode();
+            }
+            if (MODE_RINGER.equals(uri)) {
+                updateRingerMode();
+            }
         }
     }
 
@@ -1170,8 +1210,10 @@
         // flag at least once and we'll go back to 0 after that.
         if (0 == Settings.Global.getInt(getContext().getContentResolver(),
                     Settings.Global.DEVICE_PROVISIONED, 0)) {
-            mDisabledNotifications = StatusBarManager.DISABLE_NOTIFICATION_ALERTS;
+            mDisableNotificationAlerts = true;
         }
+        updateRingerMode();
+        updateZenMode();
 
         // register for various Intents
         IntentFilter filter = new IntentFilter();
@@ -1622,8 +1664,12 @@
 
             pw.println("  mSoundNotification=" + mSoundNotification);
             pw.println("  mVibrateNotification=" + mVibrateNotification);
-            pw.println("  mDisabledNotifications=0x"
-                    + Integer.toHexString(mDisabledNotifications));
+            pw.println("  mDisableNotificationAlerts=" + mDisableNotificationAlerts);
+            pw.println("  mZenMode=" + Settings.Global.zenModeToString(mZenMode));
+            pw.println("  mPreZenAlarmVolume=" + mPreZenAlarmVolume);
+            pw.println("  mPreZenRingerMode=" + mPreZenRingerMode);
+            pw.println("  mZenMutingAlarm=" + mZenMutingAlarm);
+            pw.println("  mZenMutingRinger=" + mZenMutingRinger);
             pw.println("  mSystemReady=" + mSystemReady);
             pw.println("  mArchive=" + mArchive.toString());
             Iterator<StatusBarNotification> iter = mArchive.descendingIterator();
@@ -1767,9 +1813,13 @@
                     return;
                 }
 
-                // Should this notification make noise, vibe, or use the LED?
-                final boolean canInterrupt = (score >= SCORE_INTERRUPTION_THRESHOLD);
+                // Is this notification intercepted by zen mode?
+                final boolean intercept = shouldIntercept(pkg, notification);
+                notification.extras.putBoolean(EXTRA_INTERCEPT, intercept);
 
+                // Should this notification make noise, vibe, or use the LED?
+                final boolean canInterrupt = (score >= SCORE_INTERRUPTION_THRESHOLD) && !intercept;
+                if (DBG) Slog.v(TAG, "canInterrupt=" + canInterrupt + " intercept=" + intercept);
                 synchronized (mNotificationList) {
                     final StatusBarNotification n = new StatusBarNotification(
                             pkg, id, tag, callingUid, callingPid, score, notification, user);
@@ -1851,8 +1901,7 @@
                     }
 
                     // If we're not supposed to beep, vibrate, etc. then don't.
-                    if (((mDisabledNotifications
-                            & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) == 0)
+                    if (!mDisableNotificationAlerts
                             && (!(old != null
                                 && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))
                             && (r.getUserId() == UserHandle.USER_ALL ||
@@ -1860,7 +1909,7 @@
                             && canInterrupt
                             && mSystemReady
                             && mAudioManager != null) {
-
+                        if (DBG) Slog.v(TAG, "Interrupting!");
                         // sound
 
                         // should we use the default notification sound? (indicated either by
@@ -1905,6 +1954,8 @@
                                     final IRingtonePlayer player =
                                             mAudioManager.getRingtonePlayer();
                                     if (player != null) {
+                                        if (DBG) Slog.v(TAG, "Playing sound " + soundUri
+                                                + " on stream " + audioStreamType);
                                         player.playAsync(soundUri, user, looping, audioStreamType);
                                     }
                                 } catch (RemoteException e) {
@@ -1999,20 +2050,35 @@
         }
     }
 
+    /**
+     * Removes a listener from the list and unbinds from its service.
+     */
     void unregisterListenerImpl(final INotificationListener listener, final int userid) {
+        NotificationListenerInfo info = removeListenerImpl(listener, userid);
+        if (info != null && info.connection != null) {
+            getContext().unbindService(info.connection);
+        }
+    }
+
+    /**
+     * Removes a listener from the list but does not unbind from the listener's service.
+     *
+     * @return the removed listener.
+     */
+    NotificationListenerInfo removeListenerImpl(
+            final INotificationListener listener, final int userid) {
+        NotificationListenerInfo listenerInfo = null;
         synchronized (mNotificationList) {
             final int N = mListeners.size();
             for (int i=N-1; i>=0; i--) {
                 final NotificationListenerInfo info = mListeners.get(i);
                 if (info.listener.asBinder() == listener.asBinder()
                         && info.userid == userid) {
-                    mListeners.remove(i);
-                    if (info.connection != null) {
-                        getContext().unbindService(info.connection);
-                    }
+                    listenerInfo = mListeners.remove(i);
                 }
             }
         }
+        return listenerInfo;
     }
 
     void showNextToastLocked() {
@@ -2437,4 +2503,99 @@
             updateLightsLocked();
         }
     }
+
+    private void updateRingerMode() {
+        final int ringerMode = Settings.Global.getInt(getContext().getContentResolver(),
+                Settings.Global.MODE_RINGER, -1);
+        final boolean nonSilentRingerMode = ringerMode == AudioManager.RINGER_MODE_NORMAL
+                || ringerMode == AudioManager.RINGER_MODE_VIBRATE;
+        if (mZenMode != Settings.Global.ZEN_MODE_OFF && nonSilentRingerMode) {
+            Settings.Global.putInt(getContext().getContentResolver(),
+                    Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
+        }
+    }
+
+    private void updateZenMode() {
+        final int mode = Settings.Global.getInt(getContext().getContentResolver(),
+                Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
+        if (mode != mZenMode) {
+            Slog.d(TAG, String.format("updateZenMode: %s -> %s",
+                    Settings.Global.zenModeToString(mZenMode),
+                    Settings.Global.zenModeToString(mode)));
+        }
+        mZenMode = mode;
+        if (mAudioManager != null) {
+            // call audio
+            final boolean muteCalls = mZenMode != Settings.Global.ZEN_MODE_OFF;
+            if (muteCalls) {
+                if (!mZenMutingRinger) {
+                    if (DBG) Slog.d(TAG, "Muting STREAM_RING");
+                    mAudioManager.setStreamMute(AudioManager.STREAM_RING, true);
+                    mZenMutingRinger = true;
+                }
+                // calls vibrate if ringer mode = vibrate, so set the ringer mode as well
+                final int ringerMode = mAudioManager.getRingerMode();
+                if (ringerMode != AudioManager.RINGER_MODE_SILENT) {
+                    if (DBG) Slog.d(TAG, "Saving ringer mode of " + ringerMode);
+                    mPreZenRingerMode = ringerMode;
+                    mAudioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
+                }
+            } else {
+                if (mZenMutingRinger) {
+                    if (DBG) Slog.d(TAG, "Unmuting STREAM_RING");
+                    mAudioManager.setStreamMute(AudioManager.STREAM_RING, false);
+                    mZenMutingRinger = false;
+                }
+                if (mPreZenRingerMode != -1) {
+                    if (DBG) Slog.d(TAG, "Restoring ringer mode to " + mPreZenRingerMode);
+                    mAudioManager.setRingerMode(mPreZenRingerMode);
+                    mPreZenRingerMode = -1;
+                }
+            }
+            // alarm audio
+            final boolean muteAlarms = mZenMode == Settings.Global.ZEN_MODE_FULL;
+            if (muteAlarms) {
+                if (!mZenMutingAlarm) {
+                    if (DBG) Slog.d(TAG, "Muting STREAM_ALARM");
+                    mAudioManager.setStreamMute(AudioManager.STREAM_ALARM, true);
+                    mZenMutingAlarm = true;
+                }
+                // alarms don't simply respect mute, so set the volume as well
+                final int volume = mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM);
+                if (volume != 0) {
+                    if (DBG) Slog.d(TAG, "Saving STREAM_ALARM volume of " + volume);
+                    mPreZenAlarmVolume = volume;
+                    mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, 0, 0);
+                }
+            } else {
+                if (mZenMutingAlarm) {
+                    if (DBG) Slog.d(TAG, "Unmuting STREAM_ALARM");
+                    mAudioManager.setStreamMute(AudioManager.STREAM_ALARM, false);
+                    mZenMutingAlarm = false;
+                }
+                if (mPreZenAlarmVolume != -1) {
+                    if (DBG) Slog.d(TAG, "Restoring STREAM_ALARM volume to " + mPreZenAlarmVolume);
+                    mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, mPreZenAlarmVolume, 0);
+                    mPreZenAlarmVolume = -1;
+                }
+            }
+        }
+    }
+
+    private boolean isCall(String pkg, Notification n) {
+        return CALL_PACKAGES.contains(pkg);
+    }
+
+    private boolean isAlarm(String pkg, Notification n) {
+        return ALARM_PACKAGES.contains(pkg);
+    }
+
+    private boolean shouldIntercept(String pkg, Notification n) {
+        if (mZenMode == Settings.Global.ZEN_MODE_LIMITED) {
+            return !isAlarm(pkg, n);
+        } else if (mZenMode == Settings.Global.ZEN_MODE_FULL) {
+            return true;
+        }
+        return false;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index ad6eabd..b7e367b 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -218,6 +218,19 @@
         builder.append(' ');
         builder.append(uid);
         builder.append(isPublic ? " 1" : " 0");
+        builder.append(" *");         // No pkgName arg present
+        return execute(builder.toString());
+    }
+
+    public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName) {
+        StringBuilder builder = new StringBuilder("dexopt");
+        builder.append(' ');
+        builder.append(apkPath);
+        builder.append(' ');
+        builder.append(uid);
+        builder.append(isPublic ? " 1" : " 0");
+        builder.append(' ');
+        builder.append(pkgName);
         return execute(builder.toString());
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 84f0f2e..cbcf408 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1216,7 +1216,7 @@
                         continue;
                     }
                     try {
-                        if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
+                        if (dalvik.system.DexFile.isDexOptNeededInternal(lib, null, false)) {
                             alreadyDexOpted.add(lib);
                             mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
                             didDexOpt = true;
@@ -1260,7 +1260,7 @@
                         continue;
                     }
                     try {
-                        if (dalvik.system.DexFile.isDexOptNeeded(path)) {
+                        if (dalvik.system.DexFile.isDexOptNeededInternal(path, null, false)) {
                             mInstaller.dexopt(path, Process.SYSTEM_UID, true);
                             didDexOpt = true;
                         }
@@ -2777,6 +2777,63 @@
         return null;
     }
 
+    private ResolveInfo findPersistentPreferredActivityLP(Intent intent, String resolvedType,
+            int flags, List<ResolveInfo> query, boolean debug, int userId) {
+        final int N = query.size();
+        PersistentPreferredIntentResolver ppir = mSettings.mPersistentPreferredActivities
+                .get(userId);
+        // Get the list of persistent preferred activities that handle the intent
+        if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Looking for presistent preferred activities...");
+        List<PersistentPreferredActivity> pprefs = ppir != null
+                ? ppir.queryIntent(intent, resolvedType,
+                        (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId)
+                : null;
+        if (pprefs != null && pprefs.size() > 0) {
+            final int M = pprefs.size();
+            for (int i=0; i<M; i++) {
+                final PersistentPreferredActivity ppa = pprefs.get(i);
+                if (DEBUG_PREFERRED || debug) {
+                    Slog.v(TAG, "Checking PersistentPreferredActivity ds="
+                            + (ppa.countDataSchemes() > 0 ? ppa.getDataScheme(0) : "<none>")
+                            + "\n  component=" + ppa.mComponent);
+                    ppa.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), "  ");
+                }
+                final ActivityInfo ai = getActivityInfo(ppa.mComponent,
+                        flags | PackageManager.GET_DISABLED_COMPONENTS, userId);
+                if (DEBUG_PREFERRED || debug) {
+                    Slog.v(TAG, "Found persistent preferred activity:");
+                    if (ai != null) {
+                        ai.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), "  ");
+                    } else {
+                        Slog.v(TAG, "  null");
+                    }
+                }
+                if (ai == null) {
+                    // This previously registered persistent preferred activity
+                    // component is no longer known. Ignore it and do NOT remove it.
+                    continue;
+                }
+                for (int j=0; j<N; j++) {
+                    final ResolveInfo ri = query.get(j);
+                    if (!ri.activityInfo.applicationInfo.packageName
+                            .equals(ai.applicationInfo.packageName)) {
+                        continue;
+                    }
+                    if (!ri.activityInfo.name.equals(ai.name)) {
+                        continue;
+                    }
+                    //  Found a persistent preference that can handle the intent.
+                    if (DEBUG_PREFERRED || debug) {
+                        Slog.v(TAG, "Returning persistent preferred activity: " +
+                                ri.activityInfo.packageName + "/" + ri.activityInfo.name);
+                    }
+                    return ri;
+                }
+            }
+        }
+        return null;
+    }
+
     ResolveInfo findPreferredActivity(Intent intent, String resolvedType, int flags,
             List<ResolveInfo> query, int priority, boolean always,
             boolean removeMatches, boolean debug, int userId) {
@@ -2787,6 +2844,16 @@
                 intent = intent.getSelector();
             }
             if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
+
+            // Try to find a matching persistent preferred activity.
+            ResolveInfo pri = findPersistentPreferredActivityLP(intent, resolvedType, flags, query,
+                    debug, userId);
+
+            // If a persistent preferred activity matched, use it.
+            if (pri != null) {
+                return pri;
+            }
+
             PreferredIntentResolver pir = mSettings.mPreferredActivities.get(userId);
             // Get the list of preferred activities that handle the intent
             if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Looking for preferred activities...");
@@ -3707,6 +3774,7 @@
             updatedPkg = mSettings.getDisabledSystemPkgLPr(ps != null ? ps.name : pkg.packageName);
             if (DEBUG_INSTALL && updatedPkg != null) Slog.d(TAG, "updatedPkg = " + updatedPkg);
         }
+        boolean updatedPkgBetter = false;
         // First check if this is a system package that may involve an update
         if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
             if (ps != null && !ps.codePath.equals(scanFile)) {
@@ -3761,6 +3829,7 @@
                     synchronized (mPackages) {
                         mSettings.enableSystemPackageLPw(ps.name);
                     }
+                    updatedPkgBetter = true;
                 }
             }
         }
@@ -3837,7 +3906,7 @@
 
         String codePath = null;
         String resPath = null;
-        if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0) {
+        if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !updatedPkgBetter) {
             if (ps != null && ps.resourcePathString != null) {
                 resPath = ps.resourcePathString;
             } else {
@@ -4019,7 +4088,8 @@
             String path = pkg.mScanPath;
             int ret = 0;
             try {
-                if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) {
+                if (forceDex || dalvik.system.DexFile.isDexOptNeededInternal(path, pkg.packageName,
+                                                                             defer)) {
                     if (!forceDex && defer) {
                         if (mDeferredDexOpt == null) {
                             mDeferredDexOpt = new HashSet<PackageParser.Package>();
@@ -4029,7 +4099,8 @@
                     } else {
                         Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName);
                         final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
-                        ret = mInstaller.dexopt(path, sharedGid, !isForwardLocked(pkg));
+                        ret = mInstaller.dexopt(path, sharedGid, !isForwardLocked(pkg),
+                                                pkg.packageName);
                         pkg.mDidDexOpt = true;
                         performed = true;
                     }
@@ -10341,6 +10412,71 @@
     }
 
     @Override
+    public void addPersistentPreferredActivity(IntentFilter filter, ComponentName activity,
+            int userId) {
+        int callingUid = Binder.getCallingUid();
+        if (callingUid != Process.SYSTEM_UID) {
+            throw new SecurityException(
+                    "addPersistentPreferredActivity can only be run by the system");
+        }
+        if (filter.countActions() == 0) {
+            Slog.w(TAG, "Cannot set a preferred activity with no filter actions");
+            return;
+        }
+        synchronized (mPackages) {
+            Slog.i(TAG, "Adding persistent preferred activity " + activity + " for user " + userId +
+                    " :");
+            filter.dump(new LogPrinter(Log.INFO, TAG), "  ");
+            mSettings.editPersistentPreferredActivitiesLPw(userId).addFilter(
+                    new PersistentPreferredActivity(filter, activity));
+            mSettings.writePackageRestrictionsLPr(userId);
+        }
+    }
+
+    @Override
+    public void clearPackagePersistentPreferredActivities(String packageName, int userId) {
+        int callingUid = Binder.getCallingUid();
+        if (callingUid != Process.SYSTEM_UID) {
+            throw new SecurityException(
+                    "clearPackagePersistentPreferredActivities can only be run by the system");
+        }
+        ArrayList<PersistentPreferredActivity> removed = null;
+        boolean changed = false;
+        synchronized (mPackages) {
+            for (int i=0; i<mSettings.mPersistentPreferredActivities.size(); i++) {
+                final int thisUserId = mSettings.mPersistentPreferredActivities.keyAt(i);
+                PersistentPreferredIntentResolver ppir = mSettings.mPersistentPreferredActivities
+                        .valueAt(i);
+                if (userId != thisUserId) {
+                    continue;
+                }
+                Iterator<PersistentPreferredActivity> it = ppir.filterIterator();
+                while (it.hasNext()) {
+                    PersistentPreferredActivity ppa = it.next();
+                    // Mark entry for removal only if it matches the package name.
+                    if (ppa.mComponent.getPackageName().equals(packageName)) {
+                        if (removed == null) {
+                            removed = new ArrayList<PersistentPreferredActivity>();
+                        }
+                        removed.add(ppa);
+                    }
+                }
+                if (removed != null) {
+                    for (int j=0; j<removed.size(); j++) {
+                        PersistentPreferredActivity ppa = removed.get(j);
+                        ppir.removeFilter(ppa);
+                    }
+                    changed = true;
+                }
+            }
+
+            if (changed) {
+                mSettings.writePackageRestrictionsLPr(userId);
+            }
+        }
+    }
+
+    @Override
     public ComponentName getHomeActivities(List<ResolveInfo> allHomeCandidates) {
         Intent intent = new Intent(Intent.ACTION_MAIN);
         intent.addCategory(Intent.CATEGORY_HOME);
diff --git a/services/core/java/com/android/server/pm/PersistentPreferredActivity.java b/services/core/java/com/android/server/pm/PersistentPreferredActivity.java
new file mode 100644
index 0000000..4284a6d
--- /dev/null
+++ b/services/core/java/com/android/server/pm/PersistentPreferredActivity.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2014 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.pm;
+
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import android.content.ComponentName;
+import android.content.IntentFilter;
+import android.util.Log;
+
+import java.io.IOException;
+
+class PersistentPreferredActivity extends IntentFilter {
+    private static final String ATTR_NAME = "name"; // component name
+    private static final String ATTR_FILTER = "filter"; // filter
+
+    private static final String TAG = "PersistentPreferredActivity";
+
+    private static final boolean DEBUG_FILTERS = false;
+
+    final ComponentName mComponent;
+
+    PersistentPreferredActivity(IntentFilter filter, ComponentName activity) {
+        super(filter);
+        mComponent = activity;
+    }
+
+    PersistentPreferredActivity(XmlPullParser parser) throws XmlPullParserException, IOException {
+        String shortComponent = parser.getAttributeValue(null, ATTR_NAME);
+        mComponent = ComponentName.unflattenFromString(shortComponent);
+        if (mComponent == null) {
+            PackageManagerService.reportSettingsProblem(Log.WARN,
+                    "Error in package manager settings <hard-preferred-activity>: " +
+                            "Bad activity name " + shortComponent +
+                            " at " + parser.getPositionDescription());
+        }
+        int outerDepth = parser.getDepth();
+        String tagName = parser.getName();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            tagName = parser.getName();
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            } else if (type == XmlPullParser.START_TAG) {
+                if (tagName.equals(ATTR_FILTER)) {
+                    break;
+                } else {
+                    PackageManagerService.reportSettingsProblem(Log.WARN,
+                            "Unknown element under <hard-preferred-activity>: " + tagName +
+                            " at " + parser.getPositionDescription());
+                    XmlUtils.skipCurrentTag(parser);
+                }
+            }
+        }
+        if (tagName.equals(ATTR_FILTER)) {
+            readFromXml(parser);
+        } else {
+            PackageManagerService.reportSettingsProblem(Log.WARN,
+                    "Missing element under <hard-preferred-activity>: filter at " +
+                    parser.getPositionDescription());
+            XmlUtils.skipCurrentTag(parser);
+        }
+    }
+
+    public void writeToXml(XmlSerializer serializer) throws IOException {
+        serializer.attribute(null, ATTR_NAME, mComponent.flattenToShortString());
+        serializer.startTag(null, ATTR_FILTER);
+            super.writeToXml(serializer);
+        serializer.endTag(null, ATTR_FILTER);
+    }
+
+    @Override
+    public String toString() {
+        return "PersistentPreferredActivity{0x" + Integer.toHexString(System.identityHashCode(this))
+                + " " + mComponent.flattenToShortString() + "}";
+    }
+}
diff --git a/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java b/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java
new file mode 100644
index 0000000..9c8a9bd
--- /dev/null
+++ b/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014 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.pm;
+
+import java.io.PrintWriter;
+
+import com.android.server.IntentResolver;
+
+public class PersistentPreferredIntentResolver
+        extends IntentResolver<PersistentPreferredActivity, PersistentPreferredActivity> {
+    @Override
+    protected PersistentPreferredActivity[] newArray(int size) {
+        return new PersistentPreferredActivity[size];
+    }
+
+    @Override
+    protected boolean isPackageForFilter(String packageName, PersistentPreferredActivity filter) {
+        return packageName.equals(filter.mComponent.getPackageName());
+    }
+}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index e7c6446..9236bde 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -141,6 +141,11 @@
     final SparseArray<PreferredIntentResolver> mPreferredActivities =
             new SparseArray<PreferredIntentResolver>();
 
+    // The persistent preferred activities of the user's profile/device owner
+    // associated with particular intent filters.
+    final SparseArray<PersistentPreferredIntentResolver> mPersistentPreferredActivities =
+            new SparseArray<PersistentPreferredIntentResolver>();
+
     final HashMap<String, SharedUserSetting> mSharedUsers =
             new HashMap<String, SharedUserSetting>();
     private final ArrayList<Object> mUserIds = new ArrayList<Object>();
@@ -776,6 +781,15 @@
         return pir;
     }
 
+    PersistentPreferredIntentResolver editPersistentPreferredActivitiesLPw(int userId) {
+        PersistentPreferredIntentResolver ppir = mPersistentPreferredActivities.get(userId);
+        if (ppir == null) {
+            ppir = new PersistentPreferredIntentResolver();
+            mPersistentPreferredActivities.put(userId, ppir);
+        }
+        return ppir;
+    }
+
     private File getUserPackagesStateFile(int userId) {
         return new File(Environment.getUserSystemDirectory(userId), "package-restrictions.xml");
     }
@@ -835,6 +849,27 @@
         }
     }
 
+    private void readPersistentPreferredActivitiesLPw(XmlPullParser parser, int userId)
+            throws XmlPullParserException, IOException {
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+            String tagName = parser.getName();
+            if (tagName.equals(TAG_ITEM)) {
+                PersistentPreferredActivity ppa = new PersistentPreferredActivity(parser);
+                editPersistentPreferredActivitiesLPw(userId).addFilter(ppa);
+            } else {
+                PackageManagerService.reportSettingsProblem(Log.WARN,
+                        "Unknown element under <hard-preferred-activities>: " + parser.getName());
+                XmlUtils.skipCurrentTag(parser);
+            }
+        }
+    }
+
     void readPackageRestrictionsLPr(int userId) {
         if (DEBUG_MU) {
             Log.i(TAG, "Reading package restrictions for user=" + userId);
@@ -961,6 +996,8 @@
                             enabledCaller, enabledComponents, disabledComponents);
                 } else if (tagName.equals("preferred-activities")) {
                     readPreferredActivitiesLPw(parser, userId);
+                } else if (tagName.equals("hard-preferred-activities")) {
+                    readPersistentPreferredActivitiesLPw(parser, userId);
                 } else {
                     Slog.w(PackageManagerService.TAG, "Unknown element under <stopped-packages>: "
                           + parser.getName());
@@ -1024,6 +1061,20 @@
         serializer.endTag(null, "preferred-activities");
     }
 
+    void writePersistentPreferredActivitiesLPr(XmlSerializer serializer, int userId)
+            throws IllegalArgumentException, IllegalStateException, IOException {
+        serializer.startTag(null, "hard-preferred-activities");
+        PersistentPreferredIntentResolver ppir = mPersistentPreferredActivities.get(userId);
+        if (ppir != null) {
+            for (final PersistentPreferredActivity ppa : ppir.filterSet()) {
+                serializer.startTag(null, TAG_ITEM);
+                ppa.writeToXml(serializer);
+                serializer.endTag(null, TAG_ITEM);
+            }
+        }
+        serializer.endTag(null, "hard-preferred-activities");
+    }
+
     void writePackageRestrictionsLPr(int userId) {
         if (DEBUG_MU) {
             Log.i(TAG, "Writing package restrictions for user=" + userId);
@@ -1120,6 +1171,8 @@
 
             writePreferredActivitiesLPr(serializer, userId, true);
 
+            writePersistentPreferredActivitiesLPr(serializer, userId);
+
             serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);
 
             serializer.endDocument();
@@ -1721,6 +1774,10 @@
                     // Upgrading from old single-user implementation;
                     // these are the preferred activities for user 0.
                     readPreferredActivitiesLPw(parser, 0);
+                } else if (tagName.equals("hard-preferred-activities")) {
+                    // TODO: check whether this is okay! as it is very
+                    // similar to how preferred-activities are treated
+                    readPersistentPreferredActivitiesLPw(parser, 0);
                 } else if (tagName.equals("updated-package")) {
                     readDisabledSysPackageLPw(parser);
                 } else if (tagName.equals("cleaning-package")) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 38a1949..fc98c4e 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -984,27 +984,26 @@
             Slog.w(LOG_TAG, "Only user owner can have related users");
             return null;
         }
-        synchronized (mPackagesLock) {
-            UserInfo relatedUser = getUserInfoLocked(relatedUserId);
-            if (relatedUser == null) {
-                return null;
-            }
-            return createUserInternal(name, flags, relatedUser);
-        }
+        return createUserInternal(name, flags, relatedUserId);
     }
 
     @Override
     public UserInfo createUser(String name, int flags) {
         checkManageUsersPermission("Only the system can create users");
-        return createUserInternal(name, flags, null);
+        return createUserInternal(name, flags, UserHandle.USER_NULL);
     }
 
-    private UserInfo createUserInternal(String name, int flags, UserInfo relatedUser) {
+    private UserInfo createUserInternal(String name, int flags, int relatedUserId) {
         final long ident = Binder.clearCallingIdentity();
-        final UserInfo userInfo;
+        UserInfo userInfo = null;
         try {
             synchronized (mInstallLock) {
                 synchronized (mPackagesLock) {
+                    UserInfo relatedUser = null;
+                    if (relatedUserId != UserHandle.USER_NULL) {
+                        relatedUser = getUserInfoLocked(relatedUserId);
+                        if (relatedUser == null) return null;
+                    }
                     if (isUserLimitReachedLocked()) return null;
                     int userId = getNextAvailableIdLocked();
                     userInfo = new UserInfo(userId, name, null, flags);
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 09be3a8..e1ccf46 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -130,7 +130,7 @@
      * Called when a wake lock is acquired.
      */
     public void onWakeLockAcquired(int flags, String tag, String packageName,
-            int ownerUid, int ownerPid, WorkSource workSource) {
+            int ownerUid, int ownerPid, WorkSource workSource, String historyTag) {
         if (DEBUG) {
             Slog.d(TAG, "onWakeLockAcquired: flags=" + flags + ", tag=\"" + tag
                     + "\", packageName=" + packageName
@@ -143,11 +143,11 @@
             boolean unimportantForLogging = (flags&PowerManager.UNIMPORTANT_FOR_LOGGING) != 0
                     && ownerUid == Process.SYSTEM_UID;
             if (workSource != null) {
-                mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag, monitorType,
-                        unimportantForLogging);
+                mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag, historyTag,
+                        monitorType, unimportantForLogging);
             } else {
-                mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, monitorType,
-                        unimportantForLogging);
+                mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, historyTag,
+                        monitorType, unimportantForLogging);
                 // XXX need to deal with disabled operations.
                 mAppOps.startOperation(AppOpsManager.getToken(mAppOps),
                         AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 0ba55b6..e7bbf1c 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -632,7 +632,7 @@
     }
 
     private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName,
-            WorkSource ws, int uid, int pid) {
+            WorkSource ws, String historyTag, int uid, int pid) {
         synchronized (mLock) {
             if (DEBUG_SPEW) {
                 Slog.d(TAG, "acquireWakeLockInternal: lock=" + Objects.hashCode(lock)
@@ -647,11 +647,11 @@
                 if (!wakeLock.hasSameProperties(flags, tag, ws, uid, pid)) {
                     // Update existing wake lock.  This shouldn't happen but is harmless.
                     notifyWakeLockReleasedLocked(wakeLock);
-                    wakeLock.updateProperties(flags, tag, packageName, ws, uid, pid);
+                    wakeLock.updateProperties(flags, tag, packageName, ws, historyTag, uid, pid);
                     notifyWakeLockAcquiredLocked(wakeLock);
                 }
             } else {
-                wakeLock = new WakeLock(lock, flags, tag, packageName, ws, uid, pid);
+                wakeLock = new WakeLock(lock, flags, tag, packageName, ws, historyTag, uid, pid);
                 try {
                     lock.linkToDeath(wakeLock, 0);
                 } catch (RemoteException ex) {
@@ -786,7 +786,8 @@
         if (mSystemReady) {
             wakeLock.mNotifiedAcquired = true;
             mNotifier.onWakeLockAcquired(wakeLock.mFlags, wakeLock.mTag, wakeLock.mPackageName,
-                    wakeLock.mOwnerUid, wakeLock.mOwnerPid, wakeLock.mWorkSource);
+                    wakeLock.mOwnerUid, wakeLock.mOwnerPid, wakeLock.mWorkSource,
+                    wakeLock.mHistoryTag);
         }
     }
 
@@ -1553,7 +1554,7 @@
             return false;
         }
         if (!isBeingKeptAwakeLocked()) {
-            if (!mIsPowered && !mDreamsEnabledByDefaultConfig) {
+            if (!mIsPowered && !mDreamsEnabledOnBatteryConfig) {
                 return false;
             }
             if (!mIsPowered
@@ -1590,12 +1591,9 @@
                 | DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
                 | DIRTY_SETTINGS | DIRTY_SCREEN_ON_BLOCKER_RELEASED)) != 0) {
             final int newScreenState = getDesiredScreenPowerStateLocked();
-            if (newScreenState != mDisplayPowerRequest.screenState) {
-                mDisplayPowerRequest.screenState = newScreenState;
-                nativeSetPowerState(
-                        mDisplayPowerRequest.wantScreenOnNormal(),
-                        newScreenState == DisplayPowerRequest.SCREEN_STATE_BRIGHT);
-            }
+            mDisplayPowerRequest.screenState = newScreenState;
+            nativeSetPowerState(isScreenOnLocked(),
+                    newScreenState == DisplayPowerRequest.SCREEN_STATE_BRIGHT);
 
             int screenBrightness = mScreenBrightnessSettingDefault;
             float screenAutoBrightnessAdjustment = 0.0f;
@@ -1805,11 +1803,15 @@
 
     private boolean isScreenOnInternal() {
         synchronized (mLock) {
-            return !mSystemReady
-                    || mDisplayPowerRequest.wantScreenOnNormal();
+            return isScreenOnLocked();
         }
     }
 
+    private boolean isScreenOnLocked() {
+        return mWakefulness == WAKEFULNESS_AWAKE
+                || mWakefulness == WAKEFULNESS_DREAMING;
+    }
+
     private void handleBatteryStateChangedLocked() {
         mDirty |= DIRTY_BATTERY_STATE;
         updatePowerStateLocked();
@@ -2274,17 +2276,19 @@
         public String mTag;
         public final String mPackageName;
         public WorkSource mWorkSource;
+        public String mHistoryTag;
         public final int mOwnerUid;
         public final int mOwnerPid;
         public boolean mNotifiedAcquired;
 
         public WakeLock(IBinder lock, int flags, String tag, String packageName,
-                WorkSource workSource, int ownerUid, int ownerPid) {
+                WorkSource workSource, String historyTag, int ownerUid, int ownerPid) {
             mLock = lock;
             mFlags = flags;
             mTag = tag;
             mPackageName = packageName;
             mWorkSource = copyWorkSource(workSource);
+            mHistoryTag = historyTag;
             mOwnerUid = ownerUid;
             mOwnerPid = ownerPid;
         }
@@ -2304,7 +2308,7 @@
         }
 
         public void updateProperties(int flags, String tag, String packageName,
-                WorkSource workSource, int ownerUid, int ownerPid) {
+                WorkSource workSource, String historyTag, int ownerUid, int ownerPid) {
             if (!mPackageName.equals(packageName)) {
                 throw new IllegalStateException("Existing wake lock package name changed: "
                         + mPackageName + " to " + packageName);
@@ -2320,6 +2324,7 @@
             mFlags = flags;
             mTag = tag;
             updateWorkSource(workSource);
+            mHistoryTag = historyTag;
         }
 
         public boolean hasSameWorkSource(WorkSource workSource) {
@@ -2517,12 +2522,12 @@
         @Override // Binder call
         public void acquireWakeLockWithUid(IBinder lock, int flags, String tag,
                 String packageName, int uid) {
-            acquireWakeLock(lock, flags, tag, packageName, new WorkSource(uid));
+            acquireWakeLock(lock, flags, tag, packageName, new WorkSource(uid), null);
         }
 
         @Override // Binder call
         public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,
-                WorkSource ws) {
+                WorkSource ws, String historyTag) {
             if (lock == null) {
                 throw new IllegalArgumentException("lock must not be null");
             }
@@ -2543,7 +2548,7 @@
             final int pid = Binder.getCallingPid();
             final long ident = Binder.clearCallingIdentity();
             try {
-                acquireWakeLockInternal(lock, flags, tag, packageName, ws, uid, pid);
+                acquireWakeLockInternal(lock, flags, tag, packageName, ws, historyTag, uid, pid);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 2ae467e..8219eb5 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -23,9 +23,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
-import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.util.Slog;
@@ -207,6 +205,10 @@
 
     @Override
     public void disable(int what, IBinder token, String pkg) {
+        if (!mNotificationDelegate.allowDisable(what, token, pkg)) {
+            if (SPEW) Slog.d(TAG, "Blocking disable request from " + pkg);
+            return;
+        }
         disableInternal(mCurrentUserId, what, token, pkg);
     }
 
@@ -676,26 +678,4 @@
             }
         }
     }
-
-    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)
-                    || Intent.ACTION_SCREEN_OFF.equals(action)) {
-                collapsePanels();
-            }
-            /*
-            else if (Telephony.Intents.SPN_STRINGS_UPDATED_ACTION.equals(action)) {
-                updateNetworkName(intent.getBooleanExtra(Telephony.Intents.EXTRA_SHOW_SPN, false),
-                        intent.getStringExtra(Telephony.Intents.EXTRA_SPN),
-                        intent.getBooleanExtra(Telephony.Intents.EXTRA_SHOW_PLMN, false),
-                        intent.getStringExtra(Telephony.Intents.EXTRA_PLMN));
-            }
-            else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
-                updateResources();
-            }
-            */
-        }
-    };
-
 }
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index 3cccf1d..7fe895b 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -1,4 +1,18 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
+/*
+ * Copyright (C) 2014 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.wm;
 
diff --git a/services/core/java/com/android/server/wm/DimLayer.java b/services/core/java/com/android/server/wm/DimLayer.java
index aa7d485..c09ea5c 100644
--- a/services/core/java/com/android/server/wm/DimLayer.java
+++ b/services/core/java/com/android/server/wm/DimLayer.java
@@ -1,4 +1,18 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
+/*
+ * Copyright (C) 2014 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.wm;
 
@@ -125,12 +139,53 @@
         }
     }
 
+    /**
+     * @param layer The new layer value.
+     * @param inTransaction Whether the call is made within a surface transaction.
+     */
+    void adjustSurface(int layer, boolean inTransaction) {
+        final int dw, dh;
+        final float xPos, yPos;
+        if (!mStack.isFullscreen()) {
+            dw = mBounds.width();
+            dh = mBounds.height();
+            xPos = mBounds.left;
+            yPos = mBounds.top;
+        } else {
+            // Set surface size to screen size.
+            final DisplayInfo info = mDisplayContent.getDisplayInfo();
+            // Multiply by 1.5 so that rotating a frozen surface that includes this does not expose
+            // a corner.
+            dw = (int) (info.logicalWidth * 1.5);
+            dh = (int) (info.logicalHeight * 1.5);
+            // back off position so 1/4 of Surface is before and 1/4 is after.
+            xPos = -1 * dw / 6;
+            yPos = -1 * dh / 6;
+        }
+
+        try {
+            if (!inTransaction) {
+                SurfaceControl.openTransaction();
+            }
+            mDimSurface.setPosition(xPos, yPos);
+            mDimSurface.setSize(dw, dh);
+            mDimSurface.setLayer(layer);
+        } catch (RuntimeException e) {
+            Slog.w(TAG, "Failure setting size or layer", e);
+        } finally {
+            if (!inTransaction) {
+                SurfaceControl.closeTransaction();
+            }
+        }
+        mLastBounds.set(mBounds);
+        mLayer = layer;
+    }
+
+    // Assumes that surface transactions are currently closed.
     void setBounds(Rect bounds) {
         mBounds.set(bounds);
         if (isDimming() && !mLastBounds.equals(bounds)) {
-            // Clearing mAlpha forces show to redisplay with new size. 
-            mAlpha = 0;
-            show();
+            adjustSurface(mLayer, false);
         }
     }
 
@@ -169,35 +224,8 @@
             return;
         }
 
-        final int dw, dh;
-        final float xPos, yPos;
-        if (!mStack.isFullscreen()) {
-            dw = mBounds.width();
-            dh = mBounds.height();
-            xPos = mBounds.left;
-            yPos = mBounds.top;
-        } else {
-            // Set surface size to screen size.
-            final DisplayInfo info = mDisplayContent.getDisplayInfo();
-            // Multiply by 1.5 so that rotating a frozen surface that includes this does not expose a
-            // corner.
-            dw = (int) (info.logicalWidth * 1.5);
-            dh = (int) (info.logicalHeight * 1.5);
-            // back off position so 1/4 of Surface is before and 1/4 is after.
-            xPos = -1 * dw / 6;
-            yPos = -1 * dh / 6;
-        }
-
         if (!mLastBounds.equals(mBounds) || mLayer != layer) {
-            try {
-                mDimSurface.setPosition(xPos, yPos);
-                mDimSurface.setSize(dw, dh);
-                mDimSurface.setLayer(layer);
-            } catch (RuntimeException e) {
-                Slog.w(TAG, "Failure setting size or layer", e);
-            }
-            mLastBounds.set(mBounds);
-            mLayer = layer;
+            adjustSurface(layer, true);
         }
 
         long curTime = SystemClock.uptimeMillis();
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 68834d8..d4bcd5c 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -102,9 +102,8 @@
 
     final WindowManagerService mService;
 
-    static final int DEFER_DETACH = 1;
-    static final int DEFER_REMOVAL = 2;
-    int mDeferredActions;
+    /** Remove this display when animation on it has completed. */
+    boolean mDeferredRemoval;
 
     /**
      * @param display May not be null.
@@ -302,6 +301,49 @@
         }
     }
 
+    boolean isAnimating() {
+        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+            final TaskStack stack = mStacks.get(stackNdx);
+            if (stack.isAnimating()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    void checkForDeferredActions() {
+        boolean animating = false;
+        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+            final TaskStack stack = mStacks.get(stackNdx);
+            if (stack.isAnimating()) {
+                animating = true;
+            } else {
+                if (stack.mDeferDetach) {
+                    mService.detachStackLocked(this, stack);
+                }
+                final ArrayList<Task> tasks = stack.getTasks();
+                for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
+                    final Task task = tasks.get(taskNdx);
+                    AppTokenList tokens = task.mAppTokens;
+                    for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
+                        AppWindowToken wtoken = tokens.get(tokenNdx);
+                        if (wtoken.mDeferRemoval) {
+                            wtoken.mDeferRemoval = false;
+                            mService.removeAppFromTaskLocked(wtoken);
+                        }
+                    }
+                    if (task.mDeferRemoval) {
+                        task.mDeferRemoval = false;
+                        mService.removeTaskLocked(task);
+                    }
+                }
+            }
+        }
+        if (!animating && mDeferredRemoval) {
+            mService.onDisplayRemoved(mDisplayId);
+        }
+    }
+
     public void dump(String prefix, PrintWriter pw) {
         pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
         final String subPrefix = "  " + prefix;
@@ -325,7 +367,8 @@
             pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
             pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
             pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
-            pw.print(subPrefix); pw.print("layoutNeeded="); pw.println(layoutNeeded);
+            pw.print(subPrefix); pw.print("deferred="); pw.print(mDeferredRemoval);
+                pw.print(" layoutNeeded="); pw.println(layoutNeeded);
         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
             final TaskStack stack = mStacks.get(stackNdx);
             pw.print(prefix); pw.print("mStacks[" + stackNdx + "]"); pw.println(stack.mStackId);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index c301ffe..09c4e20 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -16,10 +16,12 @@
 
 package com.android.server.wm;
 
+import static com.android.server.wm.WindowManagerService.TAG;
+
 import android.util.EventLog;
+import android.util.Slog;
 
 class Task {
-//    private final String TAG = "TaskGroup";
     TaskStack mStack;
     final AppTokenList mAppTokens = new AppTokenList();
     final int taskId;
@@ -38,17 +40,24 @@
     }
 
     void addAppToken(int addPos, AppWindowToken wtoken) {
+        final int lastPos = mAppTokens.size();
+        if (addPos > lastPos) {
+            // We lost an app token. Don't crash though.
+            Slog.e(TAG, "Task.addAppToken: Out of bounds attempt token=" + wtoken + " addPos="
+                    + addPos + " lastPos=" + lastPos);
+            addPos = lastPos;
+        }
         mAppTokens.add(addPos, wtoken);
+        mDeferRemoval = false;
     }
 
     boolean removeAppToken(AppWindowToken wtoken) {
-        mAppTokens.remove(wtoken);
+        boolean removed = mAppTokens.remove(wtoken);
         if (mAppTokens.size() == 0) {
             EventLog.writeEvent(com.android.server.EventLogTags.WM_TASK_REMOVED, taskId,
                     "removeAppToken: last token");
-            return true;
         }
-        return false;
+        return removed;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index c70bc62..81db8b3 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -75,6 +75,9 @@
     /** Application tokens that are exiting, but still on screen for animations. */
     final AppTokenList mExitingAppTokens = new AppTokenList();
 
+    /** Detach this stack from its display when animation completes. */
+    boolean mDeferDetach;
+
     TaskStack(WindowManagerService service, int stackId) {
         mService = service;
         mStackId = stackId;
@@ -362,36 +365,9 @@
         mAnimationBackgroundSurface.mDimSurface.destroy();
     }
 
-    void checkForDeferredActions() {
-        if (mDisplayContent != null &&
-                (mDisplayContent.mDeferredActions & DisplayContent.DEFER_DETACH) != 0 &&
-                !isAnimating()) {
-            mDisplayContent.mDeferredActions &= ~DisplayContent.DEFER_DETACH;
-            if ((mDisplayContent.mDeferredActions & DisplayContent.DEFER_REMOVAL) != 0) {
-                mDisplayContent.mDeferredActions &= ~DisplayContent.DEFER_REMOVAL;
-                mService.onDisplayRemoved(mDisplayContent.getDisplayId());
-            }
-            mService.detachStack(mStackId);
-        }
-        for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
-            final Task task = mTasks.get(taskNdx);
-            AppTokenList tokens = task.mAppTokens;
-            for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
-                AppWindowToken wtoken = tokens.get(tokenNdx);
-                if (wtoken.mDeferRemoval) {
-                    wtoken.mDeferRemoval = false;
-                    mService.removeAppFromTaskLocked(wtoken);
-                }
-            }
-            if (task.mDeferRemoval) {
-                task.mDeferRemoval = false;
-                mService.removeTaskLocked(task);
-            }
-        }
-    }
-
     public void dump(String prefix, PrintWriter pw) {
         pw.print(prefix); pw.print("mStackId="); pw.println(mStackId);
+        pw.print(prefix); pw.print("mDeferDetach="); pw.println(mDeferDetach);
         for (int taskNdx = 0; taskNdx < mTasks.size(); ++taskNdx) {
             pw.print(prefix); pw.println(mTasks.get(taskNdx));
         }
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index a9947c0..0c68258 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -1,4 +1,18 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
+/*
+ * Copyright (C) 2014 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.wm;
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index f46056b..c006613 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -188,6 +188,7 @@
     static final boolean DEBUG_WINDOW_TRACE = false;
     static final boolean DEBUG_TASK_MOVEMENT = false;
     static final boolean DEBUG_STACK = false;
+    static final boolean DEBUG_DISPLAY = false;
     static final boolean SHOW_SURFACE_ALLOC = false;
     static final boolean SHOW_TRANSACTIONS = false;
     static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS;
@@ -3486,7 +3487,7 @@
 
             Task task = mTaskIdToTask.get(taskId);
             if (task == null) {
-                task = createTask(taskId, stackId, userId, atoken);
+                createTask(taskId, stackId, userId, atoken);
             } else {
                 task.addAppToken(addPos, atoken);
             }
@@ -3521,8 +3522,9 @@
             Task newTask = mTaskIdToTask.get(groupId);
             if (newTask == null) {
                 newTask = createTask(groupId, oldTask.mStack.mStackId, oldTask.mUserId, atoken);
+            } else {
+                newTask.mAppTokens.add(atoken);
             }
-            newTask.mAppTokens.add(atoken);
         }
     }
 
@@ -3839,27 +3841,23 @@
         }
 
         synchronized(mWindowMap) {
-            boolean changed = false;
+            final AppWindowToken newFocus;
             if (token == null) {
                 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp);
-                changed = mFocusedApp != null;
-                mFocusedApp = null;
-                if (changed) {
-                    mInputMonitor.setFocusedAppLw(null);
-                }
+                newFocus = null;
             } else {
-                AppWindowToken newFocus = findAppWindowToken(token);
+                newFocus = findAppWindowToken(token);
                 if (newFocus == null) {
                     Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token);
-                    return;
                 }
-                changed = mFocusedApp != newFocus;
                 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Set focused app to: " + newFocus
                         + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow);
+            }
+
+            final boolean changed = mFocusedApp != newFocus;
+            if (changed) {
                 mFocusedApp = newFocus;
-                if (changed) {
-                    mInputMonitor.setFocusedAppLw(newFocus);
-                }
+                mInputMonitor.setFocusedAppLw(null);
             }
 
             if (moveFocusNow && changed) {
@@ -4208,10 +4206,25 @@
         AppWindowToken atoken = findAppWindowToken(token);
         if (atoken != null) {
             atoken.appFullscreen = toOpaque;
+            // When making translucent, wait until windows below have been drawn.
+            if (toOpaque) {
+                // Making opaque so do it now.
+                setWindowOpaque(token, true);
+            }
             requestTraversal();
         }
     }
 
+    public void setWindowOpaque(IBinder token, boolean isOpaque) {
+        AppWindowToken wtoken = findAppWindowToken(token);
+        if (wtoken != null) {
+            WindowState win = wtoken.findMainWindow();
+            if (win != null) {
+                win.mWinAnimator.setOpaque(isOpaque);
+            }
+        }
+    }
+
     boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
             boolean visible, int transit, boolean performLayout) {
         boolean delayed = false;
@@ -4536,11 +4549,9 @@
     void removeAppFromTaskLocked(AppWindowToken wtoken) {
         final Task task = mTaskIdToTask.get(wtoken.groupId);
         if (task != null) {
-            task.removeAppToken(wtoken);
-            // Remove after bug resolved.
-            Slog.d(TAG, "removeAppFromTaskLocked: wtoken=" + wtoken
-                    + " numTokens left=" + task.mAppTokens.size()
-                    + " Callers=" + Debug.getCallers(5));
+            if (!task.removeAppToken(wtoken)) {
+                Slog.e(TAG, "removeAppFromTaskLocked: token=" + wtoken + " not found.");
+            }
         }
     }
 
@@ -4576,6 +4587,8 @@
                         TAG, "Removing app " + wtoken + " delayed=" + delayed
                         + " animation=" + wtoken.mAppAnimator.animation
                         + " animating=" + wtoken.mAppAnimator.animating);
+                if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "removeAppToken: "
+                        + wtoken + " delayed=" + delayed + " Callers=" + Debug.getCallers(4));
                 final TaskStack stack = mTaskIdToTask.get(wtoken.groupId).mStack;
                 if (delayed) {
                     // set the token aside because it has an active animation to be finished
@@ -4591,9 +4604,6 @@
                     wtoken.mAppAnimator.animating = false;
                     removeAppFromTaskLocked(wtoken);
                 }
-                if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
-                        "removeAppToken: " + wtoken);
-
 
                 wtoken.removed = true;
                 if (wtoken.startingData != null) {
@@ -4921,6 +4931,11 @@
         }
     }
 
+    void detachStackLocked(DisplayContent displayContent, TaskStack stack) {
+        displayContent.detachStack(stack);
+        stack.detachDisplay();
+    }
+
     public void detachStack(int stackId) {
         synchronized (mWindowMap) {
             TaskStack stack = mStackIdToStack.get(stackId);
@@ -4928,16 +4943,19 @@
                 final DisplayContent displayContent = stack.getDisplayContent();
                 if (displayContent != null) {
                     if (stack.isAnimating()) {
-                        displayContent.mDeferredActions |= DisplayContent.DEFER_DETACH;
+                        stack.mDeferDetach = true;
                         return;
                     }
-                    displayContent.detachStack(stack);
-                    stack.detachDisplay();
+                    detachStackLocked(displayContent, stack);
                 }
             }
         }
     }
 
+    public void removeStack(int stackId) {
+        mStackIdToStack.remove(stackId);
+    }
+
     void removeTaskLocked(Task task) {
         final int taskId = task.taskId;
         final TaskStack stack = task.mStack;
@@ -9493,9 +9511,9 @@
             }
         }
 
-        // Remove all deferred Stacks, tasks, and activities.
-        for (int stackNdx = mPendingStacksRemove.size() - 1; stackNdx >= 0; --stackNdx) {
-            mPendingStacksRemove.removeAt(stackNdx).checkForDeferredActions();
+        // Remove all deferred displays stacks, tasks, and activities.
+        for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
+            mDisplayContents.valueAt(displayNdx).checkForDeferredActions();
         }
 
         setFocusedStackFrame();
@@ -10780,6 +10798,7 @@
     private DisplayContent newDisplayContentLocked(final Display display) {
         DisplayContent displayContent = new DisplayContent(display, this);
         final int displayId = display.getDisplayId();
+        if (DEBUG_DISPLAY) Slog.v(TAG, "Adding display=" + display);
         mDisplayContents.put(displayId, displayContent);
 
         DisplayInfo displayInfo = displayContent.getDisplayInfo();
@@ -10881,10 +10900,11 @@
     private void handleDisplayRemovedLocked(int displayId) {
         final DisplayContent displayContent = getDisplayContentLocked(displayId);
         if (displayContent != null) {
-            if ((displayContent.mDeferredActions & DisplayContent.DEFER_DETACH) != 0) {
-                displayContent.mDeferredActions |= DisplayContent.DEFER_REMOVAL;
+            if (displayContent.isAnimating()) {
+                displayContent.mDeferredRemoval = true;
                 return;
             }
+            if (DEBUG_DISPLAY) Slog.v(TAG, "Removing display=" + displayContent);
             mDisplayContents.delete(displayId);
             displayContent.close();
             if (displayId == Display.DEFAULT_DISPLAY) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index ffb17f1..0b19b5c 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1,4 +1,18 @@
-// Copyright 2012 Google Inc. All Rights Reserved.
+/*
+ * Copyright (C) 2014 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.wm;
 
@@ -416,7 +430,6 @@
             mService.mPendingRemove.add(mWin);
             mWin.mRemoveOnExit = false;
         }
-        mService.mPendingStacksRemove.add(mWin.getStack());
         mAnimator.hideWallpapersLocked(mWin);
     }
 
@@ -490,6 +503,7 @@
         private final Rect mWindowCrop = new Rect();
         private boolean mShown = false;
         private int mLayerStack;
+        private boolean mIsOpaque;
         private final String mName;
 
         public SurfaceTrace(SurfaceSession s,
@@ -575,6 +589,16 @@
         }
 
         @Override
+        public void setOpaque(boolean isOpaque) {
+            if (isOpaque != mIsOpaque) {
+                Slog.v(SURFACE_TAG, "setOpaque(" + isOpaque + "): OLD:" + this
+                        + ". Called by " + Debug.getCallers(3));
+                mIsOpaque = isOpaque;
+            }
+            super.setOpaque(isOpaque);
+        }
+
+        @Override
         public void hide() {
             if (mShown) {
                 Slog.v(SURFACE_TAG, "hide: OLD:" + this + ". Called by " + Debug.getCallers(3));
@@ -620,7 +644,8 @@
                     + mName + " (" + mLayerStack + "): shown=" + mShown + " layer=" + mLayer
                     + " alpha=" + mSurfaceTraceAlpha + " " + mPosition.x + "," + mPosition.y
                     + " " + mSize.x + "x" + mSize.y
-                    + " crop=" + mWindowCrop.toShortString();
+                    + " crop=" + mWindowCrop.toShortString()
+                    + " opaque=" + mIsOpaque;
         }
     }
 
@@ -644,10 +669,15 @@
 
             int flags = SurfaceControl.HIDDEN;
             final WindowManager.LayoutParams attrs = mWin.mAttrs;
+            final boolean isVideoPlane =
+                    (attrs.privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_VIDEO_PLANE) != 0;
 
             if ((attrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
                 flags |= SurfaceControl.SECURE;
             }
+            if (isVideoPlane) {
+                flags |= SurfaceControl.FX_SURFACE_VIDEO_PLANE;
+            }
             if (DEBUG_VISIBILITY) Slog.v(
                 TAG, "Creating surface in session "
                 + mSession.mSurfaceSession + " window " + this
@@ -1337,8 +1367,7 @@
             Slog.w(TAG, "setTransparentRegionHint: null mSurface after mHasSurface true");
             return;
         }
-        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
-            ">>> OPEN TRANSACTION setTransparentRegion");
+        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setTransparentRegion");
         SurfaceControl.openTransaction();
         try {
             if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin,
@@ -1364,8 +1393,7 @@
                 // transformation is being applied by the animation.
                 return;
             }
-            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
-                    ">>> OPEN TRANSACTION setWallpaperOffset");
+            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setWallpaperOffset");
             SurfaceControl.openTransaction();
             try {
                 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin,
@@ -1383,6 +1411,22 @@
         }
     }
 
+    void setOpaque(boolean isOpaque) {
+        if (mSurfaceControl == null) {
+            return;
+        }
+        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setOpaque");
+        SurfaceControl.openTransaction();
+        try {
+            if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, "isOpaque=" + isOpaque,
+                    null);
+            mSurfaceControl.setOpaque(isOpaque);
+        } finally {
+            SurfaceControl.closeTransaction();
+            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setOpaque");
+        }
+    }
+
     // This must be called while inside a transaction.
     boolean performShowLocked() {
         if (mWin.isHiddenFromUserLocked()) {
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index 7675ba6..0607925 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -6,6 +6,7 @@
 
 LOCAL_SRC_FILES += \
     $(LOCAL_REL_DIR)/com_android_server_AlarmManagerService.cpp \
+    $(LOCAL_REL_DIR)/com_android_server_am_BatteryStatsService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_AssetAtlasService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_dreams_McuHal.cpp \
@@ -30,7 +31,6 @@
     frameworks/base/libs \
     frameworks/base/core/jni \
     frameworks/native/services \
-    external/skia/include/core \
     libcore/include \
     libcore/include/libsuspend \
 	$(call include-path-for, libhardware)/hardware \
diff --git a/services/core/jni/com_android_server_AlarmManagerService.cpp b/services/core/jni/com_android_server_AlarmManagerService.cpp
index 342515b..c26a516 100644
--- a/services/core/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/core/jni/com_android_server_AlarmManagerService.cpp
@@ -36,6 +36,7 @@
 #include <unistd.h>
 #include <linux/ioctl.h>
 #include <linux/android_alarm.h>
+#include <linux/rtc.h>
 
 namespace android {
 
@@ -58,6 +59,7 @@
     virtual ~AlarmImpl();
 
     virtual int set(int type, struct timespec *ts) = 0;
+    virtual int setTime(struct timeval *tv) = 0;
     virtual int waitForAlarm() = 0;
 
 protected:
@@ -71,6 +73,7 @@
     AlarmImplAlarmDriver(int fd) : AlarmImpl(&fd, 1) { }
 
     int set(int type, struct timespec *ts);
+    int setTime(struct timeval *tv);
     int waitForAlarm();
 };
 
@@ -82,6 +85,7 @@
     ~AlarmImplTimerFd();
 
     int set(int type, struct timespec *ts);
+    int setTime(struct timeval *tv);
     int waitForAlarm();
 
 private:
@@ -107,6 +111,19 @@
     return ioctl(fds[0], ANDROID_ALARM_SET(type), ts);
 }
 
+int AlarmImplAlarmDriver::setTime(struct timeval *tv)
+{
+    struct timespec ts;
+    int res;
+
+    ts.tv_sec = tv->tv_sec;
+    ts.tv_nsec = tv->tv_usec * 1000;
+    res = ioctl(fds[0], ANDROID_ALARM_SET_RTC, &ts);
+    if (res < 0)
+        ALOGV("ANDROID_ALARM_SET_RTC ioctl failed: %s\n", strerror(errno));
+    return res;
+}
+
 int AlarmImplAlarmDriver::waitForAlarm()
 {
     return ioctl(fds[0], ANDROID_ALARM_WAIT);
@@ -140,6 +157,50 @@
     return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL);
 }
 
+int AlarmImplTimerFd::setTime(struct timeval *tv)
+{
+    struct rtc_time rtc;
+    struct tm tm, *gmtime_res;
+    int fd;
+    int res;
+
+    res = settimeofday(tv, NULL);
+    if (res < 0) {
+        ALOGV("settimeofday() failed: %s\n", strerror(errno));
+        return -1;
+    }
+
+    fd = open("/dev/rtc0", O_RDWR);
+    if (fd < 0) {
+        ALOGV("Unable to open RTC driver: %s\n", strerror(errno));
+        return res;
+    }
+
+    gmtime_res = gmtime_r(&tv->tv_sec, &tm);
+    if (!gmtime_res) {
+        ALOGV("gmtime_r() failed: %s\n", strerror(errno));
+        res = -1;
+        goto done;
+    }
+
+    memset(&rtc, 0, sizeof(rtc));
+    rtc.tm_sec = tm.tm_sec;
+    rtc.tm_min = tm.tm_min;
+    rtc.tm_hour = tm.tm_hour;
+    rtc.tm_mday = tm.tm_mday;
+    rtc.tm_mon = tm.tm_mon;
+    rtc.tm_year = tm.tm_year;
+    rtc.tm_wday = tm.tm_wday;
+    rtc.tm_yday = tm.tm_yday;
+    rtc.tm_isdst = tm.tm_isdst;
+    res = ioctl(fd, RTC_SET_TIME, &rtc);
+    if (res < 0)
+        ALOGV("RTC_SET_TIME ioctl failed: %s\n", strerror(errno));
+done:
+    close(fd);
+    return res;
+}
+
 int AlarmImplTimerFd::waitForAlarm()
 {
     epoll_event events[N_ANDROID_TIMERFDS];
@@ -168,6 +229,30 @@
     return result;
 }
 
+static jint android_server_AlarmManagerService_setKernelTime(JNIEnv*, jobject, jlong nativeData, jlong millis)
+{
+    AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
+    struct timeval tv;
+    int ret;
+
+    if (millis <= 0 || millis / 1000LL >= INT_MAX) {
+        return -1;
+    }
+
+    tv.tv_sec = (time_t) (millis / 1000LL);
+    tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL);
+
+    ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec);
+
+    ret = impl->setTime(&tv);
+
+    if(ret < 0) {
+        ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno));
+        ret = -1;
+    }
+    return ret;
+}
+
 static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv*, jobject, jlong, jint minswest)
 {
     struct timezone tz;
@@ -309,6 +394,7 @@
     {"close", "(J)V", (void*)android_server_AlarmManagerService_close},
     {"set", "(JIJJ)V", (void*)android_server_AlarmManagerService_set},
     {"waitForAlarm", "(J)I", (void*)android_server_AlarmManagerService_waitForAlarm},
+    {"setKernelTime", "(JJ)I", (void*)android_server_AlarmManagerService_setKernelTime},
     {"setKernelTimezone", "(JI)I", (void*)android_server_AlarmManagerService_setKernelTimezone},
 };
 
diff --git a/services/core/jni/com_android_server_AssetAtlasService.cpp b/services/core/jni/com_android_server_AssetAtlasService.cpp
index 4a1b55d..163692b 100644
--- a/services/core/jni/com_android_server_AssetAtlasService.cpp
+++ b/services/core/jni/com_android_server_AssetAtlasService.cpp
@@ -73,7 +73,7 @@
     SkSafeUnref(previousCanvas);
 }
 
-static SkBitmap* com_android_server_AssetAtlasService_acquireCanvas(JNIEnv* env, jobject,
+static jlong com_android_server_AssetAtlasService_acquireCanvas(JNIEnv* env, jobject,
         jobject canvas, jint width, jint height) {
 
     SkBitmap* bitmap = new SkBitmap;
@@ -84,12 +84,13 @@
     SkCanvas* nativeCanvas = SkNEW_ARGS(SkCanvas, (*bitmap));
     swapCanvasPtr(env, canvas, nativeCanvas);
 
-    return bitmap;
+    return reinterpret_cast<jlong>(bitmap);
 }
 
 static void com_android_server_AssetAtlasService_releaseCanvas(JNIEnv* env, jobject,
-        jobject canvas, SkBitmap* bitmap) {
+        jobject canvas, jlong bitmapHandle) {
 
+    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
     SkCanvas* nativeCanvas = SkNEW(SkCanvas);
     swapCanvasPtr(env, canvas, nativeCanvas);
 
@@ -108,21 +109,22 @@
     return result;
 
 static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject,
-        jobject graphicBuffer, SkBitmap* bitmap) {
+        jobject graphicBuffer, jlong bitmapHandle) {
 
+    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
     // The goal of this method is to copy the bitmap into the GraphicBuffer
     // using the GPU to swizzle the texture content
     sp<GraphicBuffer> buffer(graphicBufferForJavaObject(env, graphicBuffer));
 
     if (buffer != NULL) {
         EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-        if (display == EGL_NO_DISPLAY) return false;
+        if (display == EGL_NO_DISPLAY) return JNI_FALSE;
 
         EGLint major;
         EGLint minor;
         if (!eglInitialize(display, &major, &minor)) {
             ALOGW("Could not initialize EGL");
-            return false;
+            return JNI_FALSE;
         }
 
         // We're going to use a 1x1 pbuffer surface later on
@@ -143,13 +145,13 @@
             ALOGW("Could not select EGL configuration");
             eglReleaseThread();
             eglTerminate(display);
-            return false;
+            return JNI_FALSE;
         }
         if (configCount <= 0) {
             ALOGW("Could not find EGL configuration");
             eglReleaseThread();
             eglTerminate(display);
-            return false;
+            return JNI_FALSE;
         }
 
         // These objects are initialized below but the default "null"
@@ -164,7 +166,7 @@
         EGLContext context = eglCreateContext(display, configs[0], EGL_NO_CONTEXT, attrs);
         if (context == EGL_NO_CONTEXT) {
             ALOGW("Could not create EGL context");
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
         // Create the 1x1 pbuffer
@@ -172,12 +174,12 @@
         surface = eglCreatePbufferSurface(display, configs[0], surfaceAttrs);
         if (surface == EGL_NO_SURFACE) {
             ALOGW("Could not create EGL surface");
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
         if (!eglMakeCurrent(display, surface, surface, context)) {
             ALOGW("Could not change current EGL context");
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
         // We use an EGLImage to access the content of the GraphicBuffer
@@ -188,7 +190,7 @@
                 EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttrs);
         if (image == EGL_NO_IMAGE_KHR) {
             ALOGW("Could not create EGL image");
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
         glGenTextures(1, &texture);
@@ -196,7 +198,7 @@
         glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
         if (glGetError() != GL_NO_ERROR) {
             ALOGW("Could not create/bind texture");
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
         // Upload the content of the bitmap in the GraphicBuffer
@@ -205,7 +207,7 @@
                 GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels());
         if (glGetError() != GL_NO_ERROR) {
             ALOGW("Could not upload to texture");
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
         // The fence is used to wait for the texture upload to finish
@@ -214,7 +216,7 @@
         fence = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, NULL);
         if (fence == EGL_NO_SYNC_KHR) {
             ALOGW("Could not create sync fence %#x", eglGetError());
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
         // The flag EGL_SYNC_FLUSH_COMMANDS_BIT_KHR will trigger a
@@ -223,13 +225,13 @@
                 EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, FENCE_TIMEOUT);
         if (waitStatus != EGL_CONDITION_SATISFIED_KHR) {
             ALOGW("Failed to wait for the fence %#x", eglGetError());
-            CLEANUP_GL_AND_RETURN(false);
+            CLEANUP_GL_AND_RETURN(JNI_FALSE);
         }
 
-        CLEANUP_GL_AND_RETURN(true);
+        CLEANUP_GL_AND_RETURN(JNI_TRUE);
     }
 
-    return false;
+    return JNI_FALSE;
 }
 
 // ----------------------------------------------------------------------------
@@ -247,11 +249,11 @@
 const char* const kClassPathName = "com/android/server/AssetAtlasService";
 
 static JNINativeMethod gMethods[] = {
-    { "nAcquireAtlasCanvas", "(Landroid/graphics/Canvas;II)I",
+    { "nAcquireAtlasCanvas", "(Landroid/graphics/Canvas;II)J",
             (void*) com_android_server_AssetAtlasService_acquireCanvas },
-    { "nReleaseAtlasCanvas", "(Landroid/graphics/Canvas;I)V",
+    { "nReleaseAtlasCanvas", "(Landroid/graphics/Canvas;J)V",
             (void*) com_android_server_AssetAtlasService_releaseCanvas },
-    { "nUploadAtlas", "(Landroid/view/GraphicBuffer;I)Z",
+    { "nUploadAtlas", "(Landroid/view/GraphicBuffer;J)Z",
             (void*) com_android_server_AssetAtlasService_upload },
 };
 
diff --git a/services/core/jni/com_android_server_UsbHostManager.cpp b/services/core/jni/com_android_server_UsbHostManager.cpp
index fc6de60..bc866d3 100644
--- a/services/core/jni/com_android_server_UsbHostManager.cpp
+++ b/services/core/jni/com_android_server_UsbHostManager.cpp
@@ -41,7 +41,11 @@
     jmethodID mConstructor;
 } gParcelFileDescriptorOffsets;
 
-static jmethodID method_usbDeviceAdded;
+static jmethodID method_beginUsbDeviceAdded;
+static jmethodID method_addUsbConfiguration;
+static jmethodID method_addUsbInterface;
+static jmethodID method_addUsbEndpoint;
+static jmethodID method_endUsbDeviceAdded;
 static jmethodID method_usbDeviceRemoved;
 
 static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
@@ -68,64 +72,69 @@
     Vector<int> endpointValues;
     const usb_device_descriptor* deviceDesc = usb_device_get_device_descriptor(device);
 
-    uint16_t vendorId = usb_device_get_vendor_id(device);
-    uint16_t productId = usb_device_get_product_id(device);
-    uint8_t deviceClass = deviceDesc->bDeviceClass;
-    uint8_t deviceSubClass = deviceDesc->bDeviceSubClass;
-    uint8_t protocol = deviceDesc->bDeviceProtocol;
     char *manufacturer = usb_device_get_manufacturer_name(device);
     char *product = usb_device_get_product_name(device);
     char *serial = usb_device_get_serial(device);
 
-    usb_descriptor_iter_init(device, &iter);
-
-    while ((desc = usb_descriptor_iter_next(&iter)) != NULL) {
-        if (desc->bDescriptorType == USB_DT_INTERFACE) {
-            struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)desc;
-
-            // push class, subclass, protocol and number of endpoints into interfaceValues vector
-            interfaceValues.add(interface->bInterfaceNumber);
-            interfaceValues.add(interface->bInterfaceClass);
-            interfaceValues.add(interface->bInterfaceSubClass);
-            interfaceValues.add(interface->bInterfaceProtocol);
-            interfaceValues.add(interface->bNumEndpoints);
-        } else if (desc->bDescriptorType == USB_DT_ENDPOINT) {
-            struct usb_endpoint_descriptor *endpoint = (struct usb_endpoint_descriptor *)desc;
-
-            // push address, attributes, max packet size and interval into endpointValues vector
-            endpointValues.add(endpoint->bEndpointAddress);
-            endpointValues.add(endpoint->bmAttributes);
-            endpointValues.add(__le16_to_cpu(endpoint->wMaxPacketSize));
-            endpointValues.add(endpoint->bInterval);
-        }
-    }
-
-    usb_device_close(device);
-
-    // handle generic device notification
-    int length = interfaceValues.size();
-    jintArray interfaceArray = env->NewIntArray(length);
-    env->SetIntArrayRegion(interfaceArray, 0, length, interfaceValues.array());
-
-    length = endpointValues.size();
-    jintArray endpointArray = env->NewIntArray(length);
-    env->SetIntArrayRegion(endpointArray, 0, length, endpointValues.array());
-
     jstring deviceName = env->NewStringUTF(devname);
     jstring manufacturerName = env->NewStringUTF(manufacturer);
     jstring productName = env->NewStringUTF(product);
     jstring serialNumber = env->NewStringUTF(serial);
-    env->CallVoidMethod(thiz, method_usbDeviceAdded,
-            deviceName, vendorId, productId, deviceClass,
-            deviceSubClass, protocol, manufacturerName,
-            productName, serialNumber, interfaceArray, endpointArray);
 
-    env->DeleteLocalRef(interfaceArray);
-    env->DeleteLocalRef(endpointArray);
+    jboolean result = env->CallBooleanMethod(thiz, method_beginUsbDeviceAdded,
+            deviceName, usb_device_get_vendor_id(device), usb_device_get_product_id(device),
+            deviceDesc->bDeviceClass, deviceDesc->bDeviceSubClass, deviceDesc->bDeviceProtocol,
+            manufacturerName, productName, serialNumber);
+
     env->DeleteLocalRef(serialNumber);
     env->DeleteLocalRef(productName);
     env->DeleteLocalRef(manufacturerName);
     env->DeleteLocalRef(deviceName);
+    free(manufacturer);
+    free(product);
+    free(serial);
+
+    if (!result) goto fail;
+
+    usb_descriptor_iter_init(device, &iter);
+
+    while ((desc = usb_descriptor_iter_next(&iter)) != NULL) {
+        if (desc->bDescriptorType == USB_DT_CONFIG) {
+            struct usb_config_descriptor *config = (struct usb_config_descriptor *)desc;
+            char *name = usb_device_get_string(device, config->iConfiguration);
+            jstring configName = env->NewStringUTF(name);
+
+            env->CallVoidMethod(thiz, method_addUsbConfiguration,
+                    config->bConfigurationValue, configName, config->bmAttributes,
+                    config->bMaxPower);
+
+            env->DeleteLocalRef(configName);
+            free(name);
+        } else if (desc->bDescriptorType == USB_DT_INTERFACE) {
+            struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)desc;
+            char *name = usb_device_get_string(device, interface->iInterface);
+            jstring interfaceName = env->NewStringUTF(name);
+
+            env->CallVoidMethod(thiz, method_addUsbInterface,
+                    interface->bInterfaceNumber, interfaceName, interface->bAlternateSetting,
+                    interface->bInterfaceClass, interface->bInterfaceSubClass,
+                    interface->bInterfaceProtocol);
+
+            env->DeleteLocalRef(interfaceName);
+            free(name);
+        } else if (desc->bDescriptorType == USB_DT_ENDPOINT) {
+            struct usb_endpoint_descriptor *endpoint = (struct usb_endpoint_descriptor *)desc;
+
+            env->CallVoidMethod(thiz, method_addUsbEndpoint,
+                    endpoint->bEndpointAddress, endpoint->bmAttributes,
+                    __le16_to_cpu(endpoint->wMaxPacketSize), endpoint->bInterval);
+        }
+    }
+
+    env->CallVoidMethod(thiz, method_endUsbDeviceAdded);
+
+fail:
+    usb_device_close(device);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
 
     return 0;
@@ -191,12 +200,36 @@
         ALOGE("Can't find com/android/server/usb/UsbHostManager");
         return -1;
     }
-    method_usbDeviceAdded = env->GetMethodID(clazz, "usbDeviceAdded", "(Ljava/lang/String;IIIIILjava/lang/String;Ljava/lang/String;Ljava/lang/String;[I[I)V");
-    if (method_usbDeviceAdded == NULL) {
-        ALOGE("Can't find usbDeviceAdded");
+    method_beginUsbDeviceAdded = env->GetMethodID(clazz, "beginUsbDeviceAdded",
+            "(Ljava/lang/String;IIIIILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z");
+    if (method_beginUsbDeviceAdded == NULL) {
+        ALOGE("Can't find beginUsbDeviceAdded");
         return -1;
     }
-    method_usbDeviceRemoved = env->GetMethodID(clazz, "usbDeviceRemoved", "(Ljava/lang/String;)V");
+    method_addUsbConfiguration = env->GetMethodID(clazz, "addUsbConfiguration",
+            "(ILjava/lang/String;II)V");
+    if (method_addUsbConfiguration == NULL) {
+        ALOGE("Can't find addUsbConfiguration");
+        return -1;
+    }
+    method_addUsbInterface = env->GetMethodID(clazz, "addUsbInterface",
+            "(ILjava/lang/String;IIII)V");
+    if (method_addUsbInterface == NULL) {
+        ALOGE("Can't find addUsbInterface");
+        return -1;
+    }
+    method_addUsbEndpoint = env->GetMethodID(clazz, "addUsbEndpoint", "(IIII)V");
+    if (method_addUsbEndpoint == NULL) {
+        ALOGE("Can't find addUsbEndpoint");
+        return -1;
+    }
+    method_endUsbDeviceAdded = env->GetMethodID(clazz, "endUsbDeviceAdded", "()V");
+    if (method_endUsbDeviceAdded == NULL) {
+        ALOGE("Can't find endUsbDeviceAdded");
+        return -1;
+    }
+    method_usbDeviceRemoved = env->GetMethodID(clazz, "usbDeviceRemoved",
+            "(Ljava/lang/String;)V");
     if (method_usbDeviceRemoved == NULL) {
         ALOGE("Can't find usbDeviceRemoved");
         return -1;
@@ -205,7 +238,8 @@
     clazz = env->FindClass("android/os/ParcelFileDescriptor");
     LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
     gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
-    gParcelFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V");
+    gParcelFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>",
+            "(Ljava/io/FileDescriptor;)V");
     LOG_FATAL_IF(gParcelFileDescriptorOffsets.mConstructor == NULL,
                  "Unable to find constructor for android.os.ParcelFileDescriptor");
 
diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
new file mode 100644
index 0000000..22cc519
--- /dev/null
+++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2014 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 "BatteryStatsService"
+//#define LOG_NDEBUG 0
+
+#include <android_runtime/AndroidRuntime.h>
+#include <jni.h>
+
+#include <ScopedLocalRef.h>
+#include <ScopedPrimitiveArray.h>
+
+#include <cutils/log.h>
+#include <utils/misc.h>
+#include <utils/Log.h>
+#include <hardware/hardware.h>
+#include <suspend/autosuspend.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <semaphore.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+namespace android
+{
+
+#define LAST_RESUME_REASON "/sys/kernel/wakeup_reasons/last_resume_reason"
+#define MAX_REASON_SIZE 512
+
+static bool wakeup_init = false;
+static sem_t wakeup_sem;
+
+static void wakeup_callback(void)
+{
+    ALOGV("In wakeup_callback");
+    int ret = sem_post(&wakeup_sem);
+    if (ret < 0) {
+        char buf[80];
+        strerror_r(errno, buf, sizeof(buf));
+        ALOGE("Error posting wakeup sem: %s\n", buf);
+    }
+}
+
+static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jintArray outIrqs,
+        jobjectArray outReasons)
+{
+    bool first_time = false;
+
+    if (outIrqs == NULL || outReasons == NULL) {
+        jniThrowException(env, "java/lang/NullPointerException", "null argument");
+        return -1;
+    }
+
+    // Register our wakeup callback if not yet done.
+    if (!wakeup_init) {
+        wakeup_init = true;
+        ALOGV("Creating semaphore...");
+        int ret = sem_init(&wakeup_sem, 0, 0);
+        if (ret < 0) {
+            char buf[80];
+            strerror_r(errno, buf, sizeof(buf));
+            ALOGE("Error creating semaphore: %s\n", buf);
+            jniThrowException(env, "java/lang/IllegalStateException", buf);
+            return -1;
+        }
+        ALOGV("Registering callback...");
+        set_wakeup_callback(&wakeup_callback);
+        // First time through, we will just drain the current wakeup reasons.
+        first_time = true;
+    } else {
+        // On following calls, we need to wait for wakeup.
+        ALOGV("Waiting for wakeup...");
+        int ret = sem_wait(&wakeup_sem);
+        if (ret < 0) {
+            char buf[80];
+            strerror_r(errno, buf, sizeof(buf));
+            ALOGE("Error waiting on semaphore: %s\n", buf);
+            // Return 0 here to let it continue looping but not return results.
+            return 0;
+        }
+    }
+
+    FILE *fp = fopen(LAST_RESUME_REASON, "r");
+    if (fp == NULL) {
+        ALOGE("Failed to open %s", LAST_RESUME_REASON);
+        return -1;
+    }
+
+    int numOut = env->GetArrayLength(outIrqs);
+    ScopedIntArrayRW irqs(env, outIrqs);
+
+    ALOGV("Reading up to %d wakeup reasons", numOut);
+
+    char mergedreason[MAX_REASON_SIZE];
+    char* mergedreasonpos = mergedreason;
+    int remainreasonlen = MAX_REASON_SIZE;
+    int firstirq = 0;
+    char reasonline[128];
+    int i = 0;
+    while (fgets(reasonline, sizeof(reasonline), fp) != NULL && i < numOut) {
+        char* pos = reasonline;
+        char* endPos;
+        // First field is the index.
+        int irq = (int)strtol(pos, &endPos, 10);
+        if (pos == endPos) {
+            // Ooops.
+            ALOGE("Bad reason line: %s", reasonline);
+            continue;
+        }
+        pos = endPos;
+        // Skip whitespace; rest of the buffer is the reason string.
+        while (*pos == ' ') {
+            pos++;
+        }
+        // Chop newline at end.
+        char* endpos = pos;
+        while (*endpos != 0) {
+            if (*endpos == '\n') {
+                *endpos = 0;
+                break;
+            }
+            endpos++;
+        }
+        if (i == 0) {
+            firstirq = irq;
+        } else {
+            int len = snprintf(mergedreasonpos, remainreasonlen, ":%d", irq);
+            if (len >= 0 && len < remainreasonlen) {
+                mergedreasonpos += len;
+                remainreasonlen -= len;
+            }
+        }
+        int len = snprintf(mergedreasonpos, remainreasonlen, i == 0 ? "%s" : ":%s", pos);
+        if (len >= 0 && len < remainreasonlen) {
+            mergedreasonpos += len;
+            remainreasonlen -= len;
+        }
+        // For now it is better to combine all of these in to one entry in the
+        // battery history.  In the future, it might be nice to figure out a way
+        // to efficiently store multiple lines as a single entry in the history.
+        //irqs[i] = irq;
+        //ScopedLocalRef<jstring> reasonString(env, env->NewStringUTF(pos));
+        //env->SetObjectArrayElement(outReasons, i, reasonString.get());
+        //ALOGV("Wakeup reason #%d: irw %d reason %s", i, irq, pos);
+        i++;
+    }
+
+    ALOGV("Got %d reasons", i);
+    if (first_time) {
+        i = 0;
+    }
+    if (i > 0) {
+        irqs[0] = firstirq;
+        *mergedreasonpos = 0;
+        ScopedLocalRef<jstring> reasonString(env, env->NewStringUTF(mergedreason));
+        env->SetObjectArrayElement(outReasons, 0, reasonString.get());
+        i = 1;
+    }
+
+    if (fclose(fp) != 0) {
+        ALOGE("Failed to close %s", LAST_RESUME_REASON);
+        return -1;
+    }
+
+    return first_time ? 0 : i;
+}
+
+static JNINativeMethod method_table[] = {
+    { "nativeWaitWakeup", "([I[Ljava/lang/String;)I", (void*)nativeWaitWakeup },
+};
+
+int register_android_server_BatteryStatsService(JNIEnv *env)
+{
+    return jniRegisterNativeMethods(env, "com/android/server/am/BatteryStatsService",
+            method_table, NELEM(method_table));
+}
+
+};
diff --git a/services/core/jni/com_android_server_connectivity_Vpn.cpp b/services/core/jni/com_android_server_connectivity_Vpn.cpp
index ab8c959..bf34a74 100644
--- a/services/core/jni/com_android_server_connectivity_Vpn.cpp
+++ b/services/core/jni/com_android_server_connectivity_Vpn.cpp
@@ -302,15 +302,6 @@
     return ifr4.ifr_flags;
 }
 
-static int bind_to_interface(int socket, const char *name)
-{
-    if (setsockopt(socket, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name))) {
-        ALOGE("Cannot bind socket to %s: %s", name, strerror(errno));
-        return SYSTEM_ERROR;
-    }
-    return 0;
-}
-
 //------------------------------------------------------------------------------
 
 static void throwException(JNIEnv *env, int error, const char *message)
@@ -433,19 +424,6 @@
     return flags;
 }
 
-static void protect(JNIEnv *env, jobject thiz, jint socket, jstring jName)
-{
-    const char *name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
-    if (!name) {
-        jniThrowNullPointerException(env, "name");
-        return;
-    }
-    if (bind_to_interface(socket, name) < 0) {
-        throwException(env, SYSTEM_ERROR, "Cannot protect socket");
-    }
-    env->ReleaseStringUTFChars(jName, name);
-}
-
 //------------------------------------------------------------------------------
 
 static JNINativeMethod gMethods[] = {
@@ -455,7 +433,6 @@
     {"jniSetRoutes", "(Ljava/lang/String;Ljava/lang/String;)I", (void *)setRoutes},
     {"jniReset", "(Ljava/lang/String;)V", (void *)reset},
     {"jniCheck", "(Ljava/lang/String;)I", (void *)check},
-    {"jniProtect", "(ILjava/lang/String;)V", (void *)protect},
 };
 
 int register_android_server_connectivity_Vpn(JNIEnv *env)
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 00986d5..ac6585b 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -21,6 +21,7 @@
 
 namespace android {
 int register_android_server_AlarmManagerService(JNIEnv* env);
+int register_android_server_BatteryStatsService(JNIEnv* env);
 int register_android_server_ConsumerIrService(JNIEnv *env);
 int register_android_server_InputApplicationHandle(JNIEnv* env);
 int register_android_server_InputWindowHandle(JNIEnv* env);
@@ -69,6 +70,7 @@
     register_android_server_AssetAtlasService(env);
     register_android_server_ConsumerIrService(env);
     register_android_server_dreams_McuHal(env);
+    register_android_server_BatteryStatsService(env);
 
     return JNI_VERSION_1_4;
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 12f0114..f186b2c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1315,9 +1315,7 @@
             }
             if (admin.getUid() != Binder.getCallingUid()) {
                 // If trying to remove device owner, refuse when the caller is not the owner.
-                if (mDeviceOwner != null
-                        && adminReceiver.getPackageName().equals(
-                        mDeviceOwner.getDeviceOwnerPackageName())) {
+                if (isDeviceOwner(adminReceiver.getPackageName())) {
                     return;
                 }
                 mContext.enforceCallingOrSelfPermission(
@@ -2793,6 +2791,7 @@
         }
         synchronized (this) {
             return mDeviceOwner != null
+                    && mDeviceOwner.hasDeviceOwner()
                     && mDeviceOwner.getDeviceOwnerPackageName().equals(packageName);
         }
     }
@@ -2966,4 +2965,66 @@
             }
         }
     }
+
+    private boolean isProfileOwner(String packageName, int userId) {
+        String profileOwnerPackage = getProfileOwner(userId);
+        // TODO: make public and connect with isProfileOwnerApp in DPM
+        return profileOwnerPackage != null && profileOwnerPackage.equals(packageName);
+    }
+
+    public void addPersistentPreferredActivity(ComponentName admin, IntentFilter filter,
+            ComponentName activity) {
+        int callingUserId = UserHandle.getCallingUserId();
+        Slog.d(LOG_TAG,"called by user " + callingUserId);
+        synchronized (this) {
+            ActiveAdmin aa = getActiveAdminUncheckedLocked(admin, callingUserId);
+            if (aa == null) {
+                throw new SecurityException("No active admin " + admin);
+            } else {
+                if (isProfileOwner(admin.getPackageName(), callingUserId)
+                        || isDeviceOwner(admin.getPackageName())) {
+                    IPackageManager pm = AppGlobals.getPackageManager();
+                    long id = Binder.clearCallingIdentity();
+                    try {
+                        pm.addPersistentPreferredActivity(filter, activity, callingUserId);
+                    } catch (RemoteException re) {
+                        // Shouldn't happen
+                    } finally {
+                        restoreCallingIdentity(id);
+                    }
+                } else {
+                    throw new SecurityException("Admin " + admin +
+                            "is not device owner or profile owner" );
+                }
+            }
+        }
+    }
+
+    public void clearPackagePersistentPreferredActivities(ComponentName admin,
+            String packageName) {
+        int callingUserId = UserHandle.getCallingUserId();
+        Slog.d(LOG_TAG,"called by user " + callingUserId);
+        synchronized (this) {
+            ActiveAdmin aa = getActiveAdminUncheckedLocked(admin, callingUserId);
+            if (aa == null) {
+                throw new SecurityException("No active admin " + admin);
+            } else {
+                if (isProfileOwner(admin.getPackageName(), callingUserId)
+                        || isDeviceOwner(admin.getPackageName())) {
+                    IPackageManager pm = AppGlobals.getPackageManager();
+                    long id = Binder.clearCallingIdentity();
+                    try{
+                        pm.clearPackagePersistentPreferredActivities(packageName, callingUserId);
+                    } catch (RemoteException re) {
+                        // Shouldn't happen
+                    } finally {
+                        restoreCallingIdentity(id);
+                    }
+                } else {
+                    throw new SecurityException("Admin " + admin +
+                            "is not device owner or profile owner" );
+                }
+            }
+        }
+    }
 }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 42193af..91d77fb 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -851,9 +851,8 @@
                 }
             }
 
-            if (!disableNonCoreServices
-                    && context.getResources().getBoolean(R.bool.config_dreamsSupported)) {
-                // Dreams (interactive idle-time views, a/k/a screen savers)
+            if (!disableNonCoreServices) {
+                // Dreams (interactive idle-time views, a/k/a screen savers, and doze mode)
                 mSystemServiceManager.startService(DreamManagerService.class);
             }
 
@@ -1001,138 +1000,131 @@
         // where third party code can really run (but before it has actually
         // started launching the initial applications), for us to complete our
         // initialization.
-        final Handler handler = new Handler();
         mActivityManagerService.systemReady(new Runnable() {
             @Override
             public void run() {
-                // We initiate all boot phases on the SystemServer thread.
-                handler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        Slog.i(TAG, "Making services ready");
-                        mSystemServiceManager.startBootPhase(
-                                SystemService.PHASE_ACTIVITY_MANAGER_READY);
+                Slog.i(TAG, "Making services ready");
+                mSystemServiceManager.startBootPhase(
+                        SystemService.PHASE_ACTIVITY_MANAGER_READY);
 
-                        try {
-                            mActivityManagerService.startObservingNativeCrashes();
-                        } catch (Throwable e) {
-                            reportWtf("observing native crashes", e);
-                        }
-                        try {
-                            startSystemUi(context);
-                        } catch (Throwable e) {
-                            reportWtf("starting System UI", e);
-                        }
-                        try {
-                            if (mountServiceF != null) mountServiceF.systemReady();
-                        } catch (Throwable e) {
-                            reportWtf("making Mount Service ready", e);
-                        }
-                        try {
-                            if (batteryF != null) batteryF.systemReady();
-                        } catch (Throwable e) {
-                            reportWtf("making Battery Service ready", e);
-                        }
-                        try {
-                            if (networkManagementF != null) networkManagementF.systemReady();
-                        } catch (Throwable e) {
-                            reportWtf("making Network Managment Service ready", e);
-                        }
-                        try {
-                            if (networkStatsF != null) networkStatsF.systemReady();
-                        } catch (Throwable e) {
-                            reportWtf("making Network Stats Service ready", e);
-                        }
-                        try {
-                            if (networkPolicyF != null) networkPolicyF.systemReady();
-                        } catch (Throwable e) {
-                            reportWtf("making Network Policy Service ready", e);
-                        }
-                        try {
-                            if (connectivityF != null) connectivityF.systemReady();
-                        } catch (Throwable e) {
-                            reportWtf("making Connectivity Service ready", e);
-                        }
-                        try {
-                            if (dockF != null) dockF.systemReady();
-                        } catch (Throwable e) {
-                            reportWtf("making Dock Service ready", e);
-                        }
-                        try {
-                            if (recognitionF != null) recognitionF.systemReady();
-                        } catch (Throwable e) {
-                            reportWtf("making Recognition Service ready", e);
-                        }
-                        Watchdog.getInstance().start();
+                try {
+                    mActivityManagerService.startObservingNativeCrashes();
+                } catch (Throwable e) {
+                    reportWtf("observing native crashes", e);
+                }
+                try {
+                    startSystemUi(context);
+                } catch (Throwable e) {
+                    reportWtf("starting System UI", e);
+                }
+                try {
+                    if (mountServiceF != null) mountServiceF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("making Mount Service ready", e);
+                }
+                try {
+                    if (batteryF != null) batteryF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("making Battery Service ready", e);
+                }
+                try {
+                    if (networkManagementF != null) networkManagementF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("making Network Managment Service ready", e);
+                }
+                try {
+                    if (networkStatsF != null) networkStatsF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("making Network Stats Service ready", e);
+                }
+                try {
+                    if (networkPolicyF != null) networkPolicyF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("making Network Policy Service ready", e);
+                }
+                try {
+                    if (connectivityF != null) connectivityF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("making Connectivity Service ready", e);
+                }
+                try {
+                    if (dockF != null) dockF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("making Dock Service ready", e);
+                }
+                try {
+                    if (recognitionF != null) recognitionF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("making Recognition Service ready", e);
+                }
+                Watchdog.getInstance().start();
 
-                        // It is now okay to let the various system services start their
-                        // third party code...
-                        mSystemServiceManager.startBootPhase(
-                                SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
+                // It is now okay to let the various system services start their
+                // third party code...
+                mSystemServiceManager.startBootPhase(
+                        SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
 
-                        try {
-                            if (wallpaperF != null) wallpaperF.systemRunning();
-                        } catch (Throwable e) {
-                            reportWtf("Notifying WallpaperService running", e);
-                        }
-                        try {
-                            if (immF != null) immF.systemRunning(statusBarF);
-                        } catch (Throwable e) {
-                            reportWtf("Notifying InputMethodService running", e);
-                        }
-                        try {
-                            if (locationF != null) locationF.systemRunning();
-                        } catch (Throwable e) {
-                            reportWtf("Notifying Location Service running", e);
-                        }
-                        try {
-                            if (countryDetectorF != null) countryDetectorF.systemRunning();
-                        } catch (Throwable e) {
-                            reportWtf("Notifying CountryDetectorService running", e);
-                        }
-                        try {
-                            if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning();
-                        } catch (Throwable e) {
-                            reportWtf("Notifying NetworkTimeService running", e);
-                        }
-                        try {
-                            if (commonTimeMgmtServiceF != null) {
-                                commonTimeMgmtServiceF.systemRunning();
-                            }
-                        } catch (Throwable e) {
-                            reportWtf("Notifying CommonTimeManagementService running", e);
-                        }
-                        try {
-                            if (textServiceManagerServiceF != null)
-                                textServiceManagerServiceF.systemRunning();
-                        } catch (Throwable e) {
-                            reportWtf("Notifying TextServicesManagerService running", e);
-                        }
-                        try {
-                            if (atlasF != null) atlasF.systemRunning();
-                        } catch (Throwable e) {
-                            reportWtf("Notifying AssetAtlasService running", e);
-                        }
-                        try {
-                            // TODO(BT) Pass parameter to input manager
-                            if (inputManagerF != null) inputManagerF.systemRunning();
-                        } catch (Throwable e) {
-                            reportWtf("Notifying InputManagerService running", e);
-                        }
-                        try {
-                            if (telephonyRegistryF != null) telephonyRegistryF.systemRunning();
-                        } catch (Throwable e) {
-                            reportWtf("Notifying TelephonyRegistry running", e);
-                        }
-                        try {
-                            if (mediaRouterF != null) mediaRouterF.systemRunning();
-                        } catch (Throwable e) {
-                            reportWtf("Notifying MediaRouterService running", e);
-                        }
-
-                        mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETE);
+                try {
+                    if (wallpaperF != null) wallpaperF.systemRunning();
+                } catch (Throwable e) {
+                    reportWtf("Notifying WallpaperService running", e);
+                }
+                try {
+                    if (immF != null) immF.systemRunning(statusBarF);
+                } catch (Throwable e) {
+                    reportWtf("Notifying InputMethodService running", e);
+                }
+                try {
+                    if (locationF != null) locationF.systemRunning();
+                } catch (Throwable e) {
+                    reportWtf("Notifying Location Service running", e);
+                }
+                try {
+                    if (countryDetectorF != null) countryDetectorF.systemRunning();
+                } catch (Throwable e) {
+                    reportWtf("Notifying CountryDetectorService running", e);
+                }
+                try {
+                    if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning();
+                } catch (Throwable e) {
+                    reportWtf("Notifying NetworkTimeService running", e);
+                }
+                try {
+                    if (commonTimeMgmtServiceF != null) {
+                        commonTimeMgmtServiceF.systemRunning();
                     }
-                });
+                } catch (Throwable e) {
+                    reportWtf("Notifying CommonTimeManagementService running", e);
+                }
+                try {
+                    if (textServiceManagerServiceF != null)
+                        textServiceManagerServiceF.systemRunning();
+                } catch (Throwable e) {
+                    reportWtf("Notifying TextServicesManagerService running", e);
+                }
+                try {
+                    if (atlasF != null) atlasF.systemRunning();
+                } catch (Throwable e) {
+                    reportWtf("Notifying AssetAtlasService running", e);
+                }
+                try {
+                    // TODO(BT) Pass parameter to input manager
+                    if (inputManagerF != null) inputManagerF.systemRunning();
+                } catch (Throwable e) {
+                    reportWtf("Notifying InputManagerService running", e);
+                }
+                try {
+                    if (telephonyRegistryF != null) telephonyRegistryF.systemRunning();
+                } catch (Throwable e) {
+                    reportWtf("Notifying TelephonyRegistry running", e);
+                }
+                try {
+                    if (mediaRouterF != null) mediaRouterF.systemRunning();
+                } catch (Throwable e) {
+                    reportWtf("Notifying MediaRouterService running", e);
+                }
+
+                mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETE);
             }
         });
     }
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index 8ae3824..0f20dde 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -226,9 +226,9 @@
                 final Handler handler) {
         }
 
-		@Override
-		public void invalidateCache(int userId) {
-		}
+        @Override
+        public void invalidateCache(int userId) {
+        }
     }
 
     static public class MyMockContext extends MockContext {
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index d5dd9a6..b925856 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -99,6 +99,13 @@
     // which need debouncing.
     private static final int UPDATE_DELAY = 1000;
 
+    // Time we received a request to enter USB accessory mode
+    private long mAccessoryModeRequestTime = 0;
+
+    // Timeout for entering USB request mode.
+    // Request is cancelled if host does not configure device within 10 seconds.
+    private static final int ACCESSORY_REQUEST_TIMEOUT = 10 * 1000;
+
     private static final String BOOT_MODE_PROPERTY = "ro.bootmode";
 
     private UsbHandler mHandler;
@@ -206,6 +213,8 @@
     }
 
     private void startAccessoryMode() {
+        if (!mHasUsbAccessory) return;
+
         mAccessoryStrings = nativeGetAccessoryStrings();
         boolean enableAudio = (nativeGetAudioMode() == AUDIO_MODE_SOURCE);
         // don't start accessory mode if our mandatory strings have not been set
@@ -224,6 +233,7 @@
         }
 
         if (functions != null) {
+            mAccessoryModeRequestTime = SystemClock.elapsedRealtime();
             setCurrentFunctions(functions, false);
         }
     }
@@ -452,6 +462,8 @@
         }
 
         private void setEnabledFunctions(String functions, boolean makeDefault) {
+            if (DEBUG) Slog.d(TAG, "setEnabledFunctions " + functions
+                    + " makeDefault: " + makeDefault);
 
             // Do not update persystent.sys.usb.config if the device is booted up
             // with OEM specific mode.
@@ -513,9 +525,17 @@
         }
 
         private void updateCurrentAccessory() {
-            if (!mHasUsbAccessory) return;
+            // We are entering accessory mode if we have received a request from the host
+            // and the request has not timed out yet.
+            boolean enteringAccessoryMode =
+                    mAccessoryModeRequestTime > 0 &&
+                        SystemClock.elapsedRealtime() <
+                            mAccessoryModeRequestTime + ACCESSORY_REQUEST_TIMEOUT;
 
-            if (mConfigured) {
+            if (mConfigured && enteringAccessoryMode) {
+                // successfully entered accessory mode
+                mAccessoryModeRequestTime = 0;
+
                 if (mAccessoryStrings != null) {
                     mCurrentAccessory = new UsbAccessory(mAccessoryStrings);
                     Slog.d(TAG, "entering USB accessory mode: " + mCurrentAccessory);
@@ -526,7 +546,7 @@
                 } else {
                     Slog.e(TAG, "nativeGetAccessoryStrings failed");
                 }
-            } else if (!mConnected) {
+            } else if (!enteringAccessoryMode) {
                 // make sure accessory mode is off
                 // and restore default functions
                 Slog.d(TAG, "exited USB accessory mode");
@@ -556,6 +576,8 @@
                 }
             }
 
+            if (DEBUG) Slog.d(TAG, "broadcasting " + intent + " connected: " + mConnected
+                                    + " configured: " + mConfigured);
             mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
         }
 
@@ -595,9 +617,7 @@
                     if (containsFunction(mCurrentFunctions,
                             UsbManager.USB_FUNCTION_ACCESSORY)) {
                         updateCurrentAccessory();
-                    }
-
-                    if (!mConnected) {
+                    } else if (!mConnected) {
                         // restore defaults when USB is disconnected
                         setEnabledFunctions(mDefaultFunctions, false);
                     }
diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index dfaad0b..7ae5460 100644
--- a/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -17,6 +17,7 @@
 package com.android.server.usb;
 
 import android.content.Context;
+import android.hardware.usb.UsbConfiguration;
 import android.hardware.usb.UsbConstants;
 import android.hardware.usb.UsbDevice;
 import android.hardware.usb.UsbEndpoint;
@@ -30,6 +31,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.HashMap;
 
 /**
@@ -48,6 +50,13 @@
     private final Context mContext;
     private final Object mLock = new Object();
 
+    private UsbDevice mNewDevice;
+    private UsbConfiguration mNewConfiguration;
+    private UsbInterface mNewInterface;
+    private ArrayList<UsbConfiguration> mNewConfigurations;
+    private ArrayList<UsbInterface> mNewInterfaces;
+    private ArrayList<UsbEndpoint> mNewEndpoints;
+
     @GuardedBy("mLock")
     private UsbSettingsManager mCurrentSettings;
 
@@ -93,69 +102,103 @@
         return false;
     }
 
-    /* Called from JNI in monitorUsbHostBus() to report new USB devices */
-    private void usbDeviceAdded(String deviceName, int vendorID, int productID,
+    /* Called from JNI in monitorUsbHostBus() to report new USB devices
+       Returns true if successful, in which case the JNI code will continue adding configurations,
+       interfaces and endpoints, and finally call endUsbDeviceAdded after all descriptors
+       have been processed
+     */
+    private boolean beginUsbDeviceAdded(String deviceName, int vendorID, int productID,
             int deviceClass, int deviceSubclass, int deviceProtocol,
-            String manufacturerName, String productName, String serialNumber,
-            /* array of quintuples containing id, class, subclass, protocol
-               and number of endpoints for each interface */
-            int[] interfaceValues,
-           /* array of quadruples containing address, attributes, max packet size
-              and interval for each endpoint */
-            int[] endpointValues) {
+            String manufacturerName, String productName, String serialNumber) {
 
         if (isBlackListed(deviceName) ||
                 isBlackListed(deviceClass, deviceSubclass, deviceProtocol)) {
-            return;
+            return false;
         }
 
         synchronized (mLock) {
             if (mDevices.get(deviceName) != null) {
                 Slog.w(TAG, "device already on mDevices list: " + deviceName);
-                return;
+                return false;
             }
 
-            int numInterfaces = interfaceValues.length / 5;
-            Parcelable[] interfaces = new UsbInterface[numInterfaces];
-            try {
-                // repackage interfaceValues as an array of UsbInterface
-                int intf, endp, ival = 0, eval = 0;
-                for (intf = 0; intf < numInterfaces; intf++) {
-                    int interfaceId = interfaceValues[ival++];
-                    int interfaceClass = interfaceValues[ival++];
-                    int interfaceSubclass = interfaceValues[ival++];
-                    int interfaceProtocol = interfaceValues[ival++];
-                    int numEndpoints = interfaceValues[ival++];
-
-                    Parcelable[] endpoints = new UsbEndpoint[numEndpoints];
-                    for (endp = 0; endp < numEndpoints; endp++) {
-                        int address = endpointValues[eval++];
-                        int attributes = endpointValues[eval++];
-                        int maxPacketSize = endpointValues[eval++];
-                        int interval = endpointValues[eval++];
-                        endpoints[endp] = new UsbEndpoint(address, attributes,
-                                maxPacketSize, interval);
-                    }
-
-                    // don't allow if any interfaces are blacklisted
-                    if (isBlackListed(interfaceClass, interfaceSubclass, interfaceProtocol)) {
-                        return;
-                    }
-                    interfaces[intf] = new UsbInterface(interfaceId, interfaceClass,
-                            interfaceSubclass, interfaceProtocol, endpoints);
-                }
-            } catch (Exception e) {
-                // beware of index out of bound exceptions, which might happen if
-                // a device does not set bNumEndpoints correctly
-                Slog.e(TAG, "error parsing USB descriptors", e);
-                return;
+            if (mNewDevice != null) {
+                Slog.e(TAG, "mNewDevice is not null in endUsbDeviceAdded");
+                return false;
             }
 
-            UsbDevice device = new UsbDevice(deviceName, vendorID, productID,
+            mNewDevice = new UsbDevice(deviceName, vendorID, productID,
                     deviceClass, deviceSubclass, deviceProtocol,
-                    manufacturerName, productName, serialNumber, interfaces);
-            mDevices.put(deviceName, device);
-            getCurrentSettings().deviceAttached(device);
+                    manufacturerName, productName, serialNumber);
+
+            mNewConfigurations = new ArrayList<UsbConfiguration>();
+            mNewInterfaces = new ArrayList<UsbInterface>();
+            mNewEndpoints = new ArrayList<UsbEndpoint>();
+        }
+        return true;
+    }
+
+    /* Called from JNI in monitorUsbHostBus() to report new USB configuration for the device
+       currently being added.  Returns true if successful, false in case of error.
+     */
+    private void addUsbConfiguration(int id, String name, int attributes, int maxPower) {
+        if (mNewConfiguration != null) {
+            mNewConfiguration.setInterfaces(
+                    mNewInterfaces.toArray(new UsbInterface[mNewInterfaces.size()]));
+            mNewInterfaces.clear();
+        }
+
+        mNewConfiguration = new UsbConfiguration(id, name, attributes, maxPower);
+        mNewConfigurations.add(mNewConfiguration);
+    }
+
+    /* Called from JNI in monitorUsbHostBus() to report new USB interface for the device
+       currently being added.  Returns true if successful, false in case of error.
+     */
+    private void addUsbInterface(int id, String name, int altSetting,
+            int Class, int subClass, int protocol) {
+        if (mNewInterface != null) {
+            mNewInterface.setEndpoints(
+                    mNewEndpoints.toArray(new UsbEndpoint[mNewEndpoints.size()]));
+            mNewEndpoints.clear();
+        }
+
+        mNewInterface = new UsbInterface(id, altSetting, name, Class, subClass, protocol);
+        mNewInterfaces.add(mNewInterface);
+    }
+
+    /* Called from JNI in monitorUsbHostBus() to report new USB endpoint for the device
+       currently being added.  Returns true if successful, false in case of error.
+     */
+    private void addUsbEndpoint(int address, int attributes, int maxPacketSize, int interval) {
+        mNewEndpoints.add(new UsbEndpoint(address, attributes, maxPacketSize, interval));
+    }
+
+    /* Called from JNI in monitorUsbHostBus() to finish adding a new device */
+    private void endUsbDeviceAdded() {
+        if (mNewInterface != null) {
+            mNewInterface.setEndpoints(
+                    mNewEndpoints.toArray(new UsbEndpoint[mNewEndpoints.size()]));
+        }
+        if (mNewConfiguration != null) {
+            mNewConfiguration.setInterfaces(
+                    mNewInterfaces.toArray(new UsbInterface[mNewInterfaces.size()]));
+        }
+
+        synchronized (mLock) {
+            if (mNewDevice != null) {
+                mNewDevice.setConfigurations(
+                        mNewConfigurations.toArray(new UsbConfiguration[mNewConfigurations.size()]));
+                mDevices.put(mNewDevice.getDeviceName(), mNewDevice);
+                Slog.d(TAG, "Added device " + mNewDevice);
+                getCurrentSettings().deviceAttached(mNewDevice);
+            } else {
+                Slog.e(TAG, "mNewDevice is null in endUsbDeviceAdded");
+            }
+            mNewDevice = null;
+            mNewConfigurations = null;
+            mNewInterfaces = null;
+            mNewEndpoints = null;
         }
     }
 
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 23e4d77..ec4d574 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1823,10 +1823,11 @@
     }
 
     /**
-     * Perform the specified type of NV config reset.
-     * Used for device configuration by some CDMA operators.
+     * Perform the specified type of NV config reset. The radio will be taken offline
+     * and the device must be rebooted after the operation. Used for device
+     * configuration by some CDMA operators.
      *
-     * @param resetType the type of reset to perform (1 == factory reset; 2 == NV-only reset).
+     * @param resetType reset type: 1: reload NV reset, 2: erase NV reset, 3: factory NV reset
      * @return true on success; false on any failure.
      * @hide
      */
@@ -1842,21 +1843,38 @@
     }
 
     /**
-     * Change the radio to the specified mode.
-     * Used for device configuration by some operators.
+     * Get the preferred network type.
+     * Used for device configuration by some CDMA operators.
      *
-     * @param radioMode is 0 for offline mode, 1 for online mode, 2 for low-power mode,
-     *                  or 3 to reset the radio.
+     * @return the preferred network type, defined in RILConstants.java.
+     * @hide
+     */
+    public int getPreferredNetworkType() {
+        try {
+            return getITelephony().getPreferredNetworkType();
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "getPreferredNetworkType RemoteException", ex);
+        } catch (NullPointerException ex) {
+            Rlog.e(TAG, "getPreferredNetworkType NPE", ex);
+        }
+        return -1;
+    }
+
+    /**
+     * Set the preferred network type.
+     * Used for device configuration by some CDMA operators.
+     *
+     * @param networkType the preferred network type, defined in RILConstants.java.
      * @return true on success; false on any failure.
      * @hide
      */
-    public boolean setRadioMode(int radioMode) {
+    public boolean setPreferredNetworkType(int networkType) {
         try {
-            return getITelephony().setRadioMode(radioMode);
+            return getITelephony().setPreferredNetworkType(networkType);
         } catch (RemoteException ex) {
-            Rlog.e(TAG, "setRadioMode RemoteException", ex);
+            Rlog.e(TAG, "setPreferredNetworkType RemoteException", ex);
         } catch (NullPointerException ex) {
-            Rlog.e(TAG, "setRadioMode NPE", ex);
+            Rlog.e(TAG, "setPreferredNetworkType NPE", ex);
         }
         return false;
     }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 370e27a..7c338ac 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -395,8 +395,9 @@
     boolean nvWriteCdmaPrl(in byte[] preferredRoamingList);
 
     /**
-     * Perform the specified type of NV config reset.
-     * Used for device configuration by some CDMA operators.
+     * Perform the specified type of NV config reset. The radio will be taken offline
+     * and the device must be rebooted after the operation. Used for device
+     * configuration by some CDMA operators.
      *
      * @param resetType the type of reset to perform (1 == factory reset; 2 == NV-only reset).
      * @return true on success; false on any failure.
@@ -404,12 +405,19 @@
     boolean nvResetConfig(int resetType);
 
     /**
-     * Change the radio to the specified mode.
-     * Used for device configuration by some operators.
+     * Get the preferred network type.
+     * Used for device configuration by some CDMA operators.
      *
-     * @param radioMode is 0 for offline mode, 1 for online mode, 2 for low-power mode,
-     *                  or 3 to reset the radio.
+     * @return the preferred network type, defined in RILConstants.java.
+     */
+    int getPreferredNetworkType();
+
+    /**
+     * Set the preferred network type.
+     * Used for device configuration by some CDMA operators.
+     *
+     * @param networkType the preferred network type, defined in RILConstants.java.
      * @return true on success; false on any failure.
      */
-    boolean setRadioMode(int radioMode);
+    boolean setPreferredNetworkType(int networkType);
 }
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 6015df0..d338857 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -115,8 +115,9 @@
     int DEACTIVATE_REASON_PDP_RESET = 2;
 
     /* NV config radio reset types. */
-    int NV_CONFIG_RESET_FACTORY = 1;
-    int NV_CONFIG_RESET_NV_ONLY = 2;
+    int NV_CONFIG_RELOAD_RESET = 1;
+    int NV_CONFIG_ERASE_RESET = 2;
+    int NV_CONFIG_FACTORY_RESET = 3;
 
 /*
 cat include/telephony/ril.h | \
diff --git a/test-runner/src/junit/runner/FailureDetailView.java b/test-runner/src/junit/runner/FailureDetailView.java
index 1b8365a..c846191 100644
--- a/test-runner/src/junit/runner/FailureDetailView.java
+++ b/test-runner/src/junit/runner/FailureDetailView.java
@@ -12,7 +12,7 @@
 public interface FailureDetailView {
     // The following definition was removed for compatibility with Android
     // libraries.
-    // 	/**
+    //  /**
     //   * Returns the component used to present the TraceView
     //   */
     //  public Component getComponent();
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/GraphReader.java b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/GraphReader.java
index ef885e3..ec02d34 100644
--- a/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/GraphReader.java
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/GraphReader.java
@@ -117,7 +117,7 @@
         }
 
         @Override
-	public void execute(CommandStack stack) {
+        public void execute(CommandStack stack) {
             Filter filter = null;
             try {
                 filter = stack.getFactory().createFilterByClassName(mClassName,
diff --git a/tests/HwAccelerationTest/res/layout/isolation.xml b/tests/HwAccelerationTest/res/layout/isolation.xml
index 802ac7f..e66db19 100644
--- a/tests/HwAccelerationTest/res/layout/isolation.xml
+++ b/tests/HwAccelerationTest/res/layout/isolation.xml
@@ -5,36 +5,39 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="#f55">
+    <!-- Left and right layouts are not isolated volumes, so the text views
+         will interleave since they share an isolated z volume-->
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="horizontal">
         <LinearLayout
             android:layout_width="0dp"
-            android:layout_height="150dp"
+            android:layout_height="200dp"
             android:layout_weight="1"
-            android:isolatedZVolume="false"
             android:orientation="vertical">
             <TextView style="@style/TopLeftReorderTextView"/>
             <TextView style="@style/BottomLeftReorderTextView"/>
         </LinearLayout>
         <LinearLayout
             android:layout_width="0dp"
-            android:layout_height="150dp"
+            android:layout_height="200dp"
             android:layout_weight="1"
-            android:isolatedZVolume="false"
+            android:translationY="50dp"
             android:orientation="vertical">
             <TextView style="@style/TopRightReorderTextView"/>
             <TextView style="@style/BottomRightReorderTextView"/>
         </LinearLayout>
     </LinearLayout>
+
+    <!-- Left and right volumes are isolated by default, so no interleaving will be seen. -->
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="horizontal">
         <LinearLayout
             android:layout_width="0dp"
-            android:layout_height="150dp"
+            android:layout_height="200dp"
             android:layout_weight="1"
             android:orientation="vertical">
             <TextView style="@style/TopLeftReorderTextView"/>
@@ -42,8 +45,9 @@
         </LinearLayout>
         <LinearLayout
             android:layout_width="0dp"
-            android:layout_height="150dp"
+            android:layout_height="200dp"
             android:layout_weight="1"
+            android:translationY="50dp"
             android:orientation="vertical">
             <TextView style="@style/TopRightReorderTextView"/>
             <TextView style="@style/BottomRightReorderTextView"/>
diff --git a/tests/HwAccelerationTest/res/values/styles.xml b/tests/HwAccelerationTest/res/values/styles.xml
index 0ffd3d7..cde5d20 100644
--- a/tests/HwAccelerationTest/res/values/styles.xml
+++ b/tests/HwAccelerationTest/res/values/styles.xml
@@ -1,14 +1,14 @@
 <resources>
     <style name="ReorderTextView" parent="@android:style/TextAppearance.Medium">
         <item name="android:layout_width">match_parent</item>
-        <item name="android:layout_height">75dp</item>
+        <item name="android:layout_height">100dp</item>
         <item name="android:gravity">center</item>
     </style>
     <style name="LeftReorderTextView" parent="@style/ReorderTextView">
-        <item name="android:translationX">50dp</item>
+        <item name="android:translationX">20dp</item>
     </style>
     <style name="RightReorderTextView" parent="@style/ReorderTextView">
-        <item name="android:translationX">-50dp</item>
+        <item name="android:translationX">-20dp</item>
     </style>
 
     <style name="TopLeftReorderTextView" parent="@style/LeftReorderTextView">
diff --git a/tests/ImfTest/src/com/android/imftest/samples/InputTypeActivity.java b/tests/ImfTest/src/com/android/imftest/samples/InputTypeActivity.java
index 25ac2f0..299e6bb 100644
--- a/tests/ImfTest/src/com/android/imftest/samples/InputTypeActivity.java
+++ b/tests/ImfTest/src/com/android/imftest/samples/InputTypeActivity.java
@@ -81,11 +81,11 @@
         
         /* Uri Edit Text */
         mLayout.addView(buildEntryView(EditorInfo.TYPE_CLASS_TEXT|EditorInfo.TYPE_TEXT_VARIATION_URI, 
-        		R.string.uri_edit_text_label));
+                R.string.uri_edit_text_label));
         
         /* Email Address Edit Text */
         mLayout.addView(buildEntryView(EditorInfo.TYPE_CLASS_TEXT|EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS, 
-        		R.string.email_address_edit_text_label));
+                R.string.email_address_edit_text_label));
         
         /* Email Subject Text */
         mLayout.addView(buildEntryView(EditorInfo.TYPE_CLASS_TEXT|EditorInfo.TYPE_TEXT_VARIATION_EMAIL_SUBJECT, 
@@ -142,7 +142,7 @@
     private View buildEntryView(int inputType, int label) {
 
         
-    	View view = mInflater.inflate(R.layout.sample_edit_text, mParent, false);
+        View view = mInflater.inflate(R.layout.sample_edit_text, mParent, false);
         
         EditText editText = (EditText) view.findViewById(R.id.data);
         editText.setInputType(inputType);
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollablePanScanTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollablePanScanTests.java
index a1c5fd2..2db11c5 100644
--- a/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollablePanScanTests.java
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollablePanScanTests.java
@@ -24,26 +24,26 @@
 
 public class BigEditTextActivityNonScrollablePanScanTests extends ImfBaseTestCase<BigEditTextActivityNonScrollablePanScan> {
 
-	public final String TAG = "BigEditTextActivityNonScrollablePanScanTests";
-	
+    public final String TAG = "BigEditTextActivityNonScrollablePanScanTests";
+    
     public BigEditTextActivityNonScrollablePanScanTests() {
         super(BigEditTextActivityNonScrollablePanScan.class);
     }
-	
-	@LargeTest
-	public void testAppAdjustmentPanScan() {
-	    // Give the IME 2 seconds to appear.
-	    pause(2000);
+    
+    @LargeTest
+    public void testAppAdjustmentPanScan() {
+        // Give the IME 2 seconds to appear.
+        pause(2000);
         
-	    View rootView = ((BigEditTextActivityNonScrollablePanScan) mTargetActivity).getRootView();
-	    View servedView = ((BigEditTextActivityNonScrollablePanScan) mTargetActivity).getDefaultFocusedView();
-	        
-	    assertNotNull(rootView);
-	    assertNotNull(servedView);
-	    
-	    destructiveCheckImeInitialState(rootView, servedView);
-	    
+        View rootView = ((BigEditTextActivityNonScrollablePanScan) mTargetActivity).getRootView();
+        View servedView = ((BigEditTextActivityNonScrollablePanScan) mTargetActivity).getDefaultFocusedView();
+            
+        assertNotNull(rootView);
+        assertNotNull(servedView);
+        
+        destructiveCheckImeInitialState(rootView, servedView);
+        
         verifyEditTextAdjustment(servedView, rootView.getMeasuredHeight());
-	}
-	
+    }
+    
 }
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollableResizeTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollableResizeTests.java
index 2e0b0eb..1050794 100644
--- a/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollableResizeTests.java
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollableResizeTests.java
@@ -24,14 +24,14 @@
 
 public class BigEditTextActivityNonScrollableResizeTests extends ImfBaseTestCase<BigEditTextActivityNonScrollableResize> {
 
-	public final String TAG = "BigEditTextActivityNonScrollableResizeTests";
-	
+    public final String TAG = "BigEditTextActivityNonScrollableResizeTests";
+    
     public BigEditTextActivityNonScrollableResizeTests() {
         super(BigEditTextActivityNonScrollableResize.class);
     }
-	
-	@LargeTest
-	public void testAppAdjustmentPanScan() {       // Give the IME 2 seconds to appear.
+    
+    @LargeTest
+    public void testAppAdjustmentPanScan() {       // Give the IME 2 seconds to appear.
         pause(2000);
         
         View rootView = ((BigEditTextActivityNonScrollableResize) mTargetActivity).getRootView();
@@ -43,6 +43,6 @@
         destructiveCheckImeInitialState(rootView, servedView);
             
         verifyEditTextAdjustment(servedView, rootView.getMeasuredHeight());
-	}
-	
+    }
+    
 }
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollablePanScanTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollablePanScanTests.java
index d3eefb5..1e848b0 100644
--- a/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollablePanScanTests.java
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollablePanScanTests.java
@@ -24,14 +24,14 @@
 
 public class BigEditTextActivityScrollablePanScanTests extends ImfBaseTestCase<BigEditTextActivityScrollablePanScan> {
 
-	public final String TAG = "BigEditTextActivityScrollablePanScanTests";
-	
+    public final String TAG = "BigEditTextActivityScrollablePanScanTests";
+    
     public BigEditTextActivityScrollablePanScanTests() {
         super(BigEditTextActivityScrollablePanScan.class);
     }
-	
-	@LargeTest
-	public void testAppAdjustmentPanScan() {       // Give the IME 2 seconds to appear.
+    
+    @LargeTest
+    public void testAppAdjustmentPanScan() {       // Give the IME 2 seconds to appear.
         pause(2000);
         
         View rootView = ((BigEditTextActivityScrollablePanScan) mTargetActivity).getRootView();
@@ -43,6 +43,6 @@
         destructiveCheckImeInitialState(rootView, servedView);
             
         verifyEditTextAdjustment(servedView, rootView.getMeasuredHeight());
-	}
-	
+    }
+    
 }
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollableResizeTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollableResizeTests.java
index 5c40e6d..de607d6 100644
--- a/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollableResizeTests.java
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollableResizeTests.java
@@ -24,15 +24,15 @@
 
 public class BigEditTextActivityScrollableResizeTests extends ImfBaseTestCase<BigEditTextActivityScrollableResize> {
 
-	public final String TAG = "BigEditTextActivityScrollableResizeTests";
-	
+    public final String TAG = "BigEditTextActivityScrollableResizeTests";
+    
     public BigEditTextActivityScrollableResizeTests() {
         super(BigEditTextActivityScrollableResize.class);
     }
-	
-	@LargeTest
-	public void testAppAdjustmentPanScan() {       
-	    // Give the IME 2 seconds to appear.
+    
+    @LargeTest
+    public void testAppAdjustmentPanScan() {       
+        // Give the IME 2 seconds to appear.
         pause(2000);
         
         View rootView = ((BigEditTextActivityScrollableResize) mTargetActivity).getRootView();
@@ -44,6 +44,6 @@
         destructiveCheckImeInitialState(rootView, servedView);
             
         verifyEditTextAdjustment(servedView, rootView.getMeasuredHeight());
-	}
-	
+    }
+    
 }
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/BottomEditTextActivityPanScanTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/BottomEditTextActivityPanScanTests.java
index 9a93133..c521905 100644
--- a/tests/ImfTest/tests/src/com/android/imftest/samples/BottomEditTextActivityPanScanTests.java
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/BottomEditTextActivityPanScanTests.java
@@ -24,14 +24,14 @@
 
 public class BottomEditTextActivityPanScanTests extends ImfBaseTestCase<BottomEditTextActivityPanScan> {
 
-	public final String TAG = "BottomEditTextActivityPanScanTests";
-	
+    public final String TAG = "BottomEditTextActivityPanScanTests";
+    
     public BottomEditTextActivityPanScanTests() {
         super(BottomEditTextActivityPanScan.class);
     }
-	
-	@LargeTest
-	public void testAppAdjustmentPanScan() {
+    
+    @LargeTest
+    public void testAppAdjustmentPanScan() {
         // Give the IME 2 seconds to appear.
         pause(2000);
         
@@ -44,6 +44,6 @@
         destructiveCheckImeInitialState(rootView, servedView);
         
         verifyEditTextAdjustment(servedView, rootView.getMeasuredHeight());
-	}
-	
+    }
+    
 }
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/ButtonActivityTest.java b/tests/ImfTest/tests/src/com/android/imftest/samples/ButtonActivityTest.java
index ae900c3..f6f97b5 100644
--- a/tests/ImfTest/tests/src/com/android/imftest/samples/ButtonActivityTest.java
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/ButtonActivityTest.java
@@ -23,8 +23,8 @@
 
 public class ButtonActivityTest extends ImfBaseTestCase<ButtonActivity> {
 
-	final public String TAG = "ButtonActivityTest";
-	
+    final public String TAG = "ButtonActivityTest";
+    
     public ButtonActivityTest() {
         super(ButtonActivity.class);
     }
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/OneEditTextActivityNotSelectedTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/OneEditTextActivityNotSelectedTests.java
index ed5b0c9..6147d3c 100644
--- a/tests/ImfTest/tests/src/com/android/imftest/samples/OneEditTextActivityNotSelectedTests.java
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/OneEditTextActivityNotSelectedTests.java
@@ -22,21 +22,21 @@
 
 public class OneEditTextActivityNotSelectedTests extends ImfBaseTestCase<OneEditTextActivityNotSelected> {
 
-	public final String TAG = "OneEditTextActivityNotSelectedTests";
-	
+    public final String TAG = "OneEditTextActivityNotSelectedTests";
+    
     public OneEditTextActivityNotSelectedTests() {
         super(OneEditTextActivityNotSelected.class);
     }
     
-	@LargeTest
-	public void testSoftKeyboardNoAutoPop() {
-	    
-	    // Give the IME 2 seconds to appear.
-	    pause(2000);
-	    
-	    assertFalse(mImm.isAcceptingText());
-	    
-	    View rootView = ((OneEditTextActivityNotSelected) mTargetActivity).getRootView();
+    @LargeTest
+    public void testSoftKeyboardNoAutoPop() {
+        
+        // Give the IME 2 seconds to appear.
+        pause(2000);
+        
+        assertFalse(mImm.isAcceptingText());
+        
+        View rootView = ((OneEditTextActivityNotSelected) mTargetActivity).getRootView();
         View servedView = ((OneEditTextActivityNotSelected) mTargetActivity).getDefaultFocusedView();
         
         assertNotNull(rootView);
@@ -45,6 +45,6 @@
         destructiveCheckImeInitialState(rootView, servedView);
         
         verifyEditTextAdjustment(servedView, rootView.getMeasuredHeight());
-	}
-	
+    }
+    
 }
diff --git a/tests/OneMedia/src/com/android/onemedia/IPlayerCallback.aidl b/tests/OneMedia/src/com/android/onemedia/IPlayerCallback.aidl
index 9bc3baa..2b14384 100644
--- a/tests/OneMedia/src/com/android/onemedia/IPlayerCallback.aidl
+++ b/tests/OneMedia/src/com/android/onemedia/IPlayerCallback.aidl
@@ -12,10 +12,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
+
 package com.android.onemedia;
 
-import android.media.MediaSessionToken;
+import android.media.session.MediaSessionToken;
 
 interface IPlayerCallback {
     void onSessionChanged(in MediaSessionToken session);
diff --git a/tests/OneMedia/src/com/android/onemedia/IPlayerService.aidl b/tests/OneMedia/src/com/android/onemedia/IPlayerService.aidl
index ab1d3fc..efdbe9a 100644
--- a/tests/OneMedia/src/com/android/onemedia/IPlayerService.aidl
+++ b/tests/OneMedia/src/com/android/onemedia/IPlayerService.aidl
@@ -12,17 +12,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
+
 package com.android.onemedia;
 
-import android.media.MediaSessionToken;
+import android.media.session.MediaSessionToken;
 import android.os.Bundle;
 
 import com.android.onemedia.IPlayerCallback;
 import com.android.onemedia.playback.IRequestCallback;
 
 interface IPlayerService {
-    MediaSessionToken getSessionToken(); 
+    MediaSessionToken getSessionToken();
     void registerCallback(in IPlayerCallback cb);
     void unregisterCallback(in IPlayerCallback cb);
     void sendRequest(String action, in Bundle params, in IRequestCallback cb);
diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerController.java b/tests/OneMedia/src/com/android/onemedia/PlayerController.java
index 4ccc846..3f15db5 100644
--- a/tests/OneMedia/src/com/android/onemedia/PlayerController.java
+++ b/tests/OneMedia/src/com/android/onemedia/PlayerController.java
@@ -1,8 +1,8 @@
 
 package com.android.onemedia;
 
-import android.media.MediaController;
-import android.media.MediaSessionManager;
+import android.media.session.MediaController;
+import android.media.session.MediaSessionManager;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerService.java b/tests/OneMedia/src/com/android/onemedia/PlayerService.java
index 0819077..0b2ba8f 100644
--- a/tests/OneMedia/src/com/android/onemedia/PlayerService.java
+++ b/tests/OneMedia/src/com/android/onemedia/PlayerService.java
@@ -2,7 +2,7 @@
 
 import android.app.Service;
 import android.content.Intent;
-import android.media.MediaSessionToken;
+import android.media.session.MediaSessionToken;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
index 25a8f0d..e5fb0d0 100644
--- a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
+++ b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
@@ -2,9 +2,9 @@
 
 import android.content.Context;
 import android.content.Intent;
-import android.media.MediaSession;
-import android.media.MediaSessionManager;
-import android.media.MediaSessionToken;
+import android.media.session.MediaSession;
+import android.media.session.MediaSessionManager;
+import android.media.session.MediaSessionToken;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.KeyEvent;
diff --git a/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java
index cceed16..3bd35a7 100644
--- a/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java
@@ -37,7 +37,7 @@
     }
 
     @SmallTest
-	public void testREORDER_TASKS() {
+    public void testREORDER_TASKS() {
         try {
             mAm.moveTaskToFront(0, 0, null);
             fail("IActivityManager.moveTaskToFront did not throw SecurityException as"
@@ -67,7 +67,7 @@
         } catch (RemoteException e) {
             fail("Unexpected remote exception");
         }
-	}
+    }
 
     @SmallTest
     public void testCHANGE_CONFIGURATION() {
diff --git a/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java
index 4dfe0fe..322b853 100644
--- a/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java
@@ -32,7 +32,7 @@
  */
 public class ServiceManagerPermissionTests extends TestCase {
     @SmallTest
-	public void testAddService() {
+    public void testAddService() {
         try {
             // The security in the service manager is that you can't replace
             // a service that is already published.
@@ -43,7 +43,7 @@
         } catch (SecurityException e) {
             // expected
         }
-	}
+    }
 
     @SmallTest
     public void testSetPermissionController() {
diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
index df32ee1..6f5788a 100644
--- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
@@ -41,7 +41,7 @@
     }
 
     @SmallTest
-	public void testMANAGE_APP_TOKENS() {
+    public void testMANAGE_APP_TOKENS() {
         try {
             mWm.pauseKeyDispatching(null);
             fail("IWindowManager.pauseKeyDispatching did not throw SecurityException as"
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index 2949f8e..806f8ff 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -5,7 +5,7 @@
 #
 
 # This tool is prebuilt if we're doing an app-only build.
-ifeq ($(TARGET_BUILD_APPS),)
+ifeq ($(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)),)
 
 
 aapt_src_files := \
@@ -101,4 +101,4 @@
 include $(BUILD_EXECUTABLE)
 endif
 
-endif # TARGET_BUILD_APPS
+endif # No TARGET_BUILD_APPS or TARGET_BUILD_PDK
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index cbeaae8..49b8b55 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -59,10 +59,10 @@
           mAndroidManifestFile(NULL), mPublicOutputFile(NULL),
           mRClassDir(NULL), mResourceIntermediatesDir(NULL), mManifestMinSdkVersion(NULL),
           mMinSdkVersion(NULL), mTargetSdkVersion(NULL), mMaxSdkVersion(NULL),
-          mVersionCode(NULL), mVersionName(NULL), mCustomPackage(NULL), mExtraPackages(NULL),
-          mMaxResVersion(NULL), mDebugMode(false), mNonConstantId(false), mProduct(NULL),
-          mUseCrunchCache(false), mErrorOnFailedInsert(false), mErrorOnMissingConfigEntry(false),
-          mOutputTextSymbols(NULL),
+          mVersionCode(NULL), mVersionName(NULL), mReplaceVersion(false), mCustomPackage(NULL),
+          mExtraPackages(NULL), mMaxResVersion(NULL), mDebugMode(false), mNonConstantId(false),
+          mProduct(NULL), mUseCrunchCache(false), mErrorOnFailedInsert(false),
+          mErrorOnMissingConfigEntry(false), mOutputTextSymbols(NULL),
           mSingleCrunchInputFile(NULL), mSingleCrunchOutputFile(NULL),
           mArgc(0), mArgv(NULL)
         {}
@@ -166,6 +166,8 @@
     void setVersionCode(const char*  val) { mVersionCode = val; }
     const char* getVersionName() const { return mVersionName; }
     void setVersionName(const char* val) { mVersionName = val; }
+    bool getReplaceVersion() { return mReplaceVersion; }
+    void setReplaceVersion(bool val) { mReplaceVersion = val; }
     const char* getCustomPackage() const { return mCustomPackage; }
     void setCustomPackage(const char* val) { mCustomPackage = val; }
     const char* getExtraPackages() const { return mExtraPackages; }
@@ -285,6 +287,7 @@
     const char* mMaxSdkVersion;
     const char* mVersionCode;
     const char* mVersionName;
+    bool        mReplaceVersion;
     const char* mCustomPackage;
     const char* mExtraPackages;
     const char* mMaxResVersion;
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 8e856b7..44b8340 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -435,6 +435,7 @@
     LARGEST_WIDTH_LIMIT_DP_ATTR = 0x01010366,
     PUBLIC_KEY_ATTR = 0x010103a6,
     CATEGORY_ATTR = 0x010103e8,
+    BANNER_ATTR = 0x10103f2,
 };
 
 String8 getComponentName(String8 &pkgName, String8 &componentName) {
@@ -762,6 +763,7 @@
             bool withinActivity = false;
             bool isMainActivity = false;
             bool isLauncherActivity = false;
+            bool isLeanbackLauncherActivity = false;
             bool isSearchable = false;
             bool withinApplication = false;
             bool withinSupportsInput = false;
@@ -872,6 +874,7 @@
             String8 activityName;
             String8 activityLabel;
             String8 activityIcon;
+            String8 activityBanner;
             String8 receiverName;
             String8 serviceName;
             Vector<String8> supportedInput;
@@ -896,16 +899,29 @@
                         withinApplication = false;
                         withinSupportsInput = false;
                     } else if (depth < 3) {
-                        if (withinActivity && isMainActivity && isLauncherActivity) {
+                        if (withinActivity && isMainActivity) {
                             String8 aName(getComponentName(pkg, activityName));
-                            printf("launchable-activity:");
-                            if (aName.length() > 0) {
-                                printf(" name='%s' ",
-                                        ResTable::normalizeForOutput(aName.string()).string());
+                            if (isLauncherActivity) {
+                                printf("launchable-activity:");
+                                if (aName.length() > 0) {
+                                    printf(" name='%s' ",
+                                            ResTable::normalizeForOutput(aName.string()).string());
+                                }
+                                printf(" label='%s' icon='%s'\n",
+                                        ResTable::normalizeForOutput(activityLabel.string()).string(),
+                                        ResTable::normalizeForOutput(activityIcon.string()).string());
                             }
-                            printf(" label='%s' icon='%s'\n",
-                                    ResTable::normalizeForOutput(activityLabel.string()).string(),
-                                    ResTable::normalizeForOutput(activityIcon.string()).string());
+                            if (isLeanbackLauncherActivity) {
+                                printf("leanback-launchable-activity:");
+                                if (aName.length() > 0) {
+                                    printf(" name='%s' ",
+                                            ResTable::normalizeForOutput(aName.string()).string());
+                                }
+                                printf(" label='%s' icon='%s' banner='%s'\n",
+                                        ResTable::normalizeForOutput(activityLabel.string()).string(),
+                                        ResTable::normalizeForOutput(activityIcon.string()).string(),
+                                        ResTable::normalizeForOutput(activityBanner.string()).string());
+                            }
                         }
                         if (!hasIntentFilter) {
                             hasOtherActivities |= withinActivity;
@@ -923,7 +939,7 @@
                         withinService = false;
                         withinReceiver = false;
                         hasIntentFilter = false;
-                        isMainActivity = isLauncherActivity = false;
+                        isMainActivity = isLauncherActivity = isLeanbackLauncherActivity = false;
                     } else if (depth < 4) {
                         if (withinIntentFilter) {
                             if (withinActivity) {
@@ -1329,6 +1345,13 @@
                                 goto bail;
                             }
 
+                            activityBanner = getResolvedAttribute(&res, tree, BANNER_ATTR, &error);
+                            if (error != "") {
+                                fprintf(stderr, "ERROR getting 'android:banner' attribute: %s\n",
+                                        error.string());
+                                goto bail;
+                            }
+
                             int32_t orien = getResolvedIntegerAttribute(&res, tree,
                                     SCREEN_ORIENTATION_ATTR, &error);
                             if (error == "") {
@@ -1538,6 +1561,8 @@
                         if (withinActivity) {
                             if (category == "android.intent.category.LAUNCHER") {
                                 isLauncherActivity = true;
+                            } else if (category == "android.intent.category.LEANBACK_LAUNCHER") {
+                                isLeanbackLauncherActivity = true;
                             }
                         }
                     }
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index 1ed4630..33711fa 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -153,6 +153,11 @@
         "       inserts android:versionCode in to manifest.\n"
         "   --version-name\n"
         "       inserts android:versionName in to manifest.\n"
+        "   --replace-version\n"
+        "       If --version-code and/or --version-name are specified, these\n"
+        "       values will replace any value already in the manifest. By\n"
+        "       default, nothing is changed if the manifest already defines\n"
+        "       these attributes.\n"
         "   --custom-package\n"
         "       generates R.java into a different package.\n"
         "   --extra-packages\n"
@@ -532,6 +537,8 @@
                         goto bail;
                     }
                     bundle.setVersionName(argv[0]);
+                } else if (strcmp(cp, "-replace-version") == 0) {
+                    bundle.setReplaceVersion(true);
                 } else if (strcmp(cp, "-values") == 0) {
                     bundle.setValues(true);
                 } else if (strcmp(cp, "-include-meta-data") == 0) {
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index c923bc2..6d9d62e 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -676,13 +676,15 @@
 }
 
 /*
- * Inserts an attribute in a given node, only if the attribute does not
- * exist.
+ * Inserts an attribute in a given node.
  * If errorOnFailedInsert is true, and the attribute already exists, returns false.
- * Returns true otherwise, even if the attribute already exists.
+ * If replaceExisting is true, the attribute will be updated if it already exists.
+ * Returns true otherwise, even if the attribute already exists, and does not modify
+ * the existing attribute's value.
  */
 bool addTagAttribute(const sp<XMLNode>& node, const char* ns8,
-        const char* attr8, const char* value, bool errorOnFailedInsert)
+        const char* attr8, const char* value, bool errorOnFailedInsert,
+        bool replaceExisting)
 {
     if (value == NULL) {
         return true;
@@ -691,7 +693,16 @@
     const String16 ns(ns8);
     const String16 attr(attr8);
 
-    if (node->getAttribute(ns, attr) != NULL) {
+    XMLNode::attribute_entry* existingEntry = node->editAttribute(ns, attr);
+    if (existingEntry != NULL) {
+        if (replaceExisting) {
+            NOISY(printf("Info: AndroidManifest.xml already defines %s (in %s);"
+                         " overwriting existing value from manifest.\n",
+                         String8(attr).string(), String8(ns).string()));
+            existingEntry->string = String16(value);
+            return true;
+        }
+
         if (errorOnFailedInsert) {
             fprintf(stderr, "Error: AndroidManifest.xml already defines %s (in %s);"
                             " cannot insert new value %s.\n",
@@ -711,6 +722,18 @@
     return true;
 }
 
+/*
+ * Inserts an attribute in a given node, only if the attribute does not
+ * exist.
+ * If errorOnFailedInsert is true, and the attribute already exists, returns false.
+ * Returns true otherwise, even if the attribute already exists.
+ */
+bool addTagAttribute(const sp<XMLNode>& node, const char* ns8,
+        const char* attr8, const char* value, bool errorOnFailedInsert)
+{
+    return addTagAttribute(node, ns8, attr8, value, errorOnFailedInsert, false);
+}
+
 static void fullyQualifyClassName(const String8& package, sp<XMLNode> node,
         const String16& attrName) {
     XMLNode::attribute_entry* attr = node->editAttribute(
@@ -748,13 +771,14 @@
     }
 
     bool errorOnFailedInsert = bundle->getErrorOnFailedInsert();
+    bool replaceVersion = bundle->getReplaceVersion();
 
     if (!addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "versionCode",
-            bundle->getVersionCode(), errorOnFailedInsert)) {
+            bundle->getVersionCode(), errorOnFailedInsert, replaceVersion)) {
         return UNKNOWN_ERROR;
     }
     if (!addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "versionName",
-            bundle->getVersionName(), errorOnFailedInsert)) {
+            bundle->getVersionName(), errorOnFailedInsert, replaceVersion)) {
         return UNKNOWN_ERROR;
     }
     
diff --git a/tools/aidl/Android.mk b/tools/aidl/Android.mk
index 77d46ab..efd60a2 100644
--- a/tools/aidl/Android.mk
+++ b/tools/aidl/Android.mk
@@ -3,7 +3,7 @@
 # Copies files into the directory structure described by a manifest
 
 # This tool is prebuilt if we're doing an app-only build.
-ifeq ($(TARGET_BUILD_APPS),)
+ifeq ($(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)),)
 
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
@@ -26,4 +26,4 @@
 
 include $(BUILD_HOST_EXECUTABLE)
 
-endif # TARGET_BUILD_APPS
+endif # No TARGET_BUILD_APPS or TARGET_BUILD_PDK
diff --git a/tools/aidl/Type.cpp b/tools/aidl/Type.cpp
index d572af6..2267750 100644
--- a/tools/aidl/Type.cpp
+++ b/tools/aidl/Type.cpp
@@ -1,5 +1,7 @@
 #include "Type.h"
 
+#include <sys/types.h>
+
 Namespace NAMES;
 
 Type* VOID_TYPE;
diff --git a/tools/layoutlib/bridge/.classpath b/tools/layoutlib/bridge/.classpath
index 2e4274d..aef3efa 100644
--- a/tools/layoutlib/bridge/.classpath
+++ b/tools/layoutlib/bridge/.classpath
@@ -1,12 +1,14 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 	<classpathentry excluding="org/kxml2/io/" kind="src" path="src"/>
+	<classpathentry kind="src" path="tests/src"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
-	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/layoutlib_api/layoutlib_api-prebuilt.jar"/>
+	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/layoutlib_api/layoutlib_api-prebuilt.jar" sourcepath="/ANDROID_SRC/tools/base/layoutlib-api/src/main"/>
 	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/kxml2/kxml2-2.3.0.jar" sourcepath="/ANDROID_PLAT_SRC/dalvik/libcore/xml/src/main/java"/>
 	<classpathentry kind="var" path="ANDROID_PLAT_SRC/out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar" sourcepath="/ANDROID_PLAT_SRC/frameworks/base"/>
 	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/ninepatch/ninepatch-prebuilt.jar"/>
 	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/tools-common/tools-common-prebuilt.jar"/>
 	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/icu4j/icu4j.jar"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java b/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java
index ca710cd..4603b63 100644
--- a/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java
@@ -48,14 +48,14 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static int nGetMultipleIntMethod(Class<?> targetClass, String methodName,
+    /*package*/ static long nGetMultipleIntMethod(Class<?> targetClass, String methodName,
             int numParams) {
         // TODO: return the right thing.
         return 0;
     }
 
     @LayoutlibDelegate
-    /*package*/ static int nGetMultipleFloatMethod(Class<?> targetClass, String methodName,
+    /*package*/ static long nGetMultipleFloatMethod(Class<?> targetClass, String methodName,
             int numParams) {
         // TODO: return the right thing.
         return 0;
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index 1cc8ea5..bb05d45 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -344,7 +344,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_saveLayer(long nativeCanvas, RectF bounds,
+    /*package*/ static int native_saveLayer(long nativeCanvas, RectF bounds,
                                                long paint, int layerFlags) {
         // get the delegate from the native int.
         Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -361,7 +361,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_saveLayer(long nativeCanvas, float l,
+    /*package*/ static int native_saveLayer(long nativeCanvas, float l,
                                                float t, float r, float b,
                                                long paint, int layerFlags) {
         // get the delegate from the native int.
@@ -380,7 +380,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_saveLayerAlpha(long nativeCanvas,
+    /*package*/ static int native_saveLayerAlpha(long nativeCanvas,
                                                     RectF bounds, int alpha,
                                                     int layerFlags) {
         // get the delegate from the native int.
@@ -393,7 +393,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_saveLayerAlpha(long nativeCanvas, float l,
+    /*package*/ static int native_saveLayerAlpha(long nativeCanvas, float l,
                                                     float t, float r, float b,
                                                     int alpha, int layerFlags) {
         // get the delegate from the native int.
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index 7007b71..de2e592 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -688,7 +688,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_getStyle(long native_object) {
+    /*package*/ static int native_getStyle(long native_object) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
@@ -710,7 +710,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_getStrokeCap(long native_object) {
+    /*package*/ static int native_getStrokeCap(long native_object) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
@@ -732,7 +732,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_getStrokeJoin(long native_object) {
+    /*package*/ static int native_getStrokeJoin(long native_object) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
@@ -889,7 +889,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_getTextAlign(long native_object) {
+    /*package*/ static int native_getTextAlign(long native_object) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
         if (delegate == null) {
@@ -922,7 +922,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_getTextWidths(long native_object, char[] text, int index,
+    /*package*/ static int native_getTextWidths(long native_object, char[] text, int index,
             int count, int bidiFlags, float[] widths) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(native_object);
@@ -964,14 +964,14 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_getTextWidths(long native_object, String text, int start,
+    /*package*/ static int native_getTextWidths(long native_object, String text, int start,
             int end, int bidiFlags, float[] widths) {
         return native_getTextWidths(native_object, text.toCharArray(), start, end - start,
                 bidiFlags, widths);
     }
 
     @LayoutlibDelegate
-    /* package */static long native_getTextGlyphs(long native_object, String text, int start,
+    /* package */static int native_getTextGlyphs(long native_object, String text, int start,
             int end, int contextStart, int contextEnd, int flags, char[] glyphs) {
         // FIXME
         return 0;
@@ -1012,7 +1012,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_getTextRunCursor(Paint thisPaint, long native_object, char[] text,
+    /*package*/ static int native_getTextRunCursor(Paint thisPaint, long native_object, char[] text,
             int contextStart, int contextLength, int flags, int offset, int cursorOpt) {
         // FIXME
         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -1021,7 +1021,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_getTextRunCursor(Paint thisPaint, long native_object, String text,
+    /*package*/ static int native_getTextRunCursor(Paint thisPaint, long native_object, String text,
             int contextStart, int contextEnd, int flags, int offset, int cursorOpt) {
         // FIXME
         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index 77468ec..6666385 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -142,7 +142,7 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static long native_getFillType(long nPath) {
+    /*package*/ static int native_getFillType(long nPath) {
         Path_Delegate pathDelegate = sManager.getDelegate(nPath);
         if (pathDelegate == null) {
             return 0;
diff --git a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
index ea23649..edb7025 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
@@ -275,21 +275,20 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean nativeSetRegion(long native_dst, long native_src) {
+    /*package*/ static void nativeSetRegion(long native_dst, long native_src) {
         Region_Delegate dstRegion = sManager.getDelegate(native_dst);
         if (dstRegion == null) {
-            return true;
+            return;
         }
 
         Region_Delegate srcRegion = sManager.getDelegate(native_src);
         if (srcRegion == null) {
-            return true;
+            return;
         }
 
         dstRegion.mArea.reset();
         dstRegion.mArea.add(srcRegion.mArea);
 
-        return true;
     }
 
     @LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java b/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java
index fd594f7..5f0d98b 100644
--- a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java
@@ -33,11 +33,6 @@
     private static long sBootTime = System.currentTimeMillis();
     private static long sBootTimeNano = System.nanoTime();
 
-    @LayoutlibDelegate
-    /*package*/ static boolean setCurrentTimeMillis(long millis) {
-        return true;
-    }
-
     /**
      * Returns milliseconds since boot, not counting time spent in deep sleep.
      * <b>Note:</b> This value may get reset occasionally (before it would
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index 281337c..a90632c 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -39,7 +39,7 @@
     }
 
     @Override
-    public void acquireWakeLock(IBinder arg0, int arg1, String arg2, String arg2_5, WorkSource arg3)
+    public void acquireWakeLock(IBinder arg0, int arg1, String arg2, String arg2_5, WorkSource arg3, String arg4)
             throws RemoteException {
         // pass for now.
     }
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/TestDelegates.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/TestDelegates.java
index d3218db..274516c 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/TestDelegates.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/TestDelegates.java
@@ -121,6 +121,15 @@
                 Method delegateMethod = delegateClass.getDeclaredMethod(originalMethod.getName(),
                         parameters);
 
+                // check the return type of the methods match.
+                assertTrue(
+                        String.format("Delegate method %1$s.%2$s does not match the corresponding " +
+                                "framework method which returns %3$s",
+                                delegateClass.getName(),
+                                getMethodName(delegateMethod),
+                                originalMethod.getReturnType().getName()),
+                        delegateMethod.getReturnType() == originalMethod.getReturnType());
+
                 // check that the method has the annotation
                 assertNotNull(
                         String.format(
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
index a79fba1..2ef3d5f 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
@@ -114,6 +114,7 @@
                         "android.os.*",  // for android.os.Handler
                         "android.database.ContentObserver", // for Digital clock
                         "com.android.i18n.phonenumbers.*",  // for TextView with autolink attribute
+                        "android.app.DatePickerDialog",     // b.android.com/28318
                     },
                     excludeClasses,
                     new String[] {
diff --git a/tools/preload/Android.mk b/tools/preload/Android.mk
index f325870..14a4547 100644
--- a/tools/preload/Android.mk
+++ b/tools/preload/Android.mk
@@ -20,4 +20,4 @@
 
 include $(BUILD_HOST_JAVA_LIBRARY)
 
-include $(call all-subdir-makefiles)
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 4a6b1ff..84e933d 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -20,6 +20,8 @@
 import android.net.wifi.BatchedScanSettings;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
+import android.net.wifi.ScanSettings;
+import android.net.wifi.WifiChannel;
 import android.net.wifi.ScanResult;
 import android.net.DhcpInfo;
 
@@ -45,7 +47,9 @@
 
     boolean pingSupplicant();
 
-    void startScan(in WorkSource ws);
+    List<WifiChannel> getChannelList();
+
+    void startScan(in ScanSettings requested, in WorkSource ws);
 
     List<ScanResult> getScanResults(String callingPackage);
 
diff --git a/wifi/java/android/net/wifi/ScanSettings.aidl b/wifi/java/android/net/wifi/ScanSettings.aidl
new file mode 100644
index 0000000..ebd2a39
--- /dev/null
+++ b/wifi/java/android/net/wifi/ScanSettings.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+parcelable ScanSettings;
diff --git a/wifi/java/android/net/wifi/ScanSettings.java b/wifi/java/android/net/wifi/ScanSettings.java
new file mode 100644
index 0000000..094ce34
--- /dev/null
+++ b/wifi/java/android/net/wifi/ScanSettings.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Bundle of customized scan settings
+ *
+ * @see WifiManager#startCustomizedScan
+ *
+ * @hide
+ */
+public class ScanSettings implements Parcelable {
+
+    /** channel set to scan. this can be null or empty, indicating a full scan */
+    public Collection<WifiChannel> channelSet;
+
+    /** public constructor */
+    public ScanSettings() { }
+
+    /** copy constructor */
+    public ScanSettings(ScanSettings source) {
+        if (source.channelSet != null)
+            channelSet = new ArrayList<WifiChannel>(source.channelSet);
+    }
+
+    /** check for validity */
+    public boolean isValid() {
+        for (WifiChannel channel : channelSet)
+            if (!channel.isValid()) return false;
+        return true;
+    }
+
+    /** implement Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** implement Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(channelSet == null ? 0 : channelSet.size());
+        if (channelSet != null)
+            for (WifiChannel channel : channelSet) channel.writeToParcel(out, flags);
+    }
+
+    /** implement Parcelable interface */
+    public static final Parcelable.Creator<ScanSettings> CREATOR =
+            new Parcelable.Creator<ScanSettings>() {
+        @Override
+        public ScanSettings createFromParcel(Parcel in) {
+            ScanSettings settings = new ScanSettings();
+            int size = in.readInt();
+            if (size > 0) {
+                settings.channelSet = new ArrayList<WifiChannel>(size);
+                while (size-- > 0)
+                    settings.channelSet.add(WifiChannel.CREATOR.createFromParcel(in));
+            }
+            return settings;
+        }
+
+        @Override
+        public ScanSettings[] newArray(int size) {
+            return new ScanSettings[size];
+        }
+    };
+}
diff --git a/wifi/java/android/net/wifi/WifiChannel.aidl b/wifi/java/android/net/wifi/WifiChannel.aidl
new file mode 100644
index 0000000..c3d06bd
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiChannel.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+parcelable WifiChannel;
diff --git a/wifi/java/android/net/wifi/WifiChannel.java b/wifi/java/android/net/wifi/WifiChannel.java
new file mode 100644
index 0000000..640481e
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiChannel.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Wifi Channel
+ *
+ * @see ScanSettings
+ *
+ * @hide
+ */
+public class WifiChannel implements Parcelable {
+
+    private static final int MIN_FREQ_MHZ = 2412;
+    private static final int MAX_FREQ_MHZ = 5825;
+
+    private static final int MIN_CHANNEL_NUM = 1;
+    private static final int MAX_CHANNEL_NUM = 196;
+
+    /** frequency */
+    public int freqMHz;
+
+    /** channel number */
+    public int channelNum;
+
+    /** is it a DFS channel? */
+    public boolean isDFS;
+
+    /** public constructor */
+    public WifiChannel() { }
+
+    /** check for validity */
+    public boolean isValid() {
+        if (freqMHz < MIN_FREQ_MHZ || freqMHz > MAX_FREQ_MHZ) return false;
+        if (channelNum < MIN_CHANNEL_NUM || channelNum > MAX_CHANNEL_NUM) return false;
+        return true;
+    }
+
+    /** implement Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** implement Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(freqMHz);
+        out.writeInt(channelNum);
+        out.writeInt(isDFS ? 1 : 0);
+    }
+
+    /** implement Parcelable interface */
+    public static final Parcelable.Creator<WifiChannel> CREATOR =
+            new Parcelable.Creator<WifiChannel>() {
+        @Override
+        public WifiChannel createFromParcel(Parcel in) {
+            WifiChannel channel = new WifiChannel();
+            channel.freqMHz = in.readInt();
+            channel.channelNum = in.readInt();
+            channel.isDFS = in.readInt() != 0;
+            return channel;
+        }
+
+        @Override
+        public WifiChannel[] newArray(int size) {
+            return new WifiChannel[size];
+        }
+    };
+}
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 6a13067..4a6821c 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -69,6 +69,10 @@
     public static final String LINK_SPEED_UNITS = "Mbps";
     private int mLinkSpeed;
 
+    /** Frequency in MHz */
+    public static final String FREQUENCY_UNITS = "MHz";
+    private int mFrequency;
+
     private InetAddress mIpAddress;
     private String mMacAddress;
 
@@ -86,6 +90,7 @@
         mSupplicantState = SupplicantState.UNINITIALIZED;
         mRssi = -9999;
         mLinkSpeed = -1;
+        mFrequency = -1;
     }
 
     /**
@@ -100,6 +105,7 @@
             mNetworkId = source.mNetworkId;
             mRssi = source.mRssi;
             mLinkSpeed = source.mLinkSpeed;
+            mFrequency = source.mFrequency;
             mIpAddress = source.mIpAddress;
             mMacAddress = source.mMacAddress;
             mMeteredHint = source.mMeteredHint;
@@ -179,6 +185,20 @@
     }
 
     /**
+     * Returns the current frequency in {@link #FREQUENCY_UNITS}.
+     * @return the frequency.
+     * @see #FREQUENCY_UNITS
+     */
+    public int getFrequency() {
+        return mFrequency;
+    }
+
+    /** @hide */
+    public void setFrequency(int frequency) {
+        this.mFrequency = frequency;
+    }
+
+    /**
      * Record the MAC address of the WLAN interface
      * @param macAddress the MAC address in {@code XX:XX:XX:XX:XX:XX} form
      * @hide
@@ -303,7 +323,8 @@
             append(", Supplicant state: ").
             append(mSupplicantState == null ? none : mSupplicantState).
             append(", RSSI: ").append(mRssi).
-            append(", Link speed: ").append(mLinkSpeed).
+            append(", Link speed: ").append(mLinkSpeed).append(LINK_SPEED_UNITS).
+            append(", Frequency: ").append(mFrequency).append(FREQUENCY_UNITS).
             append(", Net ID: ").append(mNetworkId).
             append(", Metered hint: ").append(mMeteredHint);
 
@@ -320,6 +341,7 @@
         dest.writeInt(mNetworkId);
         dest.writeInt(mRssi);
         dest.writeInt(mLinkSpeed);
+        dest.writeInt(mFrequency);
         if (mIpAddress != null) {
             dest.writeByte((byte)1);
             dest.writeByteArray(mIpAddress.getAddress());
@@ -346,6 +368,7 @@
                 info.setNetworkId(in.readInt());
                 info.setRssi(in.readInt());
                 info.setLinkSpeed(in.readInt());
+                info.setFrequency(in.readInt());
                 if (in.readByte() == 1) {
                     try {
                         info.setInetAddress(InetAddress.getByAddress(in.createByteArray()));
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index aabe007..0862b7e 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -20,6 +20,8 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.Context;
 import android.net.DhcpInfo;
+import android.net.wifi.ScanSettings;
+import android.net.wifi.WifiChannel;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Handler;
@@ -763,6 +765,22 @@
     }
 
     /**
+     * Get a list of available channels for customized scan.
+     *
+     * @see {@link WifiChannel}
+     *
+     * @return the channel list, or null if not available
+     * @hide
+     */
+    public List<WifiChannel> getChannelList() {
+        try {
+            return mService.getChannelList();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
      * Request a scan for access points. Returns immediately. The availability
      * of the results is made known later by means of an asynchronous event sent
      * on completion of the scan.
@@ -770,8 +788,7 @@
      */
     public boolean startScan() {
         try {
-            final WorkSource workSource = null;
-            mService.startScan(workSource);
+            mService.startScan(null, null);
             return true;
         } catch (RemoteException e) {
             return false;
@@ -781,7 +798,42 @@
     /** @hide */
     public boolean startScan(WorkSource workSource) {
         try {
-            mService.startScan(workSource);
+            mService.startScan(null, workSource);
+            return true;
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Request a scan for access points in specified channel list. Each channel is specified by its
+     * frequency in MHz, e.g. "5500" (do NOT include "DFS" even though it is). The availability of
+     * the results is made known later in the same way as {@link #startScan}.
+     *
+     * Note:
+     *
+     * 1. Customized scan is for non-connection purposes, i.e. it won't trigger a wifi connection
+     *    even though it finds some known networks.
+     *
+     * 2. Customized scan result may include access points that is not specified in the channel
+     *    list. An app will need to do frequency filtering if it wants to get pure results for the
+     *    channel list it specified.
+     *
+     * @hide
+     */
+    public boolean startCustomizedScan(ScanSettings requested) {
+        try {
+            mService.startScan(requested, null);
+            return true;
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /** @hide */
+    public boolean startCustomizedScan(ScanSettings requested, WorkSource workSource) {
+        try {
+            mService.startScan(requested, workSource);
             return true;
         } catch (RemoteException e) {
             return false;