Merge "Refactor VirtualLightRefBase & JNI"
diff --git a/api/current.txt b/api/current.txt
index 9910fdf..89261b2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -567,6 +567,7 @@
     field public static final int freezesText = 16843116; // 0x101016c
     field public static final int fromAlpha = 16843210; // 0x10101ca
     field public static final int fromDegrees = 16843187; // 0x10101b3
+    field public static final int fromId = 16843856; // 0x1010450
     field public static final int fromScene = 16843741; // 0x10103dd
     field public static final int fromXDelta = 16843206; // 0x10101c6
     field public static final int fromXScale = 16843202; // 0x10101c2
@@ -956,6 +957,7 @@
     field public static final int restoreAnyVersion = 16843450; // 0x10102ba
     field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
     field public static final int restrictedAccountType = 16843733; // 0x10103d5
+    field public static final int reversible = 16843857; // 0x1010451
     field public static final int right = 16843183; // 0x10101af
     field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
     field public static final int ringtoneType = 16843257; // 0x10101f9
@@ -1214,6 +1216,7 @@
     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 toId = 16843855; // 0x101044f
     field public static final int toScene = 16843742; // 0x10103de
     field public static final int toXDelta = 16843207; // 0x10101c7
     field public static final int toXScale = 16843203; // 0x10101c3
@@ -3258,6 +3261,7 @@
     method public boolean onContextItemSelected(android.view.MenuItem);
     method public void onContextMenuClosed(android.view.Menu);
     method protected void onCreate(android.os.Bundle);
+    method protected void onCreate(android.os.Bundle, android.os.PersistableBundle);
     method public void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo);
     method public java.lang.CharSequence onCreateDescription();
     method protected deprecated android.app.Dialog onCreateDialog(int);
@@ -3288,6 +3292,7 @@
     method public void onPanelClosed(int, android.view.Menu);
     method protected void onPause();
     method protected void onPostCreate(android.os.Bundle);
+    method protected void onPostCreate(android.os.Bundle, android.os.PersistableBundle);
     method protected void onPostResume();
     method protected deprecated void onPrepareDialog(int, android.app.Dialog);
     method protected deprecated void onPrepareDialog(int, android.app.Dialog, android.os.Bundle);
@@ -3297,9 +3302,11 @@
     method public void onProvideAssistData(android.os.Bundle);
     method protected void onRestart();
     method protected void onRestoreInstanceState(android.os.Bundle);
+    method protected void onRestoreInstanceState(android.os.Bundle, android.os.PersistableBundle);
     method protected void onResume();
     method public deprecated java.lang.Object onRetainNonConfigurationInstance();
     method protected void onSaveInstanceState(android.os.Bundle);
+    method protected void onSaveInstanceState(android.os.Bundle, android.os.PersistableBundle);
     method public boolean onSearchRequested();
     method protected void onStart();
     method protected void onStop();
@@ -4195,14 +4202,18 @@
     method public android.app.Instrumentation.ActivityMonitor addMonitor(android.content.IntentFilter, android.app.Instrumentation.ActivityResult, boolean);
     method public android.app.Instrumentation.ActivityMonitor addMonitor(java.lang.String, android.app.Instrumentation.ActivityResult, boolean);
     method public void callActivityOnCreate(android.app.Activity, android.os.Bundle);
+    method public void callActivityOnCreate(android.app.Activity, android.os.Bundle, android.os.PersistableBundle);
     method public void callActivityOnDestroy(android.app.Activity);
     method public void callActivityOnNewIntent(android.app.Activity, android.content.Intent);
     method public void callActivityOnPause(android.app.Activity);
     method public void callActivityOnPostCreate(android.app.Activity, android.os.Bundle);
+    method public void callActivityOnPostCreate(android.app.Activity, android.os.Bundle, android.os.PersistableBundle);
     method public void callActivityOnRestart(android.app.Activity);
     method public void callActivityOnRestoreInstanceState(android.app.Activity, android.os.Bundle);
+    method public void callActivityOnRestoreInstanceState(android.app.Activity, android.os.Bundle, android.os.PersistableBundle);
     method public void callActivityOnResume(android.app.Activity);
     method public void callActivityOnSaveInstanceState(android.app.Activity, android.os.Bundle);
+    method public void callActivityOnSaveInstanceState(android.app.Activity, android.os.Bundle, android.os.PersistableBundle);
     method public void callActivityOnStart(android.app.Activity);
     method public void callActivityOnStop(android.app.Activity);
     method public void callActivityOnUserLeaving(android.app.Activity);
@@ -10822,6 +10833,12 @@
     method public abstract void stop();
   }
 
+  public class AnimatedStateListDrawable extends android.graphics.drawable.StateListDrawable {
+    ctor public AnimatedStateListDrawable();
+    method public void addState(int[], android.graphics.drawable.Drawable, int);
+    method public void addTransition(int, int, android.graphics.drawable.AnimationDrawable, boolean);
+  }
+
   public class AnimationDrawable extends android.graphics.drawable.DrawableContainer implements android.graphics.drawable.Animatable java.lang.Runnable {
     ctor public AnimationDrawable();
     method public void addFrame(android.graphics.drawable.Drawable, int);
@@ -13366,6 +13383,7 @@
     field public static final int ENCODING_INVALID = 0; // 0x0
     field public static final int ENCODING_PCM_16BIT = 2; // 0x2
     field public static final int ENCODING_PCM_8BIT = 3; // 0x3
+    field public static final int ENCODING_PCM_FLOAT = 4; // 0x4
   }
 
   public class AudioManager {
@@ -13583,6 +13601,7 @@
     method public void stop() throws java.lang.IllegalStateException;
     method public int write(byte[], int, int);
     method public int write(short[], int, int);
+    method public int write(float[], int, int, int);
     method public int write(java.nio.ByteBuffer, int, int);
     field public static final int ERROR = -1; // 0xffffffff
     field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe
@@ -13815,6 +13834,7 @@
     method public final void queueSecureInputBuffer(int, int, android.media.MediaCodec.CryptoInfo, long, int) throws android.media.MediaCodec.CryptoException;
     method public final void release();
     method public final void releaseOutputBuffer(int, boolean);
+    method public final void releaseOutputBuffer(int, long);
     method public void setNotificationCallback(android.media.MediaCodec.NotificationCallback);
     method public final void setParameters(android.os.Bundle);
     method public final void setVideoScalingMode(int);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index ef6fcb7..66b82eb 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -17,6 +17,7 @@
 package android.app;
 
 import android.annotation.NonNull;
+import android.os.PersistableBundle;
 import android.transition.Scene;
 import android.transition.TransitionManager;
 import android.util.ArrayMap;
@@ -922,6 +923,30 @@
     }
 
     /**
+     * Same as {@link #onCreate(android.os.Bundle)} but called for those activities created with
+     * the attribute {@link android.R.attr#persistable} set true.
+     *
+     * @param savedInstanceState if the activity is being re-initialized after
+     *     previously being shut down then this Bundle contains the data it most
+     *     recently supplied in {@link #onSaveInstanceState}.
+     *     <b><i>Note: Otherwise it is null.</i></b>
+     * @param persistentState if the activity is being re-initialized after
+     *     previously being shut down or powered off then this Bundle contains the data it most
+     *     recently supplied to outPersistentState in {@link #onSaveInstanceState}.
+     *     <b><i>Note: Otherwise it is null.</i></b>
+     *
+     * @see #onCreate(android.os.Bundle)
+     * @see #onStart
+     * @see #onSaveInstanceState
+     * @see #onRestoreInstanceState
+     * @see #onPostCreate
+     */
+    protected void onCreate(@Nullable Bundle savedInstanceState,
+            @Nullable PersistableBundle persistentState) {
+        onCreate(savedInstanceState);
+    }
+
+    /**
      * The hook for {@link ActivityThread} to restore the state of this activity.
      *
      * Calls {@link #onSaveInstanceState(android.os.Bundle)} and
@@ -935,6 +960,23 @@
     }
 
     /**
+     * The hook for {@link ActivityThread} to restore the state of this activity.
+     *
+     * Calls {@link #onSaveInstanceState(android.os.Bundle)} and
+     * {@link #restoreManagedDialogs(android.os.Bundle)}.
+     *
+     * @param savedInstanceState contains the saved state
+     * @param persistentState contains the persistable saved state
+     */
+    final void performRestoreInstanceState(Bundle savedInstanceState,
+            PersistableBundle persistentState) {
+        onRestoreInstanceState(savedInstanceState, persistentState);
+        if (savedInstanceState != null) {
+            restoreManagedDialogs(savedInstanceState);
+        }
+    }
+
+    /**
      * This method is called after {@link #onStart} when the activity is
      * being re-initialized from a previously saved state, given here in
      * <var>savedInstanceState</var>.  Most implementations will simply use {@link #onCreate}
@@ -962,7 +1004,34 @@
             }
         }
     }
-    
+
+    /**
+     * This is the same as {@link #onRestoreInstanceState(Bundle)} but is called for activities
+     * created with the attribute {@link android.R.attr#persistable}. The {@link
+     * android.os.PersistableBundle} passed came from the restored PersistableBundle first
+     * saved in {@link #onSaveInstanceState(Bundle, PersistableBundle)}.
+     *
+     * <p>This method is called between {@link #onStart} and
+     * {@link #onPostCreate}.
+     *
+     * <p>If this method is called {@link #onRestoreInstanceState(Bundle)} will not be called.
+     *
+     * @param savedInstanceState the data most recently supplied in {@link #onSaveInstanceState}.
+     * @param persistentState the data most recently supplied in {@link #onSaveInstanceState}.
+     *
+     * @see #onRestoreInstanceState(Bundle)
+     * @see #onCreate
+     * @see #onPostCreate
+     * @see #onResume
+     * @see #onSaveInstanceState
+     */
+    protected void onRestoreInstanceState(Bundle savedInstanceState,
+            PersistableBundle persistentState) {
+        if (savedInstanceState != null) {
+            onRestoreInstanceState(savedInstanceState);
+        }
+    }
+
     /**
      * Restore the state of any saved managed dialogs.
      *
@@ -1039,6 +1108,21 @@
     }
 
     /**
+     * This is the same as {@link #onPostCreate(Bundle)} but is called for activities
+     * created with the attribute {@link android.R.attr#persistable}.
+     *
+     * @param savedInstanceState The data most recently supplied in {@link #onSaveInstanceState}
+     * @param persistentState The data caming from the PersistableBundle first
+     * saved in {@link #onSaveInstanceState(Bundle, PersistableBundle)}.
+     *
+     * @see #onCreate
+     */
+    protected void onPostCreate(@Nullable Bundle savedInstanceState,
+            @Nullable PersistableBundle persistentState) {
+        onPostCreate(savedInstanceState);
+    }
+
+    /**
      * 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}.
@@ -1194,6 +1278,22 @@
     }
 
     /**
+     * The hook for {@link ActivityThread} to save the state of this activity.
+     *
+     * Calls {@link #onSaveInstanceState(android.os.Bundle)}
+     * and {@link #saveManagedDialogs(android.os.Bundle)}.
+     *
+     * @param outState The bundle to save the state to.
+     * @param outPersistentState The bundle to save persistent state to.
+     */
+    final void performSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
+        onSaveInstanceState(outState, outPersistentState);
+        saveManagedDialogs(outState);
+        if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState +
+                ", " + outPersistentState);
+    }
+
+    /**
      * Called to retrieve per-instance state from an activity before being killed
      * so that the state can be restored in {@link #onCreate} or
      * {@link #onRestoreInstanceState} (the {@link Bundle} populated by this method
@@ -1248,6 +1348,25 @@
     }
 
     /**
+     * This is the same as {@link #onSaveInstanceState} but is called for activities
+     * created with the attribute {@link android.R.attr#persistable}. The {@link
+     * android.os.PersistableBundle} passed in will be saved and presented in
+     * {@link #onCreate(Bundle, PersistableBundle)} the first time that this activity
+     * is restarted following the next device reboot.
+     *
+     * @param outState Bundle in which to place your saved state.
+     * @param outPersistentState State which will be saved across reboots.
+     *
+     * @see #onSaveInstanceState(Bundle)
+     * @see #onCreate
+     * @see #onRestoreInstanceState(Bundle, PersistableBundle)
+     * @see #onPause
+     */
+    protected void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
+        onSaveInstanceState(outState);
+    }
+
+    /**
      * Save the state of any managed dialogs.
      *
      * @param outState place to store the saved state.
@@ -5489,13 +5608,22 @@
         return mParent != null ? mParent.getActivityToken() : mToken;
     }
 
-    final void performCreate(Bundle icicle) {
-        onCreate(icicle);
+    final void performCreateCommon() {
         mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
                 com.android.internal.R.styleable.Window_windowNoDisplay, false);
         mFragments.dispatchActivityCreated();
     }
 
+    final void performCreate(Bundle icicle) {
+        onCreate(icicle);
+        performCreateCommon();
+    }
+
+    final void performCreate(Bundle icicle, PersistableBundle persistentState) {
+        onCreate(icicle, persistentState);
+        performCreateCommon();
+    }
+
     final void performStart() {
         mFragments.noteStateNotSaved();
         mCalled = false;
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 57da21e..ec2868a 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -40,6 +40,7 @@
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
+import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StrictMode;
@@ -454,7 +455,8 @@
         case ACTIVITY_PAUSED_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
-            activityPaused(token);
+            PersistableBundle persistentState = data.readPersistableBundle();
+            activityPaused(token, persistentState);
             reply.writeNoException();
             return true;
         }
@@ -463,10 +465,9 @@
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
             Bundle map = data.readBundle();
-            Bitmap thumbnail = data.readInt() != 0
-                ? Bitmap.CREATOR.createFromParcel(data) : null;
+            PersistableBundle persistentState = data.readPersistableBundle();
             CharSequence description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data);
-            activityStopped(token, map, thumbnail, description);
+            activityStopped(token, map, persistentState, description);
             reply.writeNoException();
             return true;
         }
@@ -2583,31 +2584,27 @@
         data.recycle();
         reply.recycle();
     }
-    public void activityPaused(IBinder token) throws RemoteException
+    public void activityPaused(IBinder token, PersistableBundle persistentState) throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(token);
+        data.writePersistableBundle(persistentState);
         mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, reply, 0);
         reply.readException();
         data.recycle();
         reply.recycle();
     }
     public void activityStopped(IBinder token, Bundle state,
-            Bitmap thumbnail, CharSequence description) throws RemoteException
+            PersistableBundle persistentState, CharSequence description) throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(token);
         data.writeBundle(state);
-        if (thumbnail != null) {
-            data.writeInt(1);
-            thumbnail.writeToParcel(data, 0);
-        } else {
-            data.writeInt(0);
-        }
+        data.writePersistableBundle(persistentState);
         TextUtils.writeToParcel(description, data, 0);
         mRemote.transact(ACTIVITY_STOPPED_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
         reply.readException();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index b606088..161cb76 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -56,11 +56,11 @@
 import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.IRemoteCallback;
 import android.os.Looper;
 import android.os.Message;
 import android.os.MessageQueue;
 import android.os.ParcelFileDescriptor;
+import android.os.PersistableBundle;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -69,8 +69,6 @@
 import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
-import android.transition.Scene;
-import android.transition.TransitionManager;
 import android.provider.Settings;
 import android.util.AndroidRuntimeException;
 import android.util.ArrayMap;
@@ -268,6 +266,7 @@
         Intent intent;
         IVoiceInteractor voiceInteractor;
         Bundle state;
+        PersistableBundle persistentState;
         Activity activity;
         Window window;
         Activity parent;
@@ -317,6 +316,10 @@
             return false;
         }
 
+        public boolean isPersistable() {
+            return (activityInfo.flags & ActivityInfo.FLAG_PERSISTABLE) != 0;
+        }
+
         public String toString() {
             ComponentName componentName = intent != null ? intent.getComponent() : null;
             return "ActivityRecord{"
@@ -605,8 +608,8 @@
         // activity itself back to the activity manager. (matters more with ipc)
         public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                 ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
-                IVoiceInteractor voiceInteractor,
-                int procState, Bundle state, List<ResultInfo> pendingResults,
+                IVoiceInteractor voiceInteractor, int procState, Bundle state,
+                PersistableBundle persistentState, List<ResultInfo> pendingResults,
                 List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
                 String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler,
                 Bundle resumeArgs) {
@@ -622,6 +625,7 @@
             r.activityInfo = info;
             r.compatInfo = compatInfo;
             r.state = state;
+            r.persistentState = persistentState;
 
             r.pendingResults = pendingResults;
             r.pendingIntents = pendingNewIntents;
@@ -2205,7 +2209,11 @@
                 }
 
                 activity.mCalled = false;
-                mInstrumentation.callActivityOnCreate(activity, r.state);
+                if (r.isPersistable()) {
+                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
+                } else {
+                    mInstrumentation.callActivityOnCreate(activity, r.state);
+                }
                 if (!activity.mCalled) {
                     throw new SuperNotCalledException(
                         "Activity " + r.intent.getComponent().toShortString() +
@@ -2218,13 +2226,23 @@
                     r.stopped = false;
                 }
                 if (!r.activity.mFinished) {
-                    if (r.state != null) {
+                    if (r.isPersistable()) {
+                        if (r.state != null || r.persistentState != null) {
+                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
+                                    r.persistentState);
+                        }
+                    } else if (r.state != null) {
                         mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                     }
                 }
                 if (!r.activity.mFinished) {
                     activity.mCalled = false;
-                    mInstrumentation.callActivityOnPostCreate(activity, r.state);
+                    if (r.isPersistable()) {
+                        mInstrumentation.callActivityOnPostCreate(activity, r.state,
+                                r.persistentState);
+                    } else {
+                        mInstrumentation.callActivityOnPostCreate(activity, r.state);
+                    }
                     if (!activity.mCalled) {
                         throw new SuperNotCalledException(
                             "Activity " + r.intent.getComponent().toShortString() +
@@ -2842,6 +2860,7 @@
                 r.paused = false;
                 r.stopped = false;
                 r.state = null;
+                r.persistentState = null;
             } catch (Exception e) {
                 if (!mInstrumentation.onException(r.activity, e)) {
                     throw new RuntimeException(
@@ -3069,7 +3088,7 @@
 
             // Tell the activity manager we have paused.
             try {
-                ActivityManagerNative.getDefault().activityPaused(token);
+                ActivityManagerNative.getDefault().activityPaused(token, r.persistentState);
             } catch (RemoteException ex) {
             }
         }
@@ -3099,17 +3118,13 @@
                     + r.intent.getComponent().toShortString());
             Slog.e(TAG, e.getMessage(), e);
         }
-        Bundle state = null;
         if (finished) {
             r.activity.mFinished = true;
         }
         try {
             // Next have the activity save its current state and managed dialogs...
             if (!r.activity.mFinished && saveState) {
-                state = new Bundle();
-                state.setAllowFds(false);
-                mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
-                r.state = state;
+                callCallActivityOnSaveInstanceState(r);
             }
             // Now we are idle.
             r.activity.mCalled = false;
@@ -3145,7 +3160,7 @@
             listeners.get(i).onPaused(r.activity);
         }
 
-        return state;
+        return !r.activity.mFinished && saveState ? r.state : null;
     }
 
     final void performStopActivity(IBinder token, boolean saveState) {
@@ -3156,7 +3171,7 @@
     private static class StopInfo implements Runnable {
         ActivityClientRecord activity;
         Bundle state;
-        Bitmap thumbnail;
+        PersistableBundle persistentState;
         CharSequence description;
 
         @Override public void run() {
@@ -3164,7 +3179,7 @@
             try {
                 if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Reporting activity stopped: " + activity);
                 ActivityManagerNative.getDefault().activityStopped(
-                    activity.token, state, thumbnail, description);
+                    activity.token, state, persistentState, description);
             } catch (RemoteException ex) {
             }
         }
@@ -3203,7 +3218,6 @@
     private void performStopActivityInner(ActivityClientRecord r,
             StopInfo info, boolean keepShown, boolean saveState) {
         if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
-        Bundle state = null;
         if (r != null) {
             if (!keepShown && r.stopped) {
                 if (r.activity.mFinished) {
@@ -3223,7 +3237,6 @@
                     // First create a thumbnail for the activity...
                     // For now, don't create the thumbnail here; we are
                     // doing that by doing a screen snapshot.
-                    info.thumbnail = null; //createThumbnailBitmap(r);
                     info.description = r.activity.onCreateDescription();
                 } catch (Exception e) {
                     if (!mInstrumentation.onException(r.activity, e)) {
@@ -3238,12 +3251,7 @@
             // Next have the activity save its current state and managed dialogs...
             if (!r.activity.mFinished && saveState) {
                 if (r.state == null) {
-                    state = new Bundle();
-                    state.setAllowFds(false);
-                    mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
-                    r.state = state;
-                } else {
-                    state = r.state;
+                    callCallActivityOnSaveInstanceState(r);
                 }
             }
 
@@ -3319,6 +3327,7 @@
         // manager to proceed and allow us to go fully into the background.
         info.activity = r;
         info.state = r.state;
+        info.persistentState = r.persistentState;
         mH.post(info);
     }
 
@@ -3775,9 +3784,7 @@
             performPauseActivity(r.token, false, r.isPreHoneycomb());
         }
         if (r.state == null && !r.stopped && !r.isPreHoneycomb()) {
-            r.state = new Bundle();
-            r.state.setAllowFds(false);
-            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
+            callCallActivityOnSaveInstanceState(r);
         }
 
         handleDestroyActivity(r.token, false, configChanges, true);
@@ -3807,6 +3814,18 @@
         handleLaunchActivity(r, currentIntent);
     }
 
+    private void callCallActivityOnSaveInstanceState(ActivityClientRecord r) {
+        r.state = new Bundle();
+        r.state.setAllowFds(false);
+        if (r.isPersistable()) {
+            r.persistentState = new PersistableBundle();
+            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state,
+                    r.persistentState);
+        } else {
+            mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
+        }
+    }
+
     ArrayList<ComponentCallbacks2> collectComponentCallbacks(
             boolean allActivities, Configuration newConfig) {
         ArrayList<ComponentCallbacks2> callbacks
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 7f2fb59..e7902a9 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -29,6 +29,7 @@
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.Parcelable;
+import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.IBinder;
 import android.os.Parcel;
@@ -141,6 +142,7 @@
                     data.readStrongBinder());
             int procState = data.readInt();
             Bundle state = data.readBundle();
+            PersistableBundle persistentState = data.readPersistableBundle();
             List<ResultInfo> ri = data.createTypedArrayList(ResultInfo.CREATOR);
             List<Intent> pi = data.createTypedArrayList(Intent.CREATOR);
             boolean notResumed = data.readInt() != 0;
@@ -151,9 +153,9 @@
             boolean autoStopProfiler = data.readInt() != 0;
             Bundle resumeArgs = data.readBundle();
             scheduleLaunchActivity(intent, b, ident, info, curConfig, compatInfo,
-                    voiceInteractor, procState, state,
-                    ri, pi, notResumed, isForward, profileName, profileFd, autoStopProfiler,
-                    resumeArgs);
+                    voiceInteractor, procState, state, persistentState,
+                    ri, pi, notResumed, isForward, profileName, profileFd,
+                    autoStopProfiler, resumeArgs);
             return true;
         }
         
@@ -731,8 +733,8 @@
 
     public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
             ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
-            IVoiceInteractor voiceInteractor,
-            int procState, Bundle state, List<ResultInfo> pendingResults,
+            IVoiceInteractor voiceInteractor, int procState, Bundle state,
+            PersistableBundle persistentState, List<ResultInfo> pendingResults,
             List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
             String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler,
             Bundle resumeArgs)
@@ -748,6 +750,7 @@
         data.writeStrongBinder(voiceInteractor != null ? voiceInteractor.asBinder() : null);
         data.writeInt(procState);
         data.writeBundle(state);
+        data.writePersistableBundle(persistentState);
         data.writeTypedList(pendingResults);
         data.writeTypedList(pendingNewIntents);
         data.writeInt(notResumed ? 1 : 0);
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 2e9cdf3b7..074b427 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -45,6 +45,7 @@
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
+import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.StrictMode;
 import android.service.voice.IVoiceInteractionSession;
@@ -104,9 +105,9 @@
     public void activityResumed(IBinder token) throws RemoteException;
     public void activityIdle(IBinder token, Configuration config,
             boolean stopProfiling) throws RemoteException;
-    public void activityPaused(IBinder token) throws RemoteException;
+    public void activityPaused(IBinder token, PersistableBundle persistentState) throws RemoteException;
     public void activityStopped(IBinder token, Bundle state,
-            Bitmap thumbnail, CharSequence description) throws RemoteException;
+            PersistableBundle persistentState, CharSequence description) throws RemoteException;
     public void activitySlept(IBinder token) throws RemoteException;
     public void activityDestroyed(IBinder token) throws RemoteException;
     public String getCallingPackage(IBinder token) throws RemoteException;
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index fefba8a..a832034 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -28,6 +28,7 @@
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.ParcelFileDescriptor;
+import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.IBinder;
 import android.os.IInterface;
@@ -58,8 +59,8 @@
     void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
             ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
             IVoiceInteractor voiceInteractor, int procState, Bundle state,
-            List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, boolean notResumed,
-            boolean isForward,
+            PersistableBundle persistentState, List<ResultInfo> pendingResults,
+            List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
             String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler,
             Bundle resumeArgs)
             throws RemoteException;
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index e58ccb8..bb3e002 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -30,6 +30,7 @@
 import android.os.Looper;
 import android.os.MessageQueue;
 import android.os.PerformanceCollector;
+import android.os.PersistableBundle;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -1061,15 +1062,7 @@
         return (Activity)cl.loadClass(className).newInstance();
     }
 
-    /**
-     * Perform calling of an activity's {@link Activity#onCreate}
-     * method.  The default implementation simply calls through to that method.
-     * 
-     * @param activity The activity being created.
-     * @param icicle The previously frozen state (or null) to pass through to
-     *               onCreate().
-     */
-    public void callActivityOnCreate(Activity activity, Bundle icicle) {
+    private void prePerformCreate(Activity activity) {
         if (mWaitingActivities != null) {
             synchronized (mSync) {
                 final int N = mWaitingActivities.size();
@@ -1083,9 +1076,9 @@
                 }
             }
         }
-        
-        activity.performCreate(icicle);
-        
+    }
+
+    private void postPerformCreate(Activity activity) {
         if (mActivityMonitors != null) {
             synchronized (mSync) {
                 final int N = mActivityMonitors.size();
@@ -1096,6 +1089,33 @@
             }
         }
     }
+
+    /**
+     * Perform calling of an activity's {@link Activity#onCreate}
+     * method.  The default implementation simply calls through to that method.
+     *
+     * @param activity The activity being created.
+     * @param icicle The previously frozen state (or null) to pass through to onCreate().
+     */
+    public void callActivityOnCreate(Activity activity, Bundle icicle) {
+        prePerformCreate(activity);
+        activity.performCreate(icicle);
+        postPerformCreate(activity);
+    }
+
+    /**
+     * Perform calling of an activity's {@link Activity#onCreate}
+     * method.  The default implementation simply calls through to that method.
+     *  @param activity The activity being created.
+     * @param icicle The previously frozen state (or null) to pass through to
+     * @param persistentState The previously persisted state (or null)
+     */
+    public void callActivityOnCreate(Activity activity, Bundle icicle,
+            PersistableBundle persistentState) {
+        prePerformCreate(activity);
+        activity.performCreate(icicle, persistentState);
+        postPerformCreate(activity);
+    }
     
     public void callActivityOnDestroy(Activity activity) {
       // TODO: the following block causes intermittent hangs when using startActivity
@@ -1130,7 +1150,7 @@
     /**
      * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
      * method.  The default implementation simply calls through to that method.
-     * 
+     *
      * @param activity The activity being restored.
      * @param savedInstanceState The previously saved state being restored.
      */
@@ -1139,9 +1159,22 @@
     }
 
     /**
+     * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
+     * method.  The default implementation simply calls through to that method.
+     *
+     * @param activity The activity being restored.
+     * @param savedInstanceState The previously saved state being restored.
+     * @param persistentState The previously persisted state (or null)
+     */
+    public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState,
+            PersistableBundle persistentState) {
+        activity.performRestoreInstanceState(savedInstanceState, persistentState);
+    }
+
+    /**
      * Perform calling of an activity's {@link Activity#onPostCreate} method.
      * The default implementation simply calls through to that method.
-     * 
+     *
      * @param activity The activity being created.
      * @param icicle The previously frozen state (or null) to pass through to
      *               onPostCreate().
@@ -1151,6 +1184,19 @@
     }
 
     /**
+     * Perform calling of an activity's {@link Activity#onPostCreate} method.
+     * The default implementation simply calls through to that method.
+     *
+     * @param activity The activity being created.
+     * @param icicle The previously frozen state (or null) to pass through to
+     *               onPostCreate().
+     */
+    public void callActivityOnPostCreate(Activity activity, Bundle icicle,
+            PersistableBundle persistentState) {
+        activity.onPostCreate(icicle, persistentState);
+    }
+
+    /**
      * Perform calling of an activity's {@link Activity#onNewIntent}
      * method.  The default implementation simply calls through to that method.
      * 
@@ -1215,7 +1261,7 @@
     /**
      * Perform calling of an activity's {@link Activity#onSaveInstanceState}
      * method.  The default implementation simply calls through to that method.
-     * 
+     *
      * @param activity The activity being saved.
      * @param outState The bundle to pass to the call.
      */
@@ -1224,6 +1270,18 @@
     }
 
     /**
+     * Perform calling of an activity's {@link Activity#onSaveInstanceState}
+     * method.  The default implementation simply calls through to that method.
+     *  @param activity The activity being saved.
+     * @param outState The bundle to pass to the call.
+     * @param outPersistentState The persistent bundle to pass to the call.
+     */
+    public void callActivityOnSaveInstanceState(Activity activity, Bundle outState,
+            PersistableBundle outPersistentState) {
+        activity.performSaveInstanceState(outState, outPersistentState);
+    }
+
+    /**
      * Perform calling of an activity's {@link Activity#onPause} method.  The
      * default implementation simply calls through to that method.
      * 
@@ -1428,7 +1486,7 @@
     }
 
     /**
-     * Like {@link #execStartActivity},
+     * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
      * but accepts an array of activities to be started.  Note that active
      * {@link ActivityMonitor} objects only match against the first activity in
      * the array.
@@ -1442,7 +1500,7 @@
     }
 
     /**
-     * Like {@link #execStartActivity},
+     * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
      * but accepts an array of activities to be started.  Note that active
      * {@link ActivityMonitor} objects only match against the first activity in
      * the array.
@@ -1545,7 +1603,8 @@
     }
 
     /**
-     * Like {@link #execStartActivity}, but for starting as a particular user.
+     * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
+     * but for starting as a particular user.
      *
      * @param who The Context from which the activity is being started.
      * @param contextThread The main thread of the Context from which the activity
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index aab6ed8..db91742a 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -44,8 +44,8 @@
      * you to disable / reenable the keyguard.
      */
     public class KeyguardLock {
-        private IBinder mToken = new Binder();
-        private String mTag;
+        private final IBinder mToken = new Binder();
+        private final String mTag;
 
         KeyguardLock(String tag) {
             mTag = tag;
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index f161f3a..0ca9161 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -458,7 +458,19 @@
      * brightness</p>
      * <p>For example, if EV step is 0.333, '6' will mean an
      * exposure compensation of +2 EV; -3 will mean an exposure
-     * compensation of -1</p>
+     * compensation of -1 EV. Note that this control will only be effective
+     * if {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} <code>!=</code> OFF. This control will take effect even when
+     * {@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock} <code>== true</code>.</p>
+     * <p>In the event of exposure compensation value being changed, camera device
+     * may take several frames to reach the newly requested exposure target.
+     * During that time, {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} field will be in the SEARCHING
+     * state. Once the new exposure target is reached, {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} will
+     * change from SEARCHING to either CONVERGED, LOCKED (if AE lock is enabled), or
+     * FLASH_REQUIRED (if the scene is too dark for still capture).</p>
+     *
+     * @see CaptureRequest#CONTROL_AE_LOCK
+     * @see CaptureRequest#CONTROL_AE_MODE
+     * @see CaptureResult#CONTROL_AE_STATE
      */
     public static final Key<Integer> CONTROL_AE_EXPOSURE_COMPENSATION =
             new Key<Integer>("android.control.aeExposureCompensation", int.class);
@@ -469,6 +481,8 @@
      * <p>Note that even when AE is locked, the flash may be
      * fired if the {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is ON_AUTO_FLASH / ON_ALWAYS_FLASH /
      * ON_AUTO_FLASH_REDEYE.</p>
+     * <p>When {@link CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION android.control.aeExposureCompensation} is changed, even if the AE lock
+     * is ON, the camera device will still adjust its exposure value.</p>
      * <p>If AE precapture is triggered (see {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger})
      * when AE is already locked, the camera device will not change the exposure time
      * ({@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}) and sensitivity ({@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity})
@@ -477,6 +491,7 @@
      * {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is ON_ALWAYS_FLASH, the scene may become overexposed.</p>
      * <p>See {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} for AE lock related state transition details.</p>
      *
+     * @see CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION
      * @see CaptureRequest#CONTROL_AE_MODE
      * @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
      * @see CaptureResult#CONTROL_AE_STATE
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 51ea447..42a3de8 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -275,7 +275,19 @@
      * brightness</p>
      * <p>For example, if EV step is 0.333, '6' will mean an
      * exposure compensation of +2 EV; -3 will mean an exposure
-     * compensation of -1</p>
+     * compensation of -1 EV. Note that this control will only be effective
+     * if {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} <code>!=</code> OFF. This control will take effect even when
+     * {@link CaptureRequest#CONTROL_AE_LOCK android.control.aeLock} <code>== true</code>.</p>
+     * <p>In the event of exposure compensation value being changed, camera device
+     * may take several frames to reach the newly requested exposure target.
+     * During that time, {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} field will be in the SEARCHING
+     * state. Once the new exposure target is reached, {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} will
+     * change from SEARCHING to either CONVERGED, LOCKED (if AE lock is enabled), or
+     * FLASH_REQUIRED (if the scene is too dark for still capture).</p>
+     *
+     * @see CaptureRequest#CONTROL_AE_LOCK
+     * @see CaptureRequest#CONTROL_AE_MODE
+     * @see CaptureResult#CONTROL_AE_STATE
      */
     public static final Key<Integer> CONTROL_AE_EXPOSURE_COMPENSATION =
             new Key<Integer>("android.control.aeExposureCompensation", int.class);
@@ -286,6 +298,8 @@
      * <p>Note that even when AE is locked, the flash may be
      * fired if the {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is ON_AUTO_FLASH / ON_ALWAYS_FLASH /
      * ON_AUTO_FLASH_REDEYE.</p>
+     * <p>When {@link CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION android.control.aeExposureCompensation} is changed, even if the AE lock
+     * is ON, the camera device will still adjust its exposure value.</p>
      * <p>If AE precapture is triggered (see {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger})
      * when AE is already locked, the camera device will not change the exposure time
      * ({@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}) and sensitivity ({@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity})
@@ -294,6 +308,7 @@
      * {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is ON_ALWAYS_FLASH, the scene may become overexposed.</p>
      * <p>See {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} for AE lock related state transition details.</p>
      *
+     * @see CaptureRequest#CONTROL_AE_EXPOSURE_COMPENSATION
      * @see CaptureRequest#CONTROL_AE_MODE
      * @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
      * @see CaptureResult#CONTROL_AE_STATE
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index cec90cd..e58c54d 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -156,6 +156,9 @@
         // If true, enables automatic brightness control.
         public boolean useAutoBrightness;
 
+        //If true, scales the brightness to half of desired.
+        public boolean lowPowerMode;
+
         // If true, prevents the screen from completely turning on if it is currently off.
         // The display does not enter a "ready" state if this flag is true and screen on is
         // blocked.  The window manager policy blocks screen on while it prepares the keyguard to
@@ -203,6 +206,7 @@
             screenAutoBrightnessAdjustment = other.screenAutoBrightnessAdjustment;
             useAutoBrightness = other.useAutoBrightness;
             blockScreenOn = other.blockScreenOn;
+            lowPowerMode = other.lowPowerMode;
         }
 
         @Override
@@ -218,7 +222,8 @@
                     && screenBrightness == other.screenBrightness
                     && screenAutoBrightnessAdjustment == other.screenAutoBrightnessAdjustment
                     && useAutoBrightness == other.useAutoBrightness
-                    && blockScreenOn == other.blockScreenOn;
+                    && blockScreenOn == other.blockScreenOn
+                    && lowPowerMode == other.lowPowerMode;
         }
 
         @Override
@@ -233,7 +238,8 @@
                     + ", screenBrightness=" + screenBrightness
                     + ", screenAutoBrightnessAdjustment=" + screenAutoBrightnessAdjustment
                     + ", useAutoBrightness=" + useAutoBrightness
-                    + ", blockScreenOn=" + blockScreenOn;
+                    + ", blockScreenOn=" + blockScreenOn
+                    + ", lowPowerMode=" + lowPowerMode;
         }
     }
 
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 8b7467f..4857533 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -21,6 +21,7 @@
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Formatter;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -30,6 +31,8 @@
 import android.text.format.DateFormat;
 import android.util.Printer;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
 import android.util.TimeUtils;
 import com.android.internal.os.BatterySipper;
 import com.android.internal.os.BatteryStatsHelper;
@@ -537,6 +540,7 @@
         public static final byte CMD_START = 4;
         public static final byte CMD_CURRENT_TIME = 5;
         public static final byte CMD_OVERFLOW = 6;
+        public static final byte CMD_RESET = 7;
 
         public byte cmd = CMD_NULL;
         
@@ -620,6 +624,8 @@
         public static final int EVENT_SYNC = 0x0004;
         // Number of event types.
         public static final int EVENT_COUNT = 0x0005;
+        // Mask to extract out only the type part of the event.
+        public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH);
 
         public static final int EVENT_PROC_START = EVENT_PROC | EVENT_FLAG_START;
         public static final int EVENT_PROC_FINISH = EVENT_PROC | EVENT_FLAG_FINISH;
@@ -684,7 +690,7 @@
                 dest.writeInt(eventCode);
                 eventTag.writeToParcel(dest, flags);
             }
-            if (cmd == CMD_CURRENT_TIME) {
+            if (cmd == CMD_CURRENT_TIME || cmd == CMD_RESET) {
                 dest.writeLong(currentTime);
             }
         }
@@ -722,7 +728,7 @@
                 eventCode = EVENT_NONE;
                 eventTag = null;
             }
-            if (cmd == CMD_CURRENT_TIME) {
+            if (cmd == CMD_CURRENT_TIME || cmd == CMD_RESET) {
                 currentTime = src.readLong();
             } else {
                 currentTime = 0;
@@ -833,7 +839,59 @@
             return true;
         }
     }
-    
+
+    public final static class HistoryEventTracker {
+        private final HashMap<String, SparseIntArray>[] mActiveEvents
+                = (HashMap<String, SparseIntArray>[]) new HashMap[HistoryItem.EVENT_COUNT];
+
+        public boolean updateState(int code, String name, int uid, int poolIdx) {
+            if ((code&HistoryItem.EVENT_FLAG_START) != 0) {
+                int idx = code&HistoryItem.EVENT_TYPE_MASK;
+                HashMap<String, SparseIntArray> active = mActiveEvents[idx];
+                if (active == null) {
+                    active = new HashMap<String, SparseIntArray>();
+                    mActiveEvents[idx] = active;
+                }
+                SparseIntArray uids = active.get(name);
+                if (uids == null) {
+                    uids = new SparseIntArray();
+                    active.put(name, uids);
+                }
+                if (uids.indexOfKey(uid) >= 0) {
+                    // Already set, nothing to do!
+                    return false;
+                }
+                uids.put(uid, poolIdx);
+            } else if ((code&HistoryItem.EVENT_FLAG_FINISH) != 0) {
+                int idx = code&HistoryItem.EVENT_TYPE_MASK;
+                HashMap<String, SparseIntArray> active = mActiveEvents[idx];
+                if (active == null) {
+                    // not currently active, nothing to do.
+                    return false;
+                }
+                SparseIntArray uids = active.get(name);
+                if (uids == null) {
+                    // not currently active, nothing to do.
+                    return false;
+                }
+                idx = uids.indexOfKey(uid);
+                if (idx < 0) {
+                    // not currently active, nothing to do.
+                    return false;
+                }
+                uids.removeAt(idx);
+                if (uids.size() <= 0) {
+                    active.remove(name);
+                }
+            }
+            return true;
+        }
+
+        public HashMap<String, SparseIntArray> getStateForEvent(int code) {
+            return mActiveEvents[code];
+        }
+    }
+
     public static final class BitDescription {
         public final int mask;
         public final int shift;
@@ -861,7 +919,7 @@
             this.shortValues = shortValues;
         }
     }
-    
+
     public abstract int getHistoryTotalSize();
 
     public abstract int getHistoryUsedSize();
@@ -2958,10 +3016,14 @@
                     pw.print(":");
                 }
                 pw.println("START");
-            } else if (rec.cmd == HistoryItem.CMD_CURRENT_TIME) {
+            } else if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
+                    || rec.cmd == HistoryItem.CMD_RESET) {
                 if (checkin) {
                     pw.print(":");
                 }
+                if (rec.cmd == HistoryItem.CMD_RESET) {
+                    pw.print("RESET:");
+                }
                 pw.print("TIME:");
                 if (checkin) {
                     pw.println(rec.currentTime);
@@ -3187,6 +3249,86 @@
     public static final int DUMP_INCLUDE_HISTORY = 1<<3;
     public static final int DUMP_VERBOSE = 1<<4;
 
+    private void dumpHistoryLocked(PrintWriter pw, int flags, long histStart, boolean checkin) {
+        final HistoryPrinter hprinter = new HistoryPrinter();
+        final HistoryItem rec = new HistoryItem();
+        long lastTime = -1;
+        long baseTime = -1;
+        boolean printed = false;
+        HistoryEventTracker tracker = null;
+        while (getNextHistoryLocked(rec)) {
+            lastTime = rec.time;
+            if (baseTime < 0) {
+                baseTime = lastTime;
+            }
+            if (rec.time >= histStart) {
+                if (histStart >= 0 && !printed) {
+                    if (rec.cmd == HistoryItem.CMD_CURRENT_TIME
+                            || rec.cmd == HistoryItem.CMD_RESET) {
+                        printed = true;
+                    } else if (rec.currentTime != 0) {
+                        printed = true;
+                        byte cmd = rec.cmd;
+                        rec.cmd = HistoryItem.CMD_CURRENT_TIME;
+                        if (checkin) {
+                            pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
+                            pw.print(HISTORY_DATA); pw.print(',');
+                        }
+                        hprinter.printNextItem(pw, rec, baseTime, checkin,
+                                (flags&DUMP_VERBOSE) != 0);
+                        rec.cmd = cmd;
+                    }
+                    if (tracker != null) {
+                        int oldCode = rec.eventCode;
+                        HistoryTag oldTag = rec.eventTag;
+                        rec.eventTag = new HistoryTag();
+                        for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
+                            HashMap<String, SparseIntArray> active
+                                    = tracker.getStateForEvent(i);
+                            if (active == null) {
+                                continue;
+                            }
+                            for (HashMap.Entry<String, SparseIntArray> ent
+                                    : active.entrySet()) {
+                                SparseIntArray uids = ent.getValue();
+                                for (int j=0; j<uids.size(); j++) {
+                                    rec.eventCode = i;
+                                    rec.eventTag.string = ent.getKey();
+                                    rec.eventTag.uid = uids.keyAt(j);
+                                    rec.eventTag.poolIdx = uids.valueAt(j);
+                                    if (checkin) {
+                                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
+                                        pw.print(HISTORY_DATA); pw.print(',');
+                                    }
+                                    hprinter.printNextItem(pw, rec, baseTime, checkin,
+                                            (flags&DUMP_VERBOSE) != 0);
+                                }
+                            }
+                        }
+                        rec.eventCode = oldCode;
+                        rec.eventTag = oldTag;
+                        tracker = null;
+                    }
+                }
+                if (checkin) {
+                    pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
+                    pw.print(HISTORY_DATA); pw.print(',');
+                }
+                hprinter.printNextItem(pw, rec, baseTime, checkin,
+                        (flags&DUMP_VERBOSE) != 0);
+            } else if (rec.eventCode != HistoryItem.EVENT_NONE) {
+                if (tracker == null) {
+                    tracker = new HistoryEventTracker();
+                }
+                tracker.updateState(rec.eventCode, rec.eventTag.string,
+                        rec.eventTag.uid, rec.eventTag.poolIdx);
+            }
+        }
+        if (histStart >= 0) {
+            pw.print(checkin ? "NEXT: " : "  NEXT: "); pw.println(lastTime+1);
+        }
+    }
+
     /**
      * Dumps a human-readable summary of the battery statistics to the given PrintWriter.
      *
@@ -3200,9 +3342,6 @@
                 (flags&(DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) != 0;
 
         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()) {
@@ -3218,35 +3357,7 @@
                     pw.print(" strings using ");
                     printSizeValue(pw, getHistoryStringPoolBytes());
                     pw.println("):");
-                    HistoryPrinter hprinter = new HistoryPrinter();
-                    long lastTime = -1;
-                    long baseTime = -1;
-                    boolean printed = false;
-                    while (getNextHistoryLocked(rec)) {
-                        lastTime = rec.time;
-                        if (baseTime < 0) {
-                            baseTime = lastTime;
-                        }
-                        if (rec.time >= histStart) {
-                            if (histStart >= 0 && !printed) {
-                                if (rec.cmd == HistoryItem.CMD_CURRENT_TIME) {
-                                    printed = true;
-                                } else if (rec.currentTime != 0) {
-                                    printed = true;
-                                    byte cmd = rec.cmd;
-                                    rec.cmd = HistoryItem.CMD_CURRENT_TIME;
-                                    hprinter.printNextItem(pw, rec, baseTime, false,
-                                            (flags&DUMP_VERBOSE) != 0);
-                                    rec.cmd = cmd;
-                                }
-                            }
-                            hprinter.printNextItem(pw, rec, baseTime, false,
-                                    (flags&DUMP_VERBOSE) != 0);
-                        }
-                    }
-                    if (histStart >= 0) {
-                        pw.print("  NEXT: "); pw.println(lastTime+1);
-                    }
+                    dumpHistoryLocked(pw, flags, histStart, false);
                     pw.println();
                 } finally {
                     finishIteratingHistoryLocked();
@@ -3255,6 +3366,7 @@
 
             if (startIteratingOldHistoryLocked()) {
                 try {
+                    final HistoryItem rec = new HistoryItem();
                     pw.println("Old battery History:");
                     HistoryPrinter hprinter = new HistoryPrinter();
                     long baseTime = -1;
@@ -3348,7 +3460,6 @@
                 (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 {
                     for (int i=0; i<getHistoryStringPoolSize(); i++) {
@@ -3365,37 +3476,7 @@
                         pw.print("\"");
                         pw.println();
                     }
-                    HistoryPrinter hprinter = new HistoryPrinter();
-                    long lastTime = -1;
-                    long baseTime = -1;
-                    boolean printed = false;
-                    while (getNextHistoryLocked(rec)) {
-                        lastTime = rec.time;
-                        if (baseTime < 0) {
-                            baseTime = lastTime;
-                        }
-                        if (rec.time >= histStart) {
-                            if (histStart >= 0 && !printed) {
-                                if (rec.cmd == HistoryItem.CMD_CURRENT_TIME) {
-                                    printed = true;
-                                } else if (rec.currentTime != 0) {
-                                    printed = true;
-                                    byte cmd = rec.cmd;
-                                    rec.cmd = HistoryItem.CMD_CURRENT_TIME;
-                                    pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
-                                    pw.print(HISTORY_DATA); pw.print(',');
-                                    hprinter.printNextItem(pw, rec, baseTime, true, false);
-                                    rec.cmd = cmd;
-                                }
-                            }
-                            pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
-                            pw.print(HISTORY_DATA); pw.print(',');
-                            hprinter.printNextItem(pw, rec, baseTime, true, false);
-                        }
-                    }
-                    if (histStart >= 0) {
-                        pw.print("NEXT: "); pw.println(lastTime+1);
-                    }
+                    dumpHistoryLocked(pw, flags, histStart, true);
                 } finally {
                     finishIteratingHistoryLocked();
                 }
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 25bcd44..ac12357 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -50,28 +50,6 @@
     private static WebViewFactoryProvider sProviderInstance;
     private static final Object sProviderLock = new Object();
 
-    public static boolean isExperimentalWebViewAvailable() {
-        // TODO: Remove callers of this method then remove it.
-        return false;  // Hide the toggle in Developer Settings.
-    }
-
-    /** @hide */
-    public static void setUseExperimentalWebView(boolean enable) {
-        // TODO: Remove callers of this method then remove it.
-    }
-
-    /** @hide */
-    public static boolean useExperimentalWebView() {
-        // TODO: Remove callers of this method then remove it.
-        return true;
-    }
-
-    /** @hide */
-    public static boolean isUseExperimentalWebViewSet() {
-        // TODO: Remove callers of this method then remove it.
-        return false;  // User has not modifed Developer Settings
-    }
-
     static WebViewFactoryProvider getProvider() {
         synchronized (sProviderLock) {
             // For now the main purpose of this function (and the factory abstraction) is to keep
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 4726da7..b568121 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -26,6 +26,7 @@
 import android.content.res.TypedArray;
 import android.database.Cursor;
 import android.graphics.drawable.Drawable;
+import android.os.Build;
 import android.os.Handler;
 import android.os.Message;
 import android.text.TextUtils;
@@ -38,6 +39,7 @@
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.view.Window;
+import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
@@ -240,6 +242,7 @@
         mWindow.requestFeature(Window.FEATURE_NO_TITLE);
         mWindow.setContentView(mAlertDialogLayout);
         setupView();
+        setupDecor();
     }
     
     public void setTitle(CharSequence title) {
@@ -415,7 +418,28 @@
     public boolean onKeyUp(int keyCode, KeyEvent event) {
         return mScrollView != null && mScrollView.executeKeyEvent(event);
     }
-    
+
+    private void setupDecor() {
+        final View decor = mWindow.getDecorView();
+        final View parent = mWindow.findViewById(R.id.parentPanel);
+        if (parent != null && decor != null) {
+            decor.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
+                @Override
+                public WindowInsets onApplyWindowInsets(View view, WindowInsets insets) {
+                    if (insets.isRound()) {
+                        // TODO: Get the padding as a function of the window size.
+                        int roundOffset = mContext.getResources().getDimensionPixelOffset(
+                                R.dimen.alert_dialog_round_padding);
+                        parent.setPadding(roundOffset, roundOffset, roundOffset, roundOffset);
+                    }
+                    return insets.consumeSystemWindowInsets();
+                }
+            });
+            decor.setFitsSystemWindows(true);
+            decor.requestApplyInsets();
+        }
+    }
+
     private void setupView() {
         LinearLayout contentPanel = (LinearLayout) mWindow.findViewById(R.id.contentPanel);
         setupContent(contentPanel);
@@ -636,14 +660,31 @@
 
     private void setBackground(TypedArray a, View topPanel, View contentPanel, View customPanel,
             View buttonPanel, boolean hasTitle, boolean hasCustomView, boolean hasButtons) {
-        final int topBright = a.getResourceId(
-                R.styleable.AlertDialog_topBright, R.drawable.popup_top_bright);
-        final int topDark = a.getResourceId(
-                R.styleable.AlertDialog_topDark, R.drawable.popup_top_dark);
-        final int centerBright = a.getResourceId(
-                R.styleable.AlertDialog_centerBright, R.drawable.popup_center_bright);
-        final int centerDark = a.getResourceId(
-                R.styleable.AlertDialog_centerDark, R.drawable.popup_center_dark);
+        int fullDark = 0;
+        int topDark = 0;
+        int centerDark = 0;
+        int bottomDark = 0;
+        int fullBright = 0;
+        int topBright = 0;
+        int centerBright = 0;
+        int bottomBright = 0;
+        int bottomMedium = 0;
+        if (mContext.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.KITKAT) {
+            fullDark = R.drawable.popup_full_dark;
+            topDark = R.drawable.popup_top_dark;
+            centerDark = R.drawable.popup_center_dark;
+            bottomDark = R.drawable.popup_bottom_dark;
+            fullBright = R.drawable.popup_full_bright;
+            topBright = R.drawable.popup_top_bright;
+            centerBright = R.drawable.popup_center_bright;
+            bottomBright = R.drawable.popup_bottom_bright;
+            bottomMedium = R.drawable.popup_bottom_medium;
+        }
+        topBright = a.getResourceId(R.styleable.AlertDialog_topBright, topBright);
+        topDark = a.getResourceId(R.styleable.AlertDialog_topDark, topDark);
+        centerBright = a.getResourceId(R.styleable.AlertDialog_centerBright, centerBright);
+        centerDark = a.getResourceId(R.styleable.AlertDialog_centerDark, centerDark);
+
 
         /* We now set the background of all of the sections of the alert.
          * First collect together each section that is being displayed along
@@ -707,22 +748,17 @@
 
         if (lastView != null) {
             if (setView) {
-                final int bottomBright = a.getResourceId(
-                        R.styleable.AlertDialog_bottomBright, R.drawable.popup_bottom_bright);
-                final int bottomMedium = a.getResourceId(
-                        R.styleable.AlertDialog_bottomMedium, R.drawable.popup_bottom_medium);
-                final int bottomDark = a.getResourceId(
-                        R.styleable.AlertDialog_bottomDark, R.drawable.popup_bottom_dark);
+                bottomBright = a.getResourceId(R.styleable.AlertDialog_bottomBright, bottomBright);
+                bottomMedium = a.getResourceId(R.styleable.AlertDialog_bottomMedium, bottomMedium);
+                bottomDark = a.getResourceId(R.styleable.AlertDialog_bottomDark, bottomDark);
 
                 // ListViews will use the Bright background, but buttons use the
                 // Medium background.
                 lastView.setBackgroundResource(
                         lastLight ? (hasButtons ? bottomMedium : bottomBright) : bottomDark);
             } else {
-                final int fullBright = a.getResourceId(
-                        R.styleable.AlertDialog_fullBright, R.drawable.popup_full_bright);
-                final int fullDark = a.getResourceId(
-                        R.styleable.AlertDialog_fullDark, R.drawable.popup_full_dark);
+                fullBright = a.getResourceId(R.styleable.AlertDialog_fullBright, fullBright);
+                fullDark = a.getResourceId(R.styleable.AlertDialog_fullDark, fullDark);
 
                 lastView.setBackgroundResource(lastLight ? fullBright : fullDark);
             }
diff --git a/core/java/com/android/internal/app/ProcessStats.java b/core/java/com/android/internal/app/ProcessStats.java
index 882bec9..41f3337 100644
--- a/core/java/com/android/internal/app/ProcessStats.java
+++ b/core/java/com/android/internal/app/ProcessStats.java
@@ -1108,13 +1108,6 @@
                 mRuntime = runtime;
             }
         }
-        String webview = WebViewFactory.useExperimentalWebView() ? "chromeview" : "webview";
-        if (!Objects.equals(webview, mWebView)) {
-            changed = true;
-            if (update) {
-                mWebView = webview;
-            }
-        }
         return changed;
     }
 
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 1aff190..7bd5b12 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -188,8 +188,7 @@
 
     boolean mShuttingDown;
 
-    HashMap<String, SparseBooleanArray>[] mActiveEvents
-            = (HashMap<String, SparseBooleanArray>[]) new HashMap[HistoryItem.EVENT_COUNT];
+    final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
 
     long mHistoryBaseTime;
     boolean mHaveBatteryLevel = false;
@@ -2297,44 +2296,8 @@
 
     public void noteEventLocked(int code, String name, int uid) {
         uid = mapUid(uid);
-        if ((code&HistoryItem.EVENT_FLAG_START) != 0) {
-            int idx = code&~HistoryItem.EVENT_FLAG_START;
-            HashMap<String, SparseBooleanArray> active = mActiveEvents[idx];
-            if (active == null) {
-                active = new HashMap<String, SparseBooleanArray>();
-                mActiveEvents[idx] = active;
-            }
-            SparseBooleanArray uids = active.get(name);
-            if (uids == null) {
-                uids = new SparseBooleanArray();
-                active.put(name, uids);
-            }
-            if (uids.get(uid)) {
-                // Already set, nothing to do!
-                return;
-            }
-            uids.put(uid, true);
-        } else if ((code&HistoryItem.EVENT_FLAG_FINISH) != 0) {
-            int idx = code&~HistoryItem.EVENT_FLAG_FINISH;
-            HashMap<String, SparseBooleanArray> active = mActiveEvents[idx];
-            if (active == null) {
-                // not currently active, nothing to do.
-                return;
-            }
-            SparseBooleanArray uids = active.get(name);
-            if (uids == null) {
-                // not currently active, nothing to do.
-                return;
-            }
-            idx = uids.indexOfKey(uid);
-            if (idx < 0 || !uids.valueAt(idx)) {
-                // not currently active, nothing to do.
-                return;
-            }
-            uids.removeAt(idx);
-            if (uids.size() <= 0) {
-                active.remove(name);
-            }
+        if (!mActiveEvents.updateState(code, name, uid, 0)) {
+            return;
         }
         final long elapsedRealtime = SystemClock.elapsedRealtime();
         final long uptime = SystemClock.uptimeMillis();
@@ -2348,6 +2311,9 @@
         }
     }
 
+    private String mInitialAcquireWakeName;
+    private int mInitialAcquireWakeUid = -1;
+
     public void noteStartWakeLocked(int uid, int pid, String name, String historyName, int type,
             boolean unimportantForLogging, long elapsedRealtime, long uptime) {
         uid = mapUid(uid);
@@ -2360,8 +2326,9 @@
                 if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
                         + Integer.toHexString(mHistoryCur.states));
                 mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
-                mHistoryCur.wakelockTag.string = historyName != null ? historyName : name;
-                mHistoryCur.wakelockTag.uid = uid;
+                mHistoryCur.wakelockTag.string = mInitialAcquireWakeName
+                        = historyName != null ? historyName : name;
+                mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
                 mWakeLockImportant = !unimportantForLogging;
                 addHistoryRecordLocked(elapsedRealtime, uptime);
             } else if (!mWakeLockImportant && !unimportantForLogging) {
@@ -2369,8 +2336,9 @@
                     // We'll try to update the last tag.
                     mHistoryLastWritten.wakelockTag = null;
                     mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
-                    mHistoryCur.wakelockTag.string = historyName != null ? historyName : name;
-                    mHistoryCur.wakelockTag.uid = uid;
+                    mHistoryCur.wakelockTag.string = mInitialAcquireWakeName
+                            = historyName != null ? historyName : name;
+                    mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
                     addHistoryRecordLocked(elapsedRealtime, uptime);
                 }
                 mWakeLockImportant = true;
@@ -2395,6 +2363,14 @@
                 mHistoryCur.states &= ~HistoryItem.STATE_WAKE_LOCK_FLAG;
                 if (DEBUG_HISTORY) Slog.v(TAG, "Stop wake lock to: "
                         + Integer.toHexString(mHistoryCur.states));
+                if ((name != null && !name.equals(mInitialAcquireWakeName))
+                        || uid != mInitialAcquireWakeUid) {
+                    mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag;
+                    mHistoryCur.wakelockTag.string = name;
+                    mHistoryCur.wakelockTag.uid = uid;
+                }
+                mInitialAcquireWakeName = null;
+                mInitialAcquireWakeUid = -1;
                 addHistoryRecordLocked(elapsedRealtime, uptime);
             }
         }
@@ -5699,7 +5675,8 @@
         final long lastRealtime = out.time;
         final long lastWalltime = out.currentTime;
         readHistoryDelta(mHistoryBuffer, out);
-        if (out.cmd != HistoryItem.CMD_CURRENT_TIME && lastWalltime != 0) {
+        if (out.cmd != HistoryItem.CMD_CURRENT_TIME
+                && out.cmd != HistoryItem.CMD_RESET && lastWalltime != 0) {
             out.currentTime = lastWalltime + (out.time - lastRealtime);
         }
         return true;
@@ -5845,17 +5822,15 @@
 
     private void initActiveHistoryEventsLocked(long elapsedRealtimeMs, long uptimeMs) {
         for (int i=0; i<HistoryItem.EVENT_COUNT; i++) {
-            HashMap<String, SparseBooleanArray> active = mActiveEvents[i];
+            HashMap<String, SparseIntArray> active = mActiveEvents.getStateForEvent(i);
             if (active == null) {
                 continue;
             }
-            for (HashMap.Entry<String, SparseBooleanArray> ent : active.entrySet()) {
-                SparseBooleanArray uids = ent.getValue();
+            for (HashMap.Entry<String, SparseIntArray> ent : active.entrySet()) {
+                SparseIntArray uids = ent.getValue();
                 for (int j=0; j<uids.size(); j++) {
-                    if (uids.valueAt(j)) {
-                        addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
-                                uids.keyAt(j));
-                    }
+                    addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, i, ent.getKey(),
+                            uids.keyAt(j));
                 }
             }
         }
@@ -5971,7 +5946,8 @@
             boolean reset) {
         mRecordingHistory = true;
         mHistoryCur.currentTime = System.currentTimeMillis();
-        addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_CURRENT_TIME,
+        addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs,
+                reset ? HistoryItem.CMD_RESET : HistoryItem.CMD_CURRENT_TIME,
                 mHistoryCur);
         mHistoryCur.currentTime = 0;
         if (reset) {
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index e0fa9ba4..0328517 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -1,838 +1,838 @@
-#include "SkBitmap.h"

-#include "SkPixelRef.h"

-#include "SkImageEncoder.h"

-#include "SkColorPriv.h"

-#include "GraphicsJNI.h"

-#include "SkDither.h"

-#include "SkUnPreMultiply.h"

-#include "SkStream.h"

-

-#include <binder/Parcel.h>

-#include "android_os_Parcel.h"

-#include "android_util_Binder.h"

-#include "android_nio_utils.h"

-#include "CreateJavaOutputStreamAdaptor.h"

-

-#include <jni.h>

-

-#include <Caches.h>

-

-#if 0

-    #define TRACE_BITMAP(code)  code

-#else

-    #define TRACE_BITMAP(code)

-#endif

-

-///////////////////////////////////////////////////////////////////////////////

-// Conversions to/from SkColor, for get/setPixels, and the create method, which

-// is basically like setPixels

-

-typedef void (*FromColorProc)(void* dst, const SkColor src[], int width,

-                              int x, int y);

-

-static void FromColor_D32(void* dst, const SkColor src[], int width,

-                          int, int) {

-    SkPMColor* d = (SkPMColor*)dst;

-

-    for (int i = 0; i < width; i++) {

-        *d++ = SkPreMultiplyColor(*src++);

-    }

-}

-

-static void FromColor_D32_Raw(void* dst, const SkColor src[], int width,

-                          int, int) {

-    // SkColor's ordering may be different from SkPMColor

-    if (SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER) {

-        memcpy(dst, src, width * sizeof(SkColor));

-        return;

-    }

-

-    // order isn't same, repack each pixel manually

-    SkPMColor* d = (SkPMColor*)dst;

-    for (int i = 0; i < width; i++) {

-        SkColor c = *src++;

-        *d++ = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),

-                                   SkColorGetG(c), SkColorGetB(c));

-    }

-}

-

-static void FromColor_D565(void* dst, const SkColor src[], int width,

-                           int x, int y) {

-    uint16_t* d = (uint16_t*)dst;

-

-    DITHER_565_SCAN(y);

-    for (int stop = x + width; x < stop; x++) {

-        SkColor c = *src++;

-        *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c),

-                                DITHER_VALUE(x));

-    }

-}

-

-static void FromColor_D4444(void* dst, const SkColor src[], int width,

-                            int x, int y) {

-    SkPMColor16* d = (SkPMColor16*)dst;

-

-    DITHER_4444_SCAN(y);

-    for (int stop = x + width; x < stop; x++) {

-        SkPMColor pmc = SkPreMultiplyColor(*src++);

-        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));

-//        *d++ = SkPixel32ToPixel4444(pmc);

-    }

-}

-

-static void FromColor_D4444_Raw(void* dst, const SkColor src[], int width,

-                            int x, int y) {

-    SkPMColor16* d = (SkPMColor16*)dst;

-

-    DITHER_4444_SCAN(y);

-    for (int stop = x + width; x < stop; x++) {

-        SkColor c = *src++;

-

-        // SkPMColor is used because the ordering is ARGB32, even though the target actually premultiplied

-        SkPMColor pmc = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),

-                                            SkColorGetG(c), SkColorGetB(c));

-        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));

-//        *d++ = SkPixel32ToPixel4444(pmc);

-    }

-}

-

-// can return NULL

-static FromColorProc ChooseFromColorProc(SkBitmap::Config config, bool isPremultiplied) {

-    switch (config) {

-        case SkBitmap::kARGB_8888_Config:

-            return isPremultiplied ? FromColor_D32 : FromColor_D32_Raw;

-        case SkBitmap::kARGB_4444_Config:

-            return isPremultiplied ? FromColor_D4444 : FromColor_D4444_Raw;

-        case SkBitmap::kRGB_565_Config:

-            return FromColor_D565;

-        default:

-            break;

-    }

-    return NULL;

-}

-

-bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,

-        int x, int y, int width, int height,

-        const SkBitmap& dstBitmap, bool isPremultiplied) {

-    SkAutoLockPixels alp(dstBitmap);

-    void* dst = dstBitmap.getPixels();

-    FromColorProc proc = ChooseFromColorProc(dstBitmap.config(), isPremultiplied);

-

-    if (NULL == dst || NULL == proc) {

-        return false;

-    }

-

-    const jint* array = env->GetIntArrayElements(srcColors, NULL);

-    const SkColor* src = (const SkColor*)array + srcOffset;

-

-    // reset to to actual choice from caller

-    dst = dstBitmap.getAddr(x, y);

-    // now copy/convert each scanline

-    for (int y = 0; y < height; y++) {

-        proc(dst, src, width, x, y);

-        src += srcStride;

-        dst = (char*)dst + dstBitmap.rowBytes();

-    }

-

-    dstBitmap.notifyPixelsChanged();

-

-    env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array),

-                                 JNI_ABORT);

-    return true;

-}

-

-//////////////////// ToColor procs

-

-typedef void (*ToColorProc)(SkColor dst[], const void* src, int width,

-                            SkColorTable*);

-

-static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,

-                              SkColorTable*) {

-    SkASSERT(width > 0);

-    const SkPMColor* s = (const SkPMColor*)src;

-    do {

-        *dst++ = SkUnPreMultiply::PMColorToColor(*s++);

-    } while (--width != 0);

-}

-

-static void ToColor_S32_Raw(SkColor dst[], const void* src, int width,

-                              SkColorTable*) {

-    SkASSERT(width > 0);

-    const SkPMColor* s = (const SkPMColor*)src;

-    do {

-        SkPMColor c = *s++;

-        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),

-                                SkGetPackedG32(c), SkGetPackedB32(c));

-    } while (--width != 0);

-}

-

-static void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,

-                               SkColorTable*) {

-    SkASSERT(width > 0);

-    const SkPMColor* s = (const SkPMColor*)src;

-    do {

-        SkPMColor c = *s++;

-        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),

-                               SkGetPackedB32(c));

-    } while (--width != 0);

-}

-

-static void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,

-                                SkColorTable*) {

-    SkASSERT(width > 0);

-    const SkPMColor16* s = (const SkPMColor16*)src;

-    do {

-        *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));

-    } while (--width != 0);

-}

-

-static void ToColor_S4444_Raw(SkColor dst[], const void* src, int width,

-                                SkColorTable*) {

-    SkASSERT(width > 0);

-    const SkPMColor16* s = (const SkPMColor16*)src;

-    do {

-        SkPMColor c = SkPixel4444ToPixel32(*s++);

-        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),

-                                SkGetPackedG32(c), SkGetPackedB32(c));

-    } while (--width != 0);

-}

-

-static void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,

-                                 SkColorTable*) {

-    SkASSERT(width > 0);

-    const SkPMColor16* s = (const SkPMColor16*)src;

-    do {

-        SkPMColor c = SkPixel4444ToPixel32(*s++);

-        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),

-                               SkGetPackedB32(c));

-    } while (--width != 0);

-}

-

-static void ToColor_S565(SkColor dst[], const void* src, int width,

-                         SkColorTable*) {

-    SkASSERT(width > 0);

-    const uint16_t* s = (const uint16_t*)src;

-    do {

-        uint16_t c = *s++;

-        *dst++ =  SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),

-                                SkPacked16ToB32(c));

-    } while (--width != 0);

-}

-

-static void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,

-                              SkColorTable* ctable) {

-    SkASSERT(width > 0);

-    const uint8_t* s = (const uint8_t*)src;

-    const SkPMColor* colors = ctable->lockColors();

-    do {

-        *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]);

-    } while (--width != 0);

-    ctable->unlockColors();

-}

-

-static void ToColor_SI8_Raw(SkColor dst[], const void* src, int width,

-                              SkColorTable* ctable) {

-    SkASSERT(width > 0);

-    const uint8_t* s = (const uint8_t*)src;

-    const SkPMColor* colors = ctable->lockColors();

-    do {

-        SkPMColor c = colors[*s++];

-        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),

-                                SkGetPackedG32(c), SkGetPackedB32(c));

-    } while (--width != 0);

-    ctable->unlockColors();

-}

-

-static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,

-                               SkColorTable* ctable) {

-    SkASSERT(width > 0);

-    const uint8_t* s = (const uint8_t*)src;

-    const SkPMColor* colors = ctable->lockColors();

-    do {

-        SkPMColor c = colors[*s++];

-        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),

-                               SkGetPackedB32(c));

-    } while (--width != 0);

-    ctable->unlockColors();

-}

-

-// can return NULL

-static ToColorProc ChooseToColorProc(const SkBitmap& src, bool isPremultiplied) {

-    switch (src.config()) {

-        case SkBitmap::kARGB_8888_Config:

-            if (src.isOpaque()) return ToColor_S32_Opaque;

-            return isPremultiplied ? ToColor_S32_Alpha : ToColor_S32_Raw;

-        case SkBitmap::kARGB_4444_Config:

-            if (src.isOpaque()) return ToColor_S4444_Opaque;

-            return isPremultiplied ? ToColor_S4444_Alpha : ToColor_S4444_Raw;

-        case SkBitmap::kRGB_565_Config:

-            return ToColor_S565;

-        case SkBitmap::kIndex8_Config:

-            if (src.getColorTable() == NULL) {

-                return NULL;

-            }

-            if (src.isOpaque()) return ToColor_SI8_Opaque;

-            return isPremultiplied ? ToColor_SI8_Raw : ToColor_SI8_Alpha;

-        default:

-            break;

-    }

-    return NULL;

-}

-

-///////////////////////////////////////////////////////////////////////////////

-///////////////////////////////////////////////////////////////////////////////

-

-static int getPremulBitmapCreateFlags(bool isMutable) {

-    int flags = GraphicsJNI::kBitmapCreateFlag_Premultiplied;

-    if (isMutable) flags |= GraphicsJNI::kBitmapCreateFlag_Mutable;

-    return flags;

-}

-

-static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,

-                              jint offset, jint stride, jint width, jint height,

-                              jint configHandle, jboolean isMutable) {

-    SkBitmap::Config config = static_cast<SkBitmap::Config>(configHandle);

-    if (NULL != jColors) {

-        size_t n = env->GetArrayLength(jColors);

-        if (n < SkAbs32(stride) * (size_t)height) {

-            doThrowAIOOBE(env);

-            return NULL;

-        }

-    }

-

-    // ARGB_4444 is a deprecated format, convert automatically to 8888

-    if (config == SkBitmap::kARGB_4444_Config) {

-        config = SkBitmap::kARGB_8888_Config;

-    }

-

-    SkBitmap bitmap;

-    bitmap.setConfig(config, width, height);

-

-    jbyteArray buff = GraphicsJNI::allocateJavaPixelRef(env, &bitmap, NULL);

-    if (NULL == buff) {

-        return NULL;

-    }

-

-    if (jColors != NULL) {

-        GraphicsJNI::SetPixels(env, jColors, offset, stride,

-                0, 0, width, height, bitmap, true);

-    }

-

-    return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff,

-            getPremulBitmapCreateFlags(isMutable), NULL, NULL);

-}

-

-static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,

-                           jint dstConfigHandle, jboolean isMutable) {

-    const SkBitmap* src = reinterpret_cast<SkBitmap*>(srcHandle);

-    SkBitmap::Config dstConfig = static_cast<SkBitmap::Config>(dstConfigHandle);

-    SkBitmap            result;

-    JavaPixelAllocator  allocator(env);

-

+#include "SkBitmap.h"
+#include "SkPixelRef.h"
+#include "SkImageEncoder.h"
+#include "SkColorPriv.h"
+#include "GraphicsJNI.h"
+#include "SkDither.h"
+#include "SkUnPreMultiply.h"
+#include "SkStream.h"
+
+#include <binder/Parcel.h>
+#include "android_os_Parcel.h"
+#include "android_util_Binder.h"
+#include "android_nio_utils.h"
+#include "CreateJavaOutputStreamAdaptor.h"
+
+#include <jni.h>
+
+#include <Caches.h>
+
+#if 0
+    #define TRACE_BITMAP(code)  code
+#else
+    #define TRACE_BITMAP(code)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Conversions to/from SkColor, for get/setPixels, and the create method, which
+// is basically like setPixels
+
+typedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
+                              int x, int y);
+
+static void FromColor_D32(void* dst, const SkColor src[], int width,
+                          int, int) {
+    SkPMColor* d = (SkPMColor*)dst;
+
+    for (int i = 0; i < width; i++) {
+        *d++ = SkPreMultiplyColor(*src++);
+    }
+}
+
+static void FromColor_D32_Raw(void* dst, const SkColor src[], int width,
+                          int, int) {
+    // SkColor's ordering may be different from SkPMColor
+    if (SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER) {
+        memcpy(dst, src, width * sizeof(SkColor));
+        return;
+    }
+
+    // order isn't same, repack each pixel manually
+    SkPMColor* d = (SkPMColor*)dst;
+    for (int i = 0; i < width; i++) {
+        SkColor c = *src++;
+        *d++ = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
+                                   SkColorGetG(c), SkColorGetB(c));
+    }
+}
+
+static void FromColor_D565(void* dst, const SkColor src[], int width,
+                           int x, int y) {
+    uint16_t* d = (uint16_t*)dst;
+
+    DITHER_565_SCAN(y);
+    for (int stop = x + width; x < stop; x++) {
+        SkColor c = *src++;
+        *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c),
+                                DITHER_VALUE(x));
+    }
+}
+
+static void FromColor_D4444(void* dst, const SkColor src[], int width,
+                            int x, int y) {
+    SkPMColor16* d = (SkPMColor16*)dst;
+
+    DITHER_4444_SCAN(y);
+    for (int stop = x + width; x < stop; x++) {
+        SkPMColor pmc = SkPreMultiplyColor(*src++);
+        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
+//        *d++ = SkPixel32ToPixel4444(pmc);
+    }
+}
+
+static void FromColor_D4444_Raw(void* dst, const SkColor src[], int width,
+                            int x, int y) {
+    SkPMColor16* d = (SkPMColor16*)dst;
+
+    DITHER_4444_SCAN(y);
+    for (int stop = x + width; x < stop; x++) {
+        SkColor c = *src++;
+
+        // SkPMColor is used because the ordering is ARGB32, even though the target actually premultiplied
+        SkPMColor pmc = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
+                                            SkColorGetG(c), SkColorGetB(c));
+        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
+//        *d++ = SkPixel32ToPixel4444(pmc);
+    }
+}
+
+// can return NULL
+static FromColorProc ChooseFromColorProc(SkBitmap::Config config, bool isPremultiplied) {
+    switch (config) {
+        case SkBitmap::kARGB_8888_Config:
+            return isPremultiplied ? FromColor_D32 : FromColor_D32_Raw;
+        case SkBitmap::kARGB_4444_Config:
+            return isPremultiplied ? FromColor_D4444 : FromColor_D4444_Raw;
+        case SkBitmap::kRGB_565_Config:
+            return FromColor_D565;
+        default:
+            break;
+    }
+    return NULL;
+}
+
+bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
+        int x, int y, int width, int height,
+        const SkBitmap& dstBitmap, bool isPremultiplied) {
+    SkAutoLockPixels alp(dstBitmap);
+    void* dst = dstBitmap.getPixels();
+    FromColorProc proc = ChooseFromColorProc(dstBitmap.config(), isPremultiplied);
+
+    if (NULL == dst || NULL == proc) {
+        return false;
+    }
+
+    const jint* array = env->GetIntArrayElements(srcColors, NULL);
+    const SkColor* src = (const SkColor*)array + srcOffset;
+
+    // reset to to actual choice from caller
+    dst = dstBitmap.getAddr(x, y);
+    // now copy/convert each scanline
+    for (int y = 0; y < height; y++) {
+        proc(dst, src, width, x, y);
+        src += srcStride;
+        dst = (char*)dst + dstBitmap.rowBytes();
+    }
+
+    dstBitmap.notifyPixelsChanged();
+
+    env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array),
+                                 JNI_ABORT);
+    return true;
+}
+
+//////////////////// ToColor procs
+
+typedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
+                            SkColorTable*);
+
+static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
+                              SkColorTable*) {
+    SkASSERT(width > 0);
+    const SkPMColor* s = (const SkPMColor*)src;
+    do {
+        *dst++ = SkUnPreMultiply::PMColorToColor(*s++);
+    } while (--width != 0);
+}
+
+static void ToColor_S32_Raw(SkColor dst[], const void* src, int width,
+                              SkColorTable*) {
+    SkASSERT(width > 0);
+    const SkPMColor* s = (const SkPMColor*)src;
+    do {
+        SkPMColor c = *s++;
+        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
+                                SkGetPackedG32(c), SkGetPackedB32(c));
+    } while (--width != 0);
+}
+
+static void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
+                               SkColorTable*) {
+    SkASSERT(width > 0);
+    const SkPMColor* s = (const SkPMColor*)src;
+    do {
+        SkPMColor c = *s++;
+        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
+                               SkGetPackedB32(c));
+    } while (--width != 0);
+}
+
+static void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
+                                SkColorTable*) {
+    SkASSERT(width > 0);
+    const SkPMColor16* s = (const SkPMColor16*)src;
+    do {
+        *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));
+    } while (--width != 0);
+}
+
+static void ToColor_S4444_Raw(SkColor dst[], const void* src, int width,
+                                SkColorTable*) {
+    SkASSERT(width > 0);
+    const SkPMColor16* s = (const SkPMColor16*)src;
+    do {
+        SkPMColor c = SkPixel4444ToPixel32(*s++);
+        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
+                                SkGetPackedG32(c), SkGetPackedB32(c));
+    } while (--width != 0);
+}
+
+static void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
+                                 SkColorTable*) {
+    SkASSERT(width > 0);
+    const SkPMColor16* s = (const SkPMColor16*)src;
+    do {
+        SkPMColor c = SkPixel4444ToPixel32(*s++);
+        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
+                               SkGetPackedB32(c));
+    } while (--width != 0);
+}
+
+static void ToColor_S565(SkColor dst[], const void* src, int width,
+                         SkColorTable*) {
+    SkASSERT(width > 0);
+    const uint16_t* s = (const uint16_t*)src;
+    do {
+        uint16_t c = *s++;
+        *dst++ =  SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),
+                                SkPacked16ToB32(c));
+    } while (--width != 0);
+}
+
+static void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
+                              SkColorTable* ctable) {
+    SkASSERT(width > 0);
+    const uint8_t* s = (const uint8_t*)src;
+    const SkPMColor* colors = ctable->lockColors();
+    do {
+        *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]);
+    } while (--width != 0);
+    ctable->unlockColors();
+}
+
+static void ToColor_SI8_Raw(SkColor dst[], const void* src, int width,
+                              SkColorTable* ctable) {
+    SkASSERT(width > 0);
+    const uint8_t* s = (const uint8_t*)src;
+    const SkPMColor* colors = ctable->lockColors();
+    do {
+        SkPMColor c = colors[*s++];
+        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
+                                SkGetPackedG32(c), SkGetPackedB32(c));
+    } while (--width != 0);
+    ctable->unlockColors();
+}
+
+static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
+                               SkColorTable* ctable) {
+    SkASSERT(width > 0);
+    const uint8_t* s = (const uint8_t*)src;
+    const SkPMColor* colors = ctable->lockColors();
+    do {
+        SkPMColor c = colors[*s++];
+        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
+                               SkGetPackedB32(c));
+    } while (--width != 0);
+    ctable->unlockColors();
+}
+
+// can return NULL
+static ToColorProc ChooseToColorProc(const SkBitmap& src, bool isPremultiplied) {
+    switch (src.config()) {
+        case SkBitmap::kARGB_8888_Config:
+            if (src.isOpaque()) return ToColor_S32_Opaque;
+            return isPremultiplied ? ToColor_S32_Alpha : ToColor_S32_Raw;
+        case SkBitmap::kARGB_4444_Config:
+            if (src.isOpaque()) return ToColor_S4444_Opaque;
+            return isPremultiplied ? ToColor_S4444_Alpha : ToColor_S4444_Raw;
+        case SkBitmap::kRGB_565_Config:
+            return ToColor_S565;
+        case SkBitmap::kIndex8_Config:
+            if (src.getColorTable() == NULL) {
+                return NULL;
+            }
+            if (src.isOpaque()) return ToColor_SI8_Opaque;
+            return isPremultiplied ? ToColor_SI8_Raw : ToColor_SI8_Alpha;
+        default:
+            break;
+    }
+    return NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static int getPremulBitmapCreateFlags(bool isMutable) {
+    int flags = GraphicsJNI::kBitmapCreateFlag_Premultiplied;
+    if (isMutable) flags |= GraphicsJNI::kBitmapCreateFlag_Mutable;
+    return flags;
+}
+
+static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
+                              jint offset, jint stride, jint width, jint height,
+                              jint configHandle, jboolean isMutable) {
+    SkBitmap::Config config = static_cast<SkBitmap::Config>(configHandle);
+    if (NULL != jColors) {
+        size_t n = env->GetArrayLength(jColors);
+        if (n < SkAbs32(stride) * (size_t)height) {
+            doThrowAIOOBE(env);
+            return NULL;
+        }
+    }
+
+    // ARGB_4444 is a deprecated format, convert automatically to 8888
+    if (config == SkBitmap::kARGB_4444_Config) {
+        config = SkBitmap::kARGB_8888_Config;
+    }
+
+    SkBitmap bitmap;
+    bitmap.setConfig(config, width, height);
+
+    jbyteArray buff = GraphicsJNI::allocateJavaPixelRef(env, &bitmap, NULL);
+    if (NULL == buff) {
+        return NULL;
+    }
+
+    if (jColors != NULL) {
+        GraphicsJNI::SetPixels(env, jColors, offset, stride,
+                0, 0, width, height, bitmap, true);
+    }
+
+    return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff,
+            getPremulBitmapCreateFlags(isMutable), NULL, NULL);
+}
+
+static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
+                           jint dstConfigHandle, jboolean isMutable) {
+    const SkBitmap* src = reinterpret_cast<SkBitmap*>(srcHandle);
+    SkBitmap::Config dstConfig = static_cast<SkBitmap::Config>(dstConfigHandle);
+    SkBitmap            result;
+    JavaPixelAllocator  allocator(env);
+
     if (!src->copyTo(&result, SkBitmapConfigToColorType(dstConfig), &allocator)) {
-        return NULL;

-    }

-    return GraphicsJNI::createBitmap(env, new SkBitmap(result), allocator.getStorageObj(),

-            getPremulBitmapCreateFlags(isMutable), NULL, NULL);

-}

-

-static void Bitmap_destructor(JNIEnv* env, jobject, jlong bitmapHandle) {

-    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);

-#ifdef USE_OPENGL_RENDERER

-    if (android::uirenderer::Caches::hasInstance()) {

-        android::uirenderer::Caches::getInstance().resourceCache.destructor(bitmap);

-        return;

-    }

-#endif // USE_OPENGL_RENDERER

-    delete bitmap;

-}

-

-static jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {

-    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);

-#ifdef USE_OPENGL_RENDERER

-    if (android::uirenderer::Caches::hasInstance()) {

-        bool result;

-        result = android::uirenderer::Caches::getInstance().resourceCache.recycle(bitmap);

-        return result ? JNI_TRUE : JNI_FALSE;

-    }

-#endif // USE_OPENGL_RENDERER

-    bitmap->setPixels(NULL, NULL);

-    return JNI_TRUE;

-}

-

-static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,

-        jint width, jint height, jint configHandle, jint allocSize) {

-    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);

-    SkBitmap::Config config = static_cast<SkBitmap::Config>(configHandle);    

-    if (width * height * SkBitmap::ComputeBytesPerPixel(config) > allocSize) {

-        // done in native as there's no way to get BytesPerPixel in Java

-        doThrowIAE(env, "Bitmap not large enough to support new configuration");

-        return;

-    }

-    SkPixelRef* ref = bitmap->pixelRef();

-    SkSafeRef(ref);

-    bitmap->setConfig(config, width, height);

-    bitmap->setPixelRef(ref);

-

-    // notifyPixelsChanged will increment the generation ID even though the actual pixel data

-    // hasn't been touched. This signals the renderer that the bitmap (including width, height,

-    // and config) has changed.

-    ref->notifyPixelsChanged();

-    SkSafeUnref(ref);

-}

-

-// These must match the int values in Bitmap.java

-enum JavaEncodeFormat {

-    kJPEG_JavaEncodeFormat = 0,

-    kPNG_JavaEncodeFormat = 1,

-    kWEBP_JavaEncodeFormat = 2

-};

-

-static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,

-                                jint format, jint quality,

-                                jobject jstream, jbyteArray jstorage) {

-    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);

-    SkImageEncoder::Type fm;

-

-    switch (format) {

-    case kJPEG_JavaEncodeFormat:

-        fm = SkImageEncoder::kJPEG_Type;

-        break;

-    case kPNG_JavaEncodeFormat:

-        fm = SkImageEncoder::kPNG_Type;

-        break;

-    case kWEBP_JavaEncodeFormat:

-        fm = SkImageEncoder::kWEBP_Type;

-        break;

-    default:

-        return JNI_FALSE;

-    }

-

-    bool success = false;

-    if (NULL != bitmap) {

-        SkAutoLockPixels alp(*bitmap);

-

-        if (NULL == bitmap->getPixels()) {

-            return JNI_FALSE;

-        }

-

-        SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);

-        if (NULL == strm) {

-            return JNI_FALSE;

-        }

-

-        SkImageEncoder* encoder = SkImageEncoder::Create(fm);

-        if (NULL != encoder) {

-            success = encoder->encodeStream(strm, *bitmap, quality);

-            delete encoder;

-        }

-        delete strm;

-    }

-    return success ? JNI_TRUE : JNI_FALSE;

-}

-

-static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {

-    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);

-    bitmap->eraseColor(color);

-}

-

-static jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {

-    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);

-    return static_cast<jint>(bitmap->rowBytes());

-}

-

-static jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {

-    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);

-    return static_cast<jint>(bitmap->config());

-}

-

-static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {

-    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);

-    return static_cast<jint>(bitmap->getGenerationID());

-}

-

-static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {

-    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);

-    return !bitmap->isOpaque() ? JNI_TRUE : JNI_FALSE;

-}

-

-static void Bitmap_setAlphaAndPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,

-                                            jboolean hasAlpha, jboolean isPremul) {

-    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);

-    if (!hasAlpha) {

-        bitmap->setAlphaType(kOpaque_SkAlphaType);

-    } else if (isPremul) {

-        bitmap->setAlphaType(kPremul_SkAlphaType);

-    } else {

-        bitmap->setAlphaType(kUnpremul_SkAlphaType);

-    }

-}

-

-static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) {

-    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);

-    return bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE;

-}

-

-static void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle,

-                                jboolean hasMipMap) {

-    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);

-    bitmap->setHasHardwareMipMap(hasMipMap);

-}

-

-///////////////////////////////////////////////////////////////////////////////

-

-static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {

-    if (parcel == NULL) {

-        SkDebugf("-------- unparcel parcel is NULL\n");

-        return NULL;

-    }

-

-    android::Parcel* p = android::parcelForJavaObject(env, parcel);

-

-    const bool              isMutable = p->readInt32() != 0;

-    const SkBitmap::Config  config = (SkBitmap::Config)p->readInt32();

-    const int               width = p->readInt32();

-    const int               height = p->readInt32();

-    const int               rowBytes = p->readInt32();

-    const int               density = p->readInt32();

-

-    if (SkBitmap::kARGB_8888_Config != config &&

-            SkBitmap::kRGB_565_Config != config &&

-            SkBitmap::kARGB_4444_Config != config &&

-            SkBitmap::kIndex8_Config != config &&

-            SkBitmap::kA8_Config != config) {

-        SkDebugf("Bitmap_createFromParcel unknown config: %d\n", config);

-        return NULL;

-    }

-

-    SkBitmap* bitmap = new SkBitmap;

-

-    bitmap->setConfig(config, width, height, rowBytes);

-

-    SkColorTable* ctable = NULL;

-    if (config == SkBitmap::kIndex8_Config) {

-        int count = p->readInt32();

-        if (count > 0) {

-            size_t size = count * sizeof(SkPMColor);

-            const SkPMColor* src = (const SkPMColor*)p->readInplace(size);

-            ctable = new SkColorTable(src, count);

-        }

-    }

-

-    jbyteArray buffer = GraphicsJNI::allocateJavaPixelRef(env, bitmap, ctable);

-    if (NULL == buffer) {

-        SkSafeUnref(ctable);

-        delete bitmap;

-        return NULL;

-    }

-

-    SkSafeUnref(ctable);

-

-    size_t size = bitmap->getSize();

-

-    android::Parcel::ReadableBlob blob;

-    android::status_t status = p->readBlob(size, &blob);

-    if (status) {

-        doThrowRE(env, "Could not read bitmap from parcel blob.");

-        delete bitmap;

-        return NULL;

-    }

-

-    bitmap->lockPixels();

-    memcpy(bitmap->getPixels(), blob.data(), size);

-    bitmap->unlockPixels();

-

-    blob.release();

-

-    return GraphicsJNI::createBitmap(env, bitmap, buffer, getPremulBitmapCreateFlags(isMutable),

-            NULL, NULL, density);

-}

-

-static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,

-                                     jlong bitmapHandle,

-                                     jboolean isMutable, jint density,

-                                     jobject parcel) {

-    const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);

-    if (parcel == NULL) {

-        SkDebugf("------- writeToParcel null parcel\n");

-        return JNI_FALSE;

-    }

-

-    android::Parcel* p = android::parcelForJavaObject(env, parcel);

-

-    p->writeInt32(isMutable);

-    p->writeInt32(bitmap->config());

-    p->writeInt32(bitmap->width());

-    p->writeInt32(bitmap->height());

-    p->writeInt32(bitmap->rowBytes());

-    p->writeInt32(density);

-

-    if (bitmap->config() == SkBitmap::kIndex8_Config) {

-        SkColorTable* ctable = bitmap->getColorTable();

-        if (ctable != NULL) {

-            int count = ctable->count();

-            p->writeInt32(count);

-            memcpy(p->writeInplace(count * sizeof(SkPMColor)),

-                   ctable->lockColors(), count * sizeof(SkPMColor));

-            ctable->unlockColors();

-        } else {

-            p->writeInt32(0);   // indicate no ctable

-        }

-    }

-

-    size_t size = bitmap->getSize();

-

-    android::Parcel::WritableBlob blob;

-    android::status_t status = p->writeBlob(size, &blob);

-    if (status) {

-        doThrowRE(env, "Could not write bitmap to parcel blob.");

-        return JNI_FALSE;

-    }

-

-    bitmap->lockPixels();

-    const void* pSrc =  bitmap->getPixels();

-    if (pSrc == NULL) {

-        memset(blob.data(), 0, size);

-    } else {

-        memcpy(blob.data(), pSrc, size);

-    }

-    bitmap->unlockPixels();

-

-    blob.release();

-    return JNI_TRUE;

-}

-

-static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,

-                                   jlong srcHandle, jlong paintHandle,

-                                   jintArray offsetXY) {

-    const SkBitmap* src = reinterpret_cast<SkBitmap*>(srcHandle);

-    const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);

-    SkIPoint  offset;

-    SkBitmap* dst = new SkBitmap;

-    JavaPixelAllocator allocator(env);

-

-    src->extractAlpha(dst, paint, &allocator, &offset);

-    // If Skia can't allocate pixels for destination bitmap, it resets

-    // it, that is set its pixels buffer to NULL, and zero width and height.

-    if (dst->getPixels() == NULL && src->getPixels() != NULL) {

-        delete dst;

-        doThrowOOME(env, "failed to allocate pixels for alpha");

-        return NULL;

-    }

-    if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {

-        int* array = env->GetIntArrayElements(offsetXY, NULL);

-        array[0] = offset.fX;

-        array[1] = offset.fY;

-        env->ReleaseIntArrayElements(offsetXY, array, 0);

-    }

-

-    return GraphicsJNI::createBitmap(env, dst, allocator.getStorageObj(),

-            getPremulBitmapCreateFlags(true), NULL, NULL);

-}

-

-///////////////////////////////////////////////////////////////////////////////

-

-static jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,

-        jint x, jint y, jboolean isPremultiplied) {

-    const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);

-    SkAutoLockPixels alp(*bitmap);

-

-    ToColorProc proc = ChooseToColorProc(*bitmap, isPremultiplied);

-    if (NULL == proc) {

-        return 0;

-    }

-    const void* src = bitmap->getAddr(x, y);

-    if (NULL == src) {

-        return 0;

-    }

-

-    SkColor dst[1];

-    proc(dst, src, 1, bitmap->getColorTable());

-    return static_cast<jint>(dst[0]);

-}

-

-static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,

-        jintArray pixelArray, jint offset, jint stride,

-        jint x, jint y, jint width, jint height, jboolean isPremultiplied) {

-    const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);

-    SkAutoLockPixels alp(*bitmap);

-

-    ToColorProc proc = ChooseToColorProc(*bitmap, isPremultiplied);

-    if (NULL == proc) {

-        return;

-    }

-    const void* src = bitmap->getAddr(x, y);

-    if (NULL == src) {

-        return;

-    }

-

-    SkColorTable* ctable = bitmap->getColorTable();

-    jint* dst = env->GetIntArrayElements(pixelArray, NULL);

-    SkColor* d = (SkColor*)dst + offset;

-    while (--height >= 0) {

-        proc(d, src, width, ctable);

-        d += stride;

-        src = (void*)((const char*)src + bitmap->rowBytes());

-    }

-    env->ReleaseIntArrayElements(pixelArray, dst, 0);

-}

-

-///////////////////////////////////////////////////////////////////////////////

-

-static void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,

-        jint x, jint y, jint colorHandle, jboolean isPremultiplied) {

-    const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);

-    SkColor color = static_cast<SkColor>(colorHandle);

-    SkAutoLockPixels alp(*bitmap);

-    if (NULL == bitmap->getPixels()) {

-        return;

-    }

-

-    FromColorProc proc = ChooseFromColorProc(bitmap->config(), isPremultiplied);

-    if (NULL == proc) {

-        return;

-    }

-

-    proc(bitmap->getAddr(x, y), &color, 1, x, y);

-    bitmap->notifyPixelsChanged();

-}

-

-static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,

-        jintArray pixelArray, jint offset, jint stride,

-        jint x, jint y, jint width, jint height, jboolean isPremultiplied) {

-    const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);

-    GraphicsJNI::SetPixels(env, pixelArray, offset, stride,

-            x, y, width, height, *bitmap, isPremultiplied);

-}

-

-static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,

-                                      jlong bitmapHandle, jobject jbuffer) {

-    const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);

-    SkAutoLockPixels alp(*bitmap);

-    const void* src = bitmap->getPixels();

-

-    if (NULL != src) {

-        android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);

-

-        // the java side has already checked that buffer is large enough

-        memcpy(abp.pointer(), src, bitmap->getSize());

-    }

-}

-

-static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,

-                                        jlong bitmapHandle, jobject jbuffer) {

-    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);

-    SkAutoLockPixels alp(*bitmap);

-    void* dst = bitmap->getPixels();

-

-    if (NULL != dst) {

-        android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);

-        // the java side has already checked that buffer is large enough

-        memcpy(dst, abp.pointer(), bitmap->getSize());

-        bitmap->notifyPixelsChanged();

-    }

-}

-

-static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle,

-                              jlong bm1Handle) {

-    const SkBitmap* bm0 = reinterpret_cast<SkBitmap*>(bm0Handle);

-    const SkBitmap* bm1 = reinterpret_cast<SkBitmap*>(bm1Handle);

-    if (bm0->width() != bm1->width() ||

-        bm0->height() != bm1->height() ||

-        bm0->config() != bm1->config()) {

-        return JNI_FALSE;

-    }

-

-    SkAutoLockPixels alp0(*bm0);

-    SkAutoLockPixels alp1(*bm1);

-

-    // if we can't load the pixels, return false

-    if (NULL == bm0->getPixels() || NULL == bm1->getPixels()) {

-        return JNI_FALSE;

-    }

-

-    if (bm0->config() == SkBitmap::kIndex8_Config) {

-        SkColorTable* ct0 = bm0->getColorTable();

-        SkColorTable* ct1 = bm1->getColorTable();

-        if (NULL == ct0 || NULL == ct1) {

-            return JNI_FALSE;

-        }

-        if (ct0->count() != ct1->count()) {

-            return JNI_FALSE;

-        }

-

-        SkAutoLockColors alc0(ct0);

-        SkAutoLockColors alc1(ct1);

-        const size_t size = ct0->count() * sizeof(SkPMColor);

-        if (memcmp(alc0.colors(), alc1.colors(), size) != 0) {

-            return JNI_FALSE;

-        }

-    }

-

-    // now compare each scanline. We can't do the entire buffer at once,

-    // since we don't care about the pixel values that might extend beyond

-    // the width (since the scanline might be larger than the logical width)

-    const int h = bm0->height();

-    const size_t size = bm0->width() * bm0->bytesPerPixel();

-    for (int y = 0; y < h; y++) {

-        if (memcmp(bm0->getAddr(0, y), bm1->getAddr(0, y), size) != 0) {

-            return JNI_FALSE;

-        }

-    }

-    return JNI_TRUE;

-}

-

-static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapHandle) {

-    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);

-    bitmap->lockPixels();

-    bitmap->unlockPixels();

-}

-

-///////////////////////////////////////////////////////////////////////////////

-

-#include <android_runtime/AndroidRuntime.h>

-

-static JNINativeMethod gBitmapMethods[] = {

-    {   "nativeCreate",             "([IIIIIIZ)Landroid/graphics/Bitmap;",

-        (void*)Bitmap_creator },

-    {   "nativeCopy",               "(JIZ)Landroid/graphics/Bitmap;",

-        (void*)Bitmap_copy },

-    {   "nativeDestructor",         "(J)V", (void*)Bitmap_destructor },

-    {   "nativeRecycle",            "(J)Z", (void*)Bitmap_recycle },

-    {   "nativeReconfigure",        "(JIIII)V", (void*)Bitmap_reconfigure },

-    {   "nativeCompress",           "(JIILjava/io/OutputStream;[B)Z",

-        (void*)Bitmap_compress },

-    {   "nativeErase",              "(JI)V", (void*)Bitmap_erase },

-    {   "nativeRowBytes",           "(J)I", (void*)Bitmap_rowBytes },

-    {   "nativeConfig",             "(J)I", (void*)Bitmap_config },

-    {   "nativeHasAlpha",           "(J)Z", (void*)Bitmap_hasAlpha },

-    {   "nativeSetAlphaAndPremultiplied", "(JZZ)V", (void*)Bitmap_setAlphaAndPremultiplied},

-    {   "nativeHasMipMap",          "(J)Z", (void*)Bitmap_hasMipMap },

-    {   "nativeSetHasMipMap",       "(JZ)V", (void*)Bitmap_setHasMipMap },

-    {   "nativeCreateFromParcel",

-        "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",

-        (void*)Bitmap_createFromParcel },

-    {   "nativeWriteToParcel",      "(JZILandroid/os/Parcel;)Z",

-        (void*)Bitmap_writeToParcel },

-    {   "nativeExtractAlpha",       "(JJ[I)Landroid/graphics/Bitmap;",

-        (void*)Bitmap_extractAlpha },

-    {   "nativeGenerationId",       "(J)I", (void*)Bitmap_getGenerationId },

-    {   "nativeGetPixel",           "(JIIZ)I", (void*)Bitmap_getPixel },

-    {   "nativeGetPixels",          "(J[IIIIIIIZ)V", (void*)Bitmap_getPixels },

-    {   "nativeSetPixel",           "(JIIIZ)V", (void*)Bitmap_setPixel },

-    {   "nativeSetPixels",          "(J[IIIIIIIZ)V", (void*)Bitmap_setPixels },

-    {   "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",

-                                            (void*)Bitmap_copyPixelsToBuffer },

-    {   "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",

-                                            (void*)Bitmap_copyPixelsFromBuffer },

-    {   "nativeSameAs",             "(JJ)Z", (void*)Bitmap_sameAs },

-    {   "nativePrepareToDraw",      "(J)V", (void*)Bitmap_prepareToDraw },

-};

-

-#define kClassPathName  "android/graphics/Bitmap"

-

-int register_android_graphics_Bitmap(JNIEnv* env)

-{

-    return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,

-                                gBitmapMethods, SK_ARRAY_COUNT(gBitmapMethods));

-}

+        return NULL;
+    }
+    return GraphicsJNI::createBitmap(env, new SkBitmap(result), allocator.getStorageObj(),
+            getPremulBitmapCreateFlags(isMutable), NULL, NULL);
+}
+
+static void Bitmap_destructor(JNIEnv* env, jobject, jlong bitmapHandle) {
+    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+#ifdef USE_OPENGL_RENDERER
+    if (android::uirenderer::Caches::hasInstance()) {
+        android::uirenderer::Caches::getInstance().resourceCache.destructor(bitmap);
+        return;
+    }
+#endif // USE_OPENGL_RENDERER
+    delete bitmap;
+}
+
+static jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
+    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+#ifdef USE_OPENGL_RENDERER
+    if (android::uirenderer::Caches::hasInstance()) {
+        bool result;
+        result = android::uirenderer::Caches::getInstance().resourceCache.recycle(bitmap);
+        return result ? JNI_TRUE : JNI_FALSE;
+    }
+#endif // USE_OPENGL_RENDERER
+    bitmap->setPixels(NULL, NULL);
+    return JNI_TRUE;
+}
+
+static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
+        jint width, jint height, jint configHandle, jint allocSize) {
+    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+    SkBitmap::Config config = static_cast<SkBitmap::Config>(configHandle);
+    if (width * height * SkBitmap::ComputeBytesPerPixel(config) > allocSize) {
+        // done in native as there's no way to get BytesPerPixel in Java
+        doThrowIAE(env, "Bitmap not large enough to support new configuration");
+        return;
+    }
+    SkPixelRef* ref = bitmap->pixelRef();
+    SkSafeRef(ref);
+    bitmap->setConfig(config, width, height);
+    bitmap->setPixelRef(ref);
+
+    // notifyPixelsChanged will increment the generation ID even though the actual pixel data
+    // hasn't been touched. This signals the renderer that the bitmap (including width, height,
+    // and config) has changed.
+    ref->notifyPixelsChanged();
+    SkSafeUnref(ref);
+}
+
+// These must match the int values in Bitmap.java
+enum JavaEncodeFormat {
+    kJPEG_JavaEncodeFormat = 0,
+    kPNG_JavaEncodeFormat = 1,
+    kWEBP_JavaEncodeFormat = 2
+};
+
+static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
+                                jint format, jint quality,
+                                jobject jstream, jbyteArray jstorage) {
+    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+    SkImageEncoder::Type fm;
+
+    switch (format) {
+    case kJPEG_JavaEncodeFormat:
+        fm = SkImageEncoder::kJPEG_Type;
+        break;
+    case kPNG_JavaEncodeFormat:
+        fm = SkImageEncoder::kPNG_Type;
+        break;
+    case kWEBP_JavaEncodeFormat:
+        fm = SkImageEncoder::kWEBP_Type;
+        break;
+    default:
+        return JNI_FALSE;
+    }
+
+    bool success = false;
+    if (NULL != bitmap) {
+        SkAutoLockPixels alp(*bitmap);
+
+        if (NULL == bitmap->getPixels()) {
+            return JNI_FALSE;
+        }
+
+        SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
+        if (NULL == strm) {
+            return JNI_FALSE;
+        }
+
+        SkImageEncoder* encoder = SkImageEncoder::Create(fm);
+        if (NULL != encoder) {
+            success = encoder->encodeStream(strm, *bitmap, quality);
+            delete encoder;
+        }
+        delete strm;
+    }
+    return success ? JNI_TRUE : JNI_FALSE;
+}
+
+static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
+    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+    bitmap->eraseColor(color);
+}
+
+static jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {
+    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+    return static_cast<jint>(bitmap->rowBytes());
+}
+
+static jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
+    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+    return static_cast<jint>(bitmap->config());
+}
+
+static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
+    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+    return static_cast<jint>(bitmap->getGenerationID());
+}
+
+static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {
+    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+    return !bitmap->isOpaque() ? JNI_TRUE : JNI_FALSE;
+}
+
+static void Bitmap_setAlphaAndPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
+                                            jboolean hasAlpha, jboolean isPremul) {
+    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+    if (!hasAlpha) {
+        bitmap->setAlphaType(kOpaque_SkAlphaType);
+    } else if (isPremul) {
+        bitmap->setAlphaType(kPremul_SkAlphaType);
+    } else {
+        bitmap->setAlphaType(kUnpremul_SkAlphaType);
+    }
+}
+
+static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) {
+    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+    return bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE;
+}
+
+static void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle,
+                                jboolean hasMipMap) {
+    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+    bitmap->setHasHardwareMipMap(hasMipMap);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
+    if (parcel == NULL) {
+        SkDebugf("-------- unparcel parcel is NULL\n");
+        return NULL;
+    }
+
+    android::Parcel* p = android::parcelForJavaObject(env, parcel);
+
+    const bool              isMutable = p->readInt32() != 0;
+    const SkBitmap::Config  config = (SkBitmap::Config)p->readInt32();
+    const int               width = p->readInt32();
+    const int               height = p->readInt32();
+    const int               rowBytes = p->readInt32();
+    const int               density = p->readInt32();
+
+    if (SkBitmap::kARGB_8888_Config != config &&
+            SkBitmap::kRGB_565_Config != config &&
+            SkBitmap::kARGB_4444_Config != config &&
+            SkBitmap::kIndex8_Config != config &&
+            SkBitmap::kA8_Config != config) {
+        SkDebugf("Bitmap_createFromParcel unknown config: %d\n", config);
+        return NULL;
+    }
+
+    SkBitmap* bitmap = new SkBitmap;
+
+    bitmap->setConfig(config, width, height, rowBytes);
+
+    SkColorTable* ctable = NULL;
+    if (config == SkBitmap::kIndex8_Config) {
+        int count = p->readInt32();
+        if (count > 0) {
+            size_t size = count * sizeof(SkPMColor);
+            const SkPMColor* src = (const SkPMColor*)p->readInplace(size);
+            ctable = new SkColorTable(src, count);
+        }
+    }
+
+    jbyteArray buffer = GraphicsJNI::allocateJavaPixelRef(env, bitmap, ctable);
+    if (NULL == buffer) {
+        SkSafeUnref(ctable);
+        delete bitmap;
+        return NULL;
+    }
+
+    SkSafeUnref(ctable);
+
+    size_t size = bitmap->getSize();
+
+    android::Parcel::ReadableBlob blob;
+    android::status_t status = p->readBlob(size, &blob);
+    if (status) {
+        doThrowRE(env, "Could not read bitmap from parcel blob.");
+        delete bitmap;
+        return NULL;
+    }
+
+    bitmap->lockPixels();
+    memcpy(bitmap->getPixels(), blob.data(), size);
+    bitmap->unlockPixels();
+
+    blob.release();
+
+    return GraphicsJNI::createBitmap(env, bitmap, buffer, getPremulBitmapCreateFlags(isMutable),
+            NULL, NULL, density);
+}
+
+static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
+                                     jlong bitmapHandle,
+                                     jboolean isMutable, jint density,
+                                     jobject parcel) {
+    const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+    if (parcel == NULL) {
+        SkDebugf("------- writeToParcel null parcel\n");
+        return JNI_FALSE;
+    }
+
+    android::Parcel* p = android::parcelForJavaObject(env, parcel);
+
+    p->writeInt32(isMutable);
+    p->writeInt32(bitmap->config());
+    p->writeInt32(bitmap->width());
+    p->writeInt32(bitmap->height());
+    p->writeInt32(bitmap->rowBytes());
+    p->writeInt32(density);
+
+    if (bitmap->config() == SkBitmap::kIndex8_Config) {
+        SkColorTable* ctable = bitmap->getColorTable();
+        if (ctable != NULL) {
+            int count = ctable->count();
+            p->writeInt32(count);
+            memcpy(p->writeInplace(count * sizeof(SkPMColor)),
+                   ctable->lockColors(), count * sizeof(SkPMColor));
+            ctable->unlockColors();
+        } else {
+            p->writeInt32(0);   // indicate no ctable
+        }
+    }
+
+    size_t size = bitmap->getSize();
+
+    android::Parcel::WritableBlob blob;
+    android::status_t status = p->writeBlob(size, &blob);
+    if (status) {
+        doThrowRE(env, "Could not write bitmap to parcel blob.");
+        return JNI_FALSE;
+    }
+
+    bitmap->lockPixels();
+    const void* pSrc =  bitmap->getPixels();
+    if (pSrc == NULL) {
+        memset(blob.data(), 0, size);
+    } else {
+        memcpy(blob.data(), pSrc, size);
+    }
+    bitmap->unlockPixels();
+
+    blob.release();
+    return JNI_TRUE;
+}
+
+static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
+                                   jlong srcHandle, jlong paintHandle,
+                                   jintArray offsetXY) {
+    const SkBitmap* src = reinterpret_cast<SkBitmap*>(srcHandle);
+    const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+    SkIPoint  offset;
+    SkBitmap* dst = new SkBitmap;
+    JavaPixelAllocator allocator(env);
+
+    src->extractAlpha(dst, paint, &allocator, &offset);
+    // If Skia can't allocate pixels for destination bitmap, it resets
+    // it, that is set its pixels buffer to NULL, and zero width and height.
+    if (dst->getPixels() == NULL && src->getPixels() != NULL) {
+        delete dst;
+        doThrowOOME(env, "failed to allocate pixels for alpha");
+        return NULL;
+    }
+    if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
+        int* array = env->GetIntArrayElements(offsetXY, NULL);
+        array[0] = offset.fX;
+        array[1] = offset.fY;
+        env->ReleaseIntArrayElements(offsetXY, array, 0);
+    }
+
+    return GraphicsJNI::createBitmap(env, dst, allocator.getStorageObj(),
+            getPremulBitmapCreateFlags(true), NULL, NULL);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
+        jint x, jint y, jboolean isPremultiplied) {
+    const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+    SkAutoLockPixels alp(*bitmap);
+
+    ToColorProc proc = ChooseToColorProc(*bitmap, isPremultiplied);
+    if (NULL == proc) {
+        return 0;
+    }
+    const void* src = bitmap->getAddr(x, y);
+    if (NULL == src) {
+        return 0;
+    }
+
+    SkColor dst[1];
+    proc(dst, src, 1, bitmap->getColorTable());
+    return static_cast<jint>(dst[0]);
+}
+
+static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
+        jintArray pixelArray, jint offset, jint stride,
+        jint x, jint y, jint width, jint height, jboolean isPremultiplied) {
+    const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+    SkAutoLockPixels alp(*bitmap);
+
+    ToColorProc proc = ChooseToColorProc(*bitmap, isPremultiplied);
+    if (NULL == proc) {
+        return;
+    }
+    const void* src = bitmap->getAddr(x, y);
+    if (NULL == src) {
+        return;
+    }
+
+    SkColorTable* ctable = bitmap->getColorTable();
+    jint* dst = env->GetIntArrayElements(pixelArray, NULL);
+    SkColor* d = (SkColor*)dst + offset;
+    while (--height >= 0) {
+        proc(d, src, width, ctable);
+        d += stride;
+        src = (void*)((const char*)src + bitmap->rowBytes());
+    }
+    env->ReleaseIntArrayElements(pixelArray, dst, 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
+        jint x, jint y, jint colorHandle, jboolean isPremultiplied) {
+    const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+    SkColor color = static_cast<SkColor>(colorHandle);
+    SkAutoLockPixels alp(*bitmap);
+    if (NULL == bitmap->getPixels()) {
+        return;
+    }
+
+    FromColorProc proc = ChooseFromColorProc(bitmap->config(), isPremultiplied);
+    if (NULL == proc) {
+        return;
+    }
+
+    proc(bitmap->getAddr(x, y), &color, 1, x, y);
+    bitmap->notifyPixelsChanged();
+}
+
+static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
+        jintArray pixelArray, jint offset, jint stride,
+        jint x, jint y, jint width, jint height, jboolean isPremultiplied) {
+    const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+    GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
+            x, y, width, height, *bitmap, isPremultiplied);
+}
+
+static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
+                                      jlong bitmapHandle, jobject jbuffer) {
+    const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+    SkAutoLockPixels alp(*bitmap);
+    const void* src = bitmap->getPixels();
+
+    if (NULL != src) {
+        android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
+
+        // the java side has already checked that buffer is large enough
+        memcpy(abp.pointer(), src, bitmap->getSize());
+    }
+}
+
+static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
+                                        jlong bitmapHandle, jobject jbuffer) {
+    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+    SkAutoLockPixels alp(*bitmap);
+    void* dst = bitmap->getPixels();
+
+    if (NULL != dst) {
+        android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
+        // the java side has already checked that buffer is large enough
+        memcpy(dst, abp.pointer(), bitmap->getSize());
+        bitmap->notifyPixelsChanged();
+    }
+}
+
+static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle,
+                              jlong bm1Handle) {
+    const SkBitmap* bm0 = reinterpret_cast<SkBitmap*>(bm0Handle);
+    const SkBitmap* bm1 = reinterpret_cast<SkBitmap*>(bm1Handle);
+    if (bm0->width() != bm1->width() ||
+        bm0->height() != bm1->height() ||
+        bm0->config() != bm1->config()) {
+        return JNI_FALSE;
+    }
+
+    SkAutoLockPixels alp0(*bm0);
+    SkAutoLockPixels alp1(*bm1);
+
+    // if we can't load the pixels, return false
+    if (NULL == bm0->getPixels() || NULL == bm1->getPixels()) {
+        return JNI_FALSE;
+    }
+
+    if (bm0->config() == SkBitmap::kIndex8_Config) {
+        SkColorTable* ct0 = bm0->getColorTable();
+        SkColorTable* ct1 = bm1->getColorTable();
+        if (NULL == ct0 || NULL == ct1) {
+            return JNI_FALSE;
+        }
+        if (ct0->count() != ct1->count()) {
+            return JNI_FALSE;
+        }
+
+        SkAutoLockColors alc0(ct0);
+        SkAutoLockColors alc1(ct1);
+        const size_t size = ct0->count() * sizeof(SkPMColor);
+        if (memcmp(alc0.colors(), alc1.colors(), size) != 0) {
+            return JNI_FALSE;
+        }
+    }
+
+    // now compare each scanline. We can't do the entire buffer at once,
+    // since we don't care about the pixel values that might extend beyond
+    // the width (since the scanline might be larger than the logical width)
+    const int h = bm0->height();
+    const size_t size = bm0->width() * bm0->bytesPerPixel();
+    for (int y = 0; y < h; y++) {
+        if (memcmp(bm0->getAddr(0, y), bm1->getAddr(0, y), size) != 0) {
+            return JNI_FALSE;
+        }
+    }
+    return JNI_TRUE;
+}
+
+static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapHandle) {
+    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+    bitmap->lockPixels();
+    bitmap->unlockPixels();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include <android_runtime/AndroidRuntime.h>
+
+static JNINativeMethod gBitmapMethods[] = {
+    {   "nativeCreate",             "([IIIIIIZ)Landroid/graphics/Bitmap;",
+        (void*)Bitmap_creator },
+    {   "nativeCopy",               "(JIZ)Landroid/graphics/Bitmap;",
+        (void*)Bitmap_copy },
+    {   "nativeDestructor",         "(J)V", (void*)Bitmap_destructor },
+    {   "nativeRecycle",            "(J)Z", (void*)Bitmap_recycle },
+    {   "nativeReconfigure",        "(JIIII)V", (void*)Bitmap_reconfigure },
+    {   "nativeCompress",           "(JIILjava/io/OutputStream;[B)Z",
+        (void*)Bitmap_compress },
+    {   "nativeErase",              "(JI)V", (void*)Bitmap_erase },
+    {   "nativeRowBytes",           "(J)I", (void*)Bitmap_rowBytes },
+    {   "nativeConfig",             "(J)I", (void*)Bitmap_config },
+    {   "nativeHasAlpha",           "(J)Z", (void*)Bitmap_hasAlpha },
+    {   "nativeSetAlphaAndPremultiplied", "(JZZ)V", (void*)Bitmap_setAlphaAndPremultiplied},
+    {   "nativeHasMipMap",          "(J)Z", (void*)Bitmap_hasMipMap },
+    {   "nativeSetHasMipMap",       "(JZ)V", (void*)Bitmap_setHasMipMap },
+    {   "nativeCreateFromParcel",
+        "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
+        (void*)Bitmap_createFromParcel },
+    {   "nativeWriteToParcel",      "(JZILandroid/os/Parcel;)Z",
+        (void*)Bitmap_writeToParcel },
+    {   "nativeExtractAlpha",       "(JJ[I)Landroid/graphics/Bitmap;",
+        (void*)Bitmap_extractAlpha },
+    {   "nativeGenerationId",       "(J)I", (void*)Bitmap_getGenerationId },
+    {   "nativeGetPixel",           "(JIIZ)I", (void*)Bitmap_getPixel },
+    {   "nativeGetPixels",          "(J[IIIIIIIZ)V", (void*)Bitmap_getPixels },
+    {   "nativeSetPixel",           "(JIIIZ)V", (void*)Bitmap_setPixel },
+    {   "nativeSetPixels",          "(J[IIIIIIIZ)V", (void*)Bitmap_setPixels },
+    {   "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",
+                                            (void*)Bitmap_copyPixelsToBuffer },
+    {   "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
+                                            (void*)Bitmap_copyPixelsFromBuffer },
+    {   "nativeSameAs",             "(JJ)Z", (void*)Bitmap_sameAs },
+    {   "nativePrepareToDraw",      "(J)V", (void*)Bitmap_prepareToDraw },
+};
+
+#define kClassPathName  "android/graphics/Bitmap"
+
+int register_android_graphics_Bitmap(JNIEnv* env)
+{
+    return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,
+                                gBitmapMethods, SK_ARRAY_COUNT(gBitmapMethods));
+}
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00000_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00000_qntm_alpha.png
new file mode 100644
index 0000000..1880a15
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_anim_00000_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00001_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00001_qntm_alpha.png
new file mode 100644
index 0000000..aecb4d2
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_anim_00001_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00002_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00002_qntm_alpha.png
new file mode 100644
index 0000000..8401f91
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_anim_00002_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00003_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00003_qntm_alpha.png
new file mode 100644
index 0000000..5832865
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_anim_00003_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00004_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00004_qntm_alpha.png
new file mode 100644
index 0000000..6d14962
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_anim_00004_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00005_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00005_qntm_alpha.png
new file mode 100644
index 0000000..aee057c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_anim_00005_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00006_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00006_qntm_alpha.png
new file mode 100644
index 0000000..fb5801e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_anim_00006_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00007_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00007_qntm_alpha.png
new file mode 100644
index 0000000..fdb5271
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_anim_00007_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00008_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00008_qntm_alpha.png
new file mode 100644
index 0000000..b8c7397
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_anim_00008_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00009_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00009_qntm_alpha.png
new file mode 100644
index 0000000..d0395a8
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_anim_00009_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00010_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00010_qntm_alpha.png
new file mode 100644
index 0000000..59bb437
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_anim_00010_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00011_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00011_qntm_alpha.png
new file mode 100644
index 0000000..c053b90
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_anim_00011_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00012_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00012_qntm_alpha.png
new file mode 100644
index 0000000..eb30a79
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_anim_00012_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00013_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00013_qntm_alpha.png
new file mode 100644
index 0000000..1af0bff
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_anim_00013_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00014_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00014_qntm_alpha.png
new file mode 100644
index 0000000..3b36e7d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_anim_00014_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00015_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00015_qntm_alpha.png
new file mode 100644
index 0000000..c12d20a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_anim_00015_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00000_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00000_qntm_alpha.png
new file mode 100644
index 0000000..882365b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_anim_00000_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00001_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00001_qntm_alpha.png
new file mode 100644
index 0000000..f6c7094
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_anim_00001_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00002_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00002_qntm_alpha.png
new file mode 100644
index 0000000..0e326c9
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_anim_00002_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00003_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00003_qntm_alpha.png
new file mode 100644
index 0000000..8bf1170
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_anim_00003_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00004_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00004_qntm_alpha.png
new file mode 100644
index 0000000..cedb66e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_anim_00004_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00005_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00005_qntm_alpha.png
new file mode 100644
index 0000000..257d7ba
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_anim_00005_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00006_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00006_qntm_alpha.png
new file mode 100644
index 0000000..e07b36e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_anim_00006_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00007_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00007_qntm_alpha.png
new file mode 100644
index 0000000..ef94200
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_anim_00007_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00008_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00008_qntm_alpha.png
new file mode 100644
index 0000000..ad67004
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_anim_00008_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00009_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00009_qntm_alpha.png
new file mode 100644
index 0000000..50796e2
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_anim_00009_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00010_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00010_qntm_alpha.png
new file mode 100644
index 0000000..ba7be9e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_anim_00010_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00011_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00011_qntm_alpha.png
new file mode 100644
index 0000000..bdbfe78
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_anim_00011_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00012_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00012_qntm_alpha.png
new file mode 100644
index 0000000..fe89951
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_anim_00012_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00013_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00013_qntm_alpha.png
new file mode 100644
index 0000000..840c88f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_anim_00013_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00014_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00014_qntm_alpha.png
new file mode 100644
index 0000000..621d1d2
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_anim_00014_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00015_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00015_qntm_alpha.png
new file mode 100644
index 0000000..fd8be89
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_anim_00015_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00000_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00000_qntm_alpha.png
new file mode 100644
index 0000000..0f44ff9
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_anim_00000_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00001_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00001_qntm_alpha.png
new file mode 100644
index 0000000..9d5dda0
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_anim_00001_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00002_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00002_qntm_alpha.png
new file mode 100644
index 0000000..e4ce802
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_anim_00002_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00003_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00003_qntm_alpha.png
new file mode 100644
index 0000000..d1806ac
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_anim_00003_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00004_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00004_qntm_alpha.png
new file mode 100644
index 0000000..ab9315b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_anim_00004_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00005_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00005_qntm_alpha.png
new file mode 100644
index 0000000..46e90e6
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_anim_00005_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00006_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00006_qntm_alpha.png
new file mode 100644
index 0000000..e8c56ff
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_anim_00006_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00007_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00007_qntm_alpha.png
new file mode 100644
index 0000000..59dcb7e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_anim_00007_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00008_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00008_qntm_alpha.png
new file mode 100644
index 0000000..e9bd4a2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_anim_00008_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00009_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00009_qntm_alpha.png
new file mode 100644
index 0000000..1d05037
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_anim_00009_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00010_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00010_qntm_alpha.png
new file mode 100644
index 0000000..91b40de
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_anim_00010_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00011_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00011_qntm_alpha.png
new file mode 100644
index 0000000..c531cab
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_anim_00011_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00012_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00012_qntm_alpha.png
new file mode 100644
index 0000000..11bb387
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_anim_00012_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00013_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00013_qntm_alpha.png
new file mode 100644
index 0000000..8843210
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_anim_00013_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00014_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00014_qntm_alpha.png
new file mode 100644
index 0000000..6ff2f3d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_anim_00014_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00015_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00015_qntm_alpha.png
new file mode 100644
index 0000000..a03c1e2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_anim_00015_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00000_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00000_qntm_alpha.png
new file mode 100644
index 0000000..0a22e1a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_anim_00000_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00001_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00001_qntm_alpha.png
new file mode 100644
index 0000000..2e2469c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_anim_00001_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00002_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00002_qntm_alpha.png
new file mode 100644
index 0000000..c1054d9
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_anim_00002_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00003_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00003_qntm_alpha.png
new file mode 100644
index 0000000..cf8d80a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_anim_00003_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00004_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00004_qntm_alpha.png
new file mode 100644
index 0000000..9d9e870
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_anim_00004_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00005_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00005_qntm_alpha.png
new file mode 100644
index 0000000..1bad701
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_anim_00005_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00006_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00006_qntm_alpha.png
new file mode 100644
index 0000000..a84a54f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_anim_00006_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00007_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00007_qntm_alpha.png
new file mode 100644
index 0000000..4d8050b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_anim_00007_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00008_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00008_qntm_alpha.png
new file mode 100644
index 0000000..374172c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_anim_00008_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00009_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00009_qntm_alpha.png
new file mode 100644
index 0000000..233036e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_anim_00009_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00010_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00010_qntm_alpha.png
new file mode 100644
index 0000000..61d9b58
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_anim_00010_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00011_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00011_qntm_alpha.png
new file mode 100644
index 0000000..274e983
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_anim_00011_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00012_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00012_qntm_alpha.png
new file mode 100644
index 0000000..acf16e5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_anim_00012_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00013_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00013_qntm_alpha.png
new file mode 100644
index 0000000..ee48241
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_anim_00013_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00014_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00014_qntm_alpha.png
new file mode 100644
index 0000000..dbbb736
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_anim_00014_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00015_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00015_qntm_alpha.png
new file mode 100644
index 0000000..bcabd0d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_anim_00015_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/stat_sys_adb.xml b/core/res/res/drawable-nodpi/stat_sys_adb.xml
index 37df348..49028b4 100644
--- a/core/res/res/drawable-nodpi/stat_sys_adb.xml
+++ b/core/res/res/drawable-nodpi/stat_sys_adb.xml
@@ -21,7 +21,7 @@
     <group>
         <path
             android:name="adb"
-            android:pathData="m3,3l8,0l0,11l11,0l0,8l-18,0z"
+            android:pathData="m3,3l8,0l0,11l11,0l0,8l-19,0z"
             android:fill="#FFFFFFFF"
             />
     </group>
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00000_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00000_qntm_alpha.png
new file mode 100644
index 0000000..25500e8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_anim_00000_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00001_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00001_qntm_alpha.png
new file mode 100644
index 0000000..b136e25
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_anim_00001_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00002_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00002_qntm_alpha.png
new file mode 100644
index 0000000..6a94e30
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_anim_00002_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00003_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00003_qntm_alpha.png
new file mode 100644
index 0000000..d386421
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_anim_00003_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00004_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00004_qntm_alpha.png
new file mode 100644
index 0000000..c811385
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_anim_00004_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00005_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00005_qntm_alpha.png
new file mode 100644
index 0000000..58b3267
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_anim_00005_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00006_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00006_qntm_alpha.png
new file mode 100644
index 0000000..0659e72
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_anim_00006_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00007_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00007_qntm_alpha.png
new file mode 100644
index 0000000..b4227d1
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_anim_00007_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00008_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00008_qntm_alpha.png
new file mode 100644
index 0000000..714ef00
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_anim_00008_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00009_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00009_qntm_alpha.png
new file mode 100644
index 0000000..139595b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_anim_00009_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00010_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00010_qntm_alpha.png
new file mode 100644
index 0000000..4491107
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_anim_00010_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00011_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00011_qntm_alpha.png
new file mode 100644
index 0000000..20eb752
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_anim_00011_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00012_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00012_qntm_alpha.png
new file mode 100644
index 0000000..532c9f2
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_anim_00012_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00013_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00013_qntm_alpha.png
new file mode 100644
index 0000000..0d78a32
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_anim_00013_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00014_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00014_qntm_alpha.png
new file mode 100644
index 0000000..af29678
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_anim_00014_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00015_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00015_qntm_alpha.png
new file mode 100644
index 0000000..23eb9e3
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_anim_00015_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00000_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00000_qntm_alpha.png
new file mode 100644
index 0000000..cd11e14
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_anim_00000_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00001_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00001_qntm_alpha.png
new file mode 100644
index 0000000..b10db83
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_anim_00001_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00002_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00002_qntm_alpha.png
new file mode 100644
index 0000000..efeb6fb
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_anim_00002_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00003_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00003_qntm_alpha.png
new file mode 100644
index 0000000..83080af
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_anim_00003_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00004_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00004_qntm_alpha.png
new file mode 100644
index 0000000..b9cc322
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_anim_00004_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00005_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00005_qntm_alpha.png
new file mode 100644
index 0000000..3b5f9c4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_anim_00005_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00006_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00006_qntm_alpha.png
new file mode 100644
index 0000000..58c93db
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_anim_00006_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00007_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00007_qntm_alpha.png
new file mode 100644
index 0000000..0f1d010
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_anim_00007_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00008_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00008_qntm_alpha.png
new file mode 100644
index 0000000..05a7a0f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_anim_00008_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00009_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00009_qntm_alpha.png
new file mode 100644
index 0000000..9345035
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_anim_00009_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00010_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00010_qntm_alpha.png
new file mode 100644
index 0000000..5f149b7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_anim_00010_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00011_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00011_qntm_alpha.png
new file mode 100644
index 0000000..191f369
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_anim_00011_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00012_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00012_qntm_alpha.png
new file mode 100644
index 0000000..44e08e6
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_anim_00012_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00013_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00013_qntm_alpha.png
new file mode 100644
index 0000000..5a9dfa0
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_anim_00013_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00014_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00014_qntm_alpha.png
new file mode 100644
index 0000000..ee921c6
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_anim_00014_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00015_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00015_qntm_alpha.png
new file mode 100644
index 0000000..567bb0c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_anim_00015_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00000_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00000_qntm_alpha.png
new file mode 100644
index 0000000..1881f54
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_anim_00000_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00001_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00001_qntm_alpha.png
new file mode 100644
index 0000000..6f8ec2d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_anim_00001_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00002_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00002_qntm_alpha.png
new file mode 100644
index 0000000..c954ed9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_anim_00002_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00003_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00003_qntm_alpha.png
new file mode 100644
index 0000000..9d1a47e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_anim_00003_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00004_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00004_qntm_alpha.png
new file mode 100644
index 0000000..ce63631
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_anim_00004_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00005_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00005_qntm_alpha.png
new file mode 100644
index 0000000..430c134
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_anim_00005_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00006_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00006_qntm_alpha.png
new file mode 100644
index 0000000..cdebf83
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_anim_00006_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00007_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00007_qntm_alpha.png
new file mode 100644
index 0000000..40ceadb
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_anim_00007_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00008_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00008_qntm_alpha.png
new file mode 100644
index 0000000..fb13eb2
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_anim_00008_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00009_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00009_qntm_alpha.png
new file mode 100644
index 0000000..d716fba
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_anim_00009_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00010_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00010_qntm_alpha.png
new file mode 100644
index 0000000..b8be041
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_anim_00010_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00011_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00011_qntm_alpha.png
new file mode 100644
index 0000000..bad0c3c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_anim_00011_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00012_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00012_qntm_alpha.png
new file mode 100644
index 0000000..a6368fb
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_anim_00012_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00013_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00013_qntm_alpha.png
new file mode 100644
index 0000000..234e5d1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_anim_00013_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00014_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00014_qntm_alpha.png
new file mode 100644
index 0000000..3e7796d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_anim_00014_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00015_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00015_qntm_alpha.png
new file mode 100644
index 0000000..0673999
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_anim_00015_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_anim_00000_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_anim_00000_qntm_alpha.png
new file mode 100644
index 0000000..4779944
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_anim_00000_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_anim_00001_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_anim_00001_qntm_alpha.png
new file mode 100644
index 0000000..866f7b7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_anim_00001_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_anim_00002_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_anim_00002_qntm_alpha.png
new file mode 100644
index 0000000..76aae57
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_anim_00002_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_anim_00003_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_anim_00003_qntm_alpha.png
new file mode 100644
index 0000000..0cd470a1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_anim_00003_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_anim_00004_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_anim_00004_qntm_alpha.png
new file mode 100644
index 0000000..0015b39
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_anim_00004_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_anim_00005_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_anim_00005_qntm_alpha.png
new file mode 100644
index 0000000..2f69f5b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_anim_00005_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_anim_00006_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_anim_00006_qntm_alpha.png
new file mode 100644
index 0000000..77142fd
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_anim_00006_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_anim_00007_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_anim_00007_qntm_alpha.png
new file mode 100644
index 0000000..2f81277
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_anim_00007_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_anim_00008_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_anim_00008_qntm_alpha.png
new file mode 100644
index 0000000..d37fe60
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_anim_00008_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_anim_00009_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_anim_00009_qntm_alpha.png
new file mode 100644
index 0000000..cb62079
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_anim_00009_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_anim_00010_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_anim_00010_qntm_alpha.png
new file mode 100644
index 0000000..82dc428
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_anim_00010_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_anim_00011_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_anim_00011_qntm_alpha.png
new file mode 100644
index 0000000..2cba2fb
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_anim_00011_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_anim_00012_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_anim_00012_qntm_alpha.png
new file mode 100644
index 0000000..5de1952
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_anim_00012_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_anim_00013_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_anim_00013_qntm_alpha.png
new file mode 100644
index 0000000..1c22a17
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_anim_00013_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_anim_00014_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_anim_00014_qntm_alpha.png
new file mode 100644
index 0000000..7f652fc
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_anim_00014_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_anim_00015_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_anim_00015_qntm_alpha.png
new file mode 100644
index 0000000..076acbd
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_anim_00015_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable/btn_check_quantum_anim.xml b/core/res/res/drawable/btn_check_quantum_anim.xml
index 4b329ad..96715a4 100644
--- a/core/res/res/drawable/btn_check_quantum_anim.xml
+++ b/core/res/res/drawable/btn_check_quantum_anim.xml
@@ -1,3 +1,4 @@
+<?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");
@@ -13,21 +14,92 @@
      limitations under the License.
 -->
 
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:versionCode="1" >
+<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:state_checked="true">
+        <bitmap android:src="@drawable/btn_check_anim_00015_qntm_alpha"
+            android:tint="?attr/colorControlActivated"
+            android:alpha="?attr/disabledAlpha" />
+    </item>
+    <item android:state_enabled="false">
+        <bitmap android:src="@drawable/btn_check_anim_00000_qntm_alpha"
+            android:tint="?attr/colorControlNormal"
+            android:alpha="?attr/disabledAlpha" />
+    </item>
+    <item android:state_checked="true" android:id="@+id/on">
+        <bitmap android:src="@drawable/btn_check_anim_00015_qntm_alpha"
+            android:tint="?attr/colorControlActivated" />
+    </item>
+    <item android:id="@+id/off">
+        <bitmap android:src="@drawable/btn_check_anim_00000_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+    <transition android:fromId="@+id/off" android:toId="@+id/on" android:reversible="true">
+        <animation-list>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_check_anim_00000_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_check_anim_00001_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_check_anim_00002_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_check_anim_00003_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_check_anim_00004_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_check_anim_00005_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_check_anim_00006_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_check_anim_00007_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_check_anim_00008_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_check_anim_00009_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_check_anim_00010_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_check_anim_00011_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_check_anim_00012_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_check_anim_00013_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_check_anim_00014_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_check_anim_00015_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+        </animation-list>
+    </transition>
+</animated-selector>
 
-    <size
-        android:height="32dp"
-        android:width="32dp" />
-
-    <viewport
-        android:viewportHeight="320"
-        android:viewportWidth="320" />
-
-    <group>
-        <path
-            android:name="check"
-            android:pathData="M 232.1,80.6 L 248.5,92.1 L 145.2,239.5 L 71.5,187.8 L 83,171.5 L 140.3,211.7 z"
-            android:fill="?attr/colorControlActivated" />
-    </group>
-</vector>
diff --git a/core/res/res/drawable/btn_radio_quantum_anim.xml b/core/res/res/drawable/btn_radio_quantum_anim.xml
new file mode 100644
index 0000000..5068b7a
--- /dev/null
+++ b/core/res/res/drawable/btn_radio_quantum_anim.xml
@@ -0,0 +1,104 @@
+<?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.
+-->
+
+<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:state_checked="true">
+        <bitmap android:src="@drawable/btn_radio_anim_00015_qntm_alpha"
+            android:tint="?attr/colorControlActivated"
+            android:alpha="?attr/disabledAlpha" />
+    </item>
+    <item android:state_enabled="false">
+        <bitmap android:src="@drawable/btn_radio_anim_00000_qntm_alpha"
+            android:tint="?attr/colorControlNormal"
+            android:alpha="?attr/disabledAlpha" />
+    </item>
+    <item android:state_checked="true" android:id="@+id/on">
+        <bitmap android:src="@drawable/btn_radio_anim_00015_qntm_alpha"
+            android:tint="?attr/colorControlActivated" />
+    </item>
+    <item android:id="@+id/off">
+        <bitmap android:src="@drawable/btn_radio_anim_00000_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+    <transition android:fromId="@+id/off" android:toId="@+id/on" android:reversible="true">
+        <animation-list>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_radio_anim_00000_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_radio_anim_00001_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_radio_anim_00002_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_radio_anim_00003_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_radio_anim_00004_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_radio_anim_00005_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_radio_anim_00006_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_radio_anim_00007_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_radio_anim_00008_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_radio_anim_00009_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_radio_anim_00010_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_radio_anim_00011_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_radio_anim_00012_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_radio_anim_00013_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_radio_anim_00014_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+            <item android:duration="33">
+                <bitmap android:src="@drawable/btn_radio_anim_00015_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+        </animation-list>
+    </transition>
+</animated-selector>
diff --git a/core/res/res/layout/alert_dialog_micro.xml b/core/res/res/layout/alert_dialog_micro.xml
index f8eb46c..abdbd16 100644
--- a/core/res/res/layout/alert_dialog_micro.xml
+++ b/core/res/res/layout/alert_dialog_micro.xml
@@ -20,6 +20,8 @@
     android:id="@+id/parentPanel"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
+    android:background="@android:color/white"
+    android:layout_gravity="center"
     android:orientation="vertical">
 
     <LinearLayout android:id="@+id/topPanel"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d9473ec..28e75e6 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4239,6 +4239,58 @@
         <attr name="autoMirrored"/>
     </declare-styleable>
 
+    <!-- Drawable used to render several states with animated transitions. Each state
+         is represented by a child drawable with an optional keyframe ID. -->
+    <declare-styleable name="AnimatedStateListDrawable">
+        <!-- Indicates whether the drawable should be initially visible. -->
+        <attr name="visible" />
+        <!-- If true, allows the drawable's padding to change based on the
+             current state that is selected.  If false, the padding will
+             stay the same (based on the maximum padding of all the states).
+             Enabling this feature requires that the owner of the drawable
+             deal with performing layout when the state changes, which is
+             often not supported. -->
+        <attr name="variablePadding" />
+        <!-- If true, the drawable's reported internal size will remain
+             constant as the state changes; the size is the maximum of all
+             of the states.  If false, the size will vary based on the
+             current state. -->
+        <attr name="constantSize" />
+        <!-- Enables or disables dithering of the bitmap if the bitmap does not have the
+             same pixel configuration as the screen (for instance: a ARGB 8888 bitmap with
+             an RGB 565 screen). -->
+        <attr name="dither" />
+        <!-- Amount of time (in milliseconds) to fade in a new state drawable. -->
+        <attr name="enterFadeDuration" />
+        <!-- Amount of time (in milliseconds) to fade out an old state drawable. -->
+        <attr name="exitFadeDuration" />
+        <!-- Indicates if the drawable needs to be mirrored when its layout direction is
+             RTL (right-to-left). -->
+        <attr name="autoMirrored"/>
+    </declare-styleable>
+
+    <!-- Transition used to animate between states with keyframe IDs. -->
+    <declare-styleable name="AnimatedStateListDrawableItem">
+        <!-- Reference to a drawable resource to use for the frame.  If not
+             given, the drawable must be defined by the first child tag. -->
+        <attr name="drawable" />
+        <!-- Keyframe identifier for use in specifying transitions. -->
+        <attr name="id" />
+    </declare-styleable>
+
+    <!-- Transition used to animate between states with keyframe IDs. -->
+    <declare-styleable name="AnimatedStateListDrawableTransition">
+        <!-- Keyframe identifier for the starting state. -->
+        <attr name="fromId" format="reference" />
+        <!-- Keyframe identifier for the ending state. -->
+        <attr name="toId" format="reference" />
+        <!-- Reference to a animation drawable resource to use for the frame.  If not
+             given, the animation drawable must be defined by the first child tag. -->
+        <attr name="drawable" />
+        <!-- Whether this transition is reversible. -->
+        <attr name="reversible" format="boolean" />
+    </declare-styleable>
+
     <!-- Drawable used to render several animated frames. -->
     <declare-styleable name="AnimationDrawable">
         <attr name="visible" />
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 6b2c788..bf92f9b 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -143,6 +143,8 @@
     <!-- Preferred width of the search view. -->
     <dimen name="search_view_preferred_width">320dip</dimen>
 
+    <!-- Dialog padding for round display -->
+    <dimen name="alert_dialog_round_padding">27dip</dimen>
     <!-- Dialog title height -->
     <dimen name="alert_dialog_title_height">64dip</dimen>
     <!-- Dialog button bar height -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 4e584c0..ecb22ae 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2166,6 +2166,9 @@
   <public type="attr" name="documentLaunchMode" />
   <public type="attr" name="autoRemoveFromRecents" />
   <public type="attr" name="stateListAnimator" />
+  <public type="attr" name="toId" />
+  <public type="attr" name="fromId" />
+  <public type="attr" name="reversible" />
 
   <public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
 
diff --git a/core/res/res/values/styles_micro.xml b/core/res/res/values/styles_micro.xml
index bdaa49d..5bac1f9 100644
--- a/core/res/res/values/styles_micro.xml
+++ b/core/res/res/values/styles_micro.xml
@@ -15,6 +15,16 @@
 -->
 <resources>
     <style name="AlertDialog.Micro" parent="AlertDialog.Holo.Light">
+        <item name="fullDark">@null</item>
+        <item name="topDark">@null</item>
+        <item name="centerDark">@null</item>
+        <item name="bottomDark">@null</item>
+        <item name="fullBright">@null</item>
+        <item name="topBright">@null</item>
+        <item name="centerBright">@null</item>
+        <item name="bottomBright">@null</item>
+        <item name="bottomMedium">@null</item>
+        <item name="centerMedium">@null</item>
         <item name="layout">@layout/alert_dialog_micro</item>
     </style>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 2bf72e8..5a78bfe 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -120,6 +120,7 @@
   <java-symbol type="id" name="overlay_display_window_title" />
   <java-symbol type="id" name="package_label" />
   <java-symbol type="id" name="packages_list" />
+  <java-symbol type="id" name="parentPanel" />
   <java-symbol type="id" name="pause" />
   <java-symbol type="id" name="perms_list" />
   <java-symbol type="id" name="perm_icon" />
@@ -325,6 +326,7 @@
   <java-symbol type="color" name="tab_indicator_text_v4" />
 
   <java-symbol type="dimen" name="accessibility_touch_slop" />
+  <java-symbol type="dimen" name="alert_dialog_round_padding"/>
   <java-symbol type="dimen" name="config_prefDialogWidth" />
   <java-symbol type="dimen" name="config_viewConfigurationTouchSlop" />
   <java-symbol type="dimen" name="config_viewMinFlingVelocity" />
diff --git a/core/res/res/values/themes_micro.xml b/core/res/res/values/themes_micro.xml
index 39df700..9647947 100644
--- a/core/res/res/values/themes_micro.xml
+++ b/core/res/res/values/themes_micro.xml
@@ -47,10 +47,15 @@
         <item name="textAppearanceInverse">@style/TextAppearance.Micro</item>
     </style>
 
-    <style name="Theme.Micro.Dialog.Alert" parent="Theme.Holo.Light.Dialog.Alert">
+    <style name="Theme.Micro.Dialog.Alert">
         <item name="windowTitleStyle">@style/DialogWindowTitle.Micro</item>
         <item name="alertDialogStyle">@style/AlertDialog.Micro</item>
         <item name="windowIsFloating">false</item>
+        <item name="windowBackground">@android:color/transparent</item>
+        <item name="windowOverscan">true</item>
+        <item name="windowContentOverlay">@null</item>
+        <item name="android:windowMinWidthMajor">@android:dimen/dialog_min_width_major</item>
+        <item name="android:windowMinWidthMinor">@android:dimen/dialog_min_width_minor</item>
     </style>
 
     <style name="Theme.Micro.Dialog.AppError" parent="Theme.Micro.Dialog">
diff --git a/core/res/res/values/themes_quantum.xml b/core/res/res/values/themes_quantum.xml
index 768fd9a..18d6f80 100644
--- a/core/res/res/values/themes_quantum.xml
+++ b/core/res/res/values/themes_quantum.xml
@@ -122,8 +122,8 @@
         <item name="listDivider">@drawable/list_divider_quantum</item>
         <item name="listSeparatorTextViewStyle">@style/Widget.Quantum.TextView.ListSeparator</item>
 
-        <item name="listChoiceIndicatorSingle">@drawable/btn_radio_quantum</item>
-        <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum</item>
+        <item name="listChoiceIndicatorSingle">@drawable/btn_radio_quantum_anim</item>
+        <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum_anim</item>
 
         <item name="listChoiceBackgroundIndicator">@drawable/list_selector_quantum</item>
 
@@ -466,8 +466,8 @@
         <item name="listDivider">@drawable/list_divider_quantum</item>
         <item name="listSeparatorTextViewStyle">@style/Widget.Quantum.Light.TextView.ListSeparator</item>
 
-        <item name="listChoiceIndicatorSingle">@drawable/btn_radio_quantum</item>
-        <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum</item>
+        <item name="listChoiceIndicatorSingle">@drawable/btn_radio_quantum_anim</item>
+        <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum_anim</item>
 
         <item name="listChoiceBackgroundIndicator">@drawable/list_selector_quantum</item>
 
diff --git a/docs/html/guide/topics/ui/notifiers/notifications.jd b/docs/html/guide/topics/ui/notifiers/notifications.jd
index 3b1292e..59c2269 100644
--- a/docs/html/guide/topics/ui/notifiers/notifications.jd
+++ b/docs/html/guide/topics/ui/notifiers/notifications.jd
@@ -16,6 +16,7 @@
       <li><a href="#Required">Required notification contents</a></li>
       <li><a href="#Optional">Optional notification contents and settings</a></li>
       <li><a href="#Actions">Notification actions</a></li>
+      <li><a href="#Priority">Notification priority</a></li>
       <li><a href="#SimpleNotification">Creating a simple notification</a></li>
       <li><a href="#ApplyStyle">Applying a big view style to a notification</a></li>
       <li><a href="#Compatibility">Handling compatibility</a></li>
@@ -290,6 +291,26 @@
     {@link android.support.v4.app.NotificationCompat.Builder}.
 </p>
 <!-- ------------------------------------------------------------------------------------------ -->
+<h3 id="Priority">Notification priority</h3>
+<p>
+    If you wish, you can set the priority of a notification. The priority acts
+    as a hint to the device UI about how the notification should be displayed.
+    To set a notification's priority, call {@link
+    android.support.v4.app.NotificationCompat.Builder#setPriority(int)
+    NotificationCompat.Builder.setPriority()} and pass in one of the {@link
+    android.support.v4.app.NotificationCompat} priority constants. There are
+    five priority levels, ranging from {@link
+    android.support.v4.app.NotificationCompat#PRIORITY_MIN} (-2) to {@link
+    android.support.v4.app.NotificationCompat#PRIORITY_MAX} (2); if not set, the
+    priority defaults to {@link
+    android.support.v4.app.NotificationCompat#PRIORITY_DEFAULT} (0).
+</p>
+<p> For information about setting an appropriate priority level, see "Correctly
+    set and manage notification priority" in the <a
+    href="{@docRoot}design/patterns/notifications.html">Notifications</a> Design
+    guide.
+</p>
+<!-- ------------------------------------------------------------------------------------------ -->
 <h3 id="SimpleNotification">Creating a simple notification</h3>
 <p>
     The following snippet illustrates a simple notification that specifies an activity to open when
diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
new file mode 100644
index 0000000..46e3401
--- /dev/null
+++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
@@ -0,0 +1,524 @@
+/*
+ * 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.graphics.drawable;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.util.LongSparseLongArray;
+import android.util.SparseIntArray;
+import android.util.StateSet;
+
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+/**
+ * Drawable containing a set of Drawable keyframes where the currently displayed
+ * keyframe is chosen based on the current state set. Animations between
+ * keyframes may optionally be defined using transition elements.
+ * <p>
+ * This drawable can be defined in an XML file with the <code>
+ * &lt;animated-selector></code> element. Each keyframe Drawable is defined in a
+ * nested <code>&lt;item></code> element. Transitions are defined in a nested
+ * <code>&lt;transition></code> element.
+ *
+ * @attr ref android.R.styleable#DrawableStates_state_focused
+ * @attr ref android.R.styleable#DrawableStates_state_window_focused
+ * @attr ref android.R.styleable#DrawableStates_state_enabled
+ * @attr ref android.R.styleable#DrawableStates_state_checkable
+ * @attr ref android.R.styleable#DrawableStates_state_checked
+ * @attr ref android.R.styleable#DrawableStates_state_selected
+ * @attr ref android.R.styleable#DrawableStates_state_activated
+ * @attr ref android.R.styleable#DrawableStates_state_active
+ * @attr ref android.R.styleable#DrawableStates_state_single
+ * @attr ref android.R.styleable#DrawableStates_state_first
+ * @attr ref android.R.styleable#DrawableStates_state_middle
+ * @attr ref android.R.styleable#DrawableStates_state_last
+ * @attr ref android.R.styleable#DrawableStates_state_pressed
+ */
+public class AnimatedStateListDrawable extends StateListDrawable {
+    private static final String ELEMENT_TRANSITION = "transition";
+    private static final String ELEMENT_ITEM = "item";
+
+    private AnimatedStateListState mState;
+
+    /** The currently running animation, if any. */
+    private ObjectAnimator mAnim;
+
+    /** Index to be set after the animation ends. */
+    private int mAnimToIndex = -1;
+
+    /** Index away from which we are animating. */
+    private int mAnimFromIndex = -1;
+
+    private boolean mMutated;
+
+    public AnimatedStateListDrawable() {
+        this(null, null);
+    }
+
+    /**
+     * Add a new drawable to the set of keyframes.
+     *
+     * @param stateSet An array of resource IDs to associate with the keyframe
+     * @param drawable The drawable to show when in the specified state
+     * @param id The unique identifier for the keyframe
+     */
+    public void addState(int[] stateSet, Drawable drawable, int id) {
+        if (drawable != null) {
+            mState.addStateSet(stateSet, drawable, id);
+            onStateChange(getState());
+        }
+    }
+
+    /**
+     * Adds a new transition between keyframes.
+     *
+     * @param fromId Unique identifier of the starting keyframe
+     * @param toId Unique identifier of the ending keyframe
+     * @param anim An AnimationDrawable to use as a transition
+     * @param reversible Whether the transition can be reversed
+     */
+    public void addTransition(int fromId, int toId, AnimationDrawable anim, boolean reversible) {
+        mState.addTransition(fromId, toId, anim, reversible);
+    }
+
+    @Override
+    public boolean isStateful() {
+        return true;
+    }
+
+    @Override
+    protected boolean onStateChange(int[] stateSet) {
+        final int keyframeIndex = mState.indexOfKeyframe(stateSet);
+        if (keyframeIndex == getCurrentIndex()) {
+            return false;
+        }
+
+        if (selectTransition(keyframeIndex)) {
+            return true;
+        }
+
+        if (selectDrawable(keyframeIndex)) {
+            return true;
+        }
+
+        return super.onStateChange(stateSet);
+    }
+
+    private boolean selectTransition(int toIndex) {
+        if (mAnim != null) {
+            if (toIndex == mAnimToIndex) {
+                // Already animating to that keyframe.
+                return true;
+            } else if (toIndex == mAnimFromIndex) {
+                // Reverse the current animation.
+                mAnim.reverse();
+                mAnimFromIndex = mAnimToIndex;
+                mAnimToIndex = toIndex;
+                return true;
+            }
+
+            // Changing animation, end the current animation.
+            mAnim.end();
+        }
+
+        final AnimatedStateListState state = mState;
+        final int fromIndex = getCurrentIndex();
+        final int fromId = state.getKeyframeIdAt(fromIndex);
+        final int toId = state.getKeyframeIdAt(toIndex);
+
+        if (toId == 0 || fromId == 0) {
+            // Missing a keyframe ID.
+            return false;
+        }
+
+        final int transitionIndex = state.indexOfTransition(fromId, toId);
+        if (transitionIndex < 0 || !selectDrawable(transitionIndex)) {
+            // Couldn't select a transition.
+            return false;
+        }
+
+        final Drawable d = getCurrent();
+        if (!(d instanceof AnimationDrawable)) {
+            // Transition isn't an animation.
+            return false;
+        }
+
+        final AnimationDrawable ad = (AnimationDrawable) d;
+        final boolean reversed = mState.isTransitionReversed(fromId, toId);
+        final int frameCount = ad.getNumberOfFrames();
+        final int fromFrame = reversed ? frameCount - 1 : 0;
+        final int toFrame = reversed ? 0 : frameCount - 1;
+
+        final FrameInterpolator interp = new FrameInterpolator(ad, reversed);
+        final ObjectAnimator anim = ObjectAnimator.ofInt(ad, "currentIndex", fromFrame, toFrame);
+        anim.setAutoCancel(true);
+        anim.setDuration(interp.getTotalDuration());
+        anim.addListener(mAnimListener);
+        anim.setInterpolator(interp);
+        anim.start();
+
+        mAnim = anim;
+        mAnimFromIndex = fromIndex;
+        mAnimToIndex = toIndex;
+        return true;
+    }
+
+    @Override
+    public void jumpToCurrentState() {
+        super.jumpToCurrentState();
+
+        if (mAnim != null) {
+            mAnim.end();
+        }
+    }
+
+    @Override
+    public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
+            throws XmlPullParserException, IOException {
+        final TypedArray a = r.obtainAttributes(attrs, R.styleable.AnimatedStateListDrawable);
+
+        super.inflateWithAttributes(r, parser, a, R.styleable.AnimatedStateListDrawable_visible);
+
+        final StateListState stateListState = getStateListState();
+        stateListState.setVariablePadding(a.getBoolean(
+                R.styleable.AnimatedStateListDrawable_variablePadding, false));
+        stateListState.setConstantSize(a.getBoolean(
+                R.styleable.AnimatedStateListDrawable_constantSize, false));
+        stateListState.setEnterFadeDuration(a.getInt(
+                R.styleable.AnimatedStateListDrawable_enterFadeDuration, 0));
+        stateListState.setExitFadeDuration(a.getInt(
+                R.styleable.AnimatedStateListDrawable_exitFadeDuration, 0));
+
+        setDither(a.getBoolean(R.styleable.AnimatedStateListDrawable_dither, true));
+        setAutoMirrored(a.getBoolean(R.styleable.AnimatedStateListDrawable_autoMirrored, false));
+
+        a.recycle();
+
+        int type;
+
+        final int innerDepth = parser.getDepth() + 1;
+        int depth;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && ((depth = parser.getDepth()) >= innerDepth
+                || type != XmlPullParser.END_TAG)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+
+            if (depth > innerDepth) {
+                continue;
+            }
+
+            if (parser.getName().equals(ELEMENT_ITEM)) {
+                parseItem(r, parser, attrs, theme);
+            } else if (parser.getName().equals(ELEMENT_TRANSITION)) {
+                parseTransition(r, parser, attrs, theme);
+            }
+        }
+
+        onStateChange(getState());
+    }
+
+    private int parseTransition(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
+            throws XmlPullParserException, IOException {
+        int drawableRes = 0;
+        int fromId = 0;
+        int toId = 0;
+        boolean reversible = false;
+
+        final int numAttrs = attrs.getAttributeCount();
+        for (int i = 0; i < numAttrs; i++) {
+            final int stateResId = attrs.getAttributeNameResource(i);
+            switch (stateResId) {
+                case 0:
+                    break;
+                case R.attr.fromId:
+                    fromId = attrs.getAttributeResourceValue(i, 0);
+                    break;
+                case R.attr.toId:
+                    toId = attrs.getAttributeResourceValue(i, 0);
+                    break;
+                case R.attr.drawable:
+                    drawableRes = attrs.getAttributeResourceValue(i, 0);
+                    break;
+                case R.attr.reversible:
+                    reversible = attrs.getAttributeBooleanValue(i, false);
+                    break;
+            }
+        }
+
+        final Drawable dr;
+        if (drawableRes != 0) {
+            dr = r.getDrawable(drawableRes);
+        } else {
+            int type;
+            while ((type = parser.next()) == XmlPullParser.TEXT) {
+            }
+            if (type != XmlPullParser.START_TAG) {
+                throw new XmlPullParserException(
+                        parser.getPositionDescription()
+                                + ": <item> tag requires a 'drawable' attribute or "
+                                + "child tag defining a drawable");
+            }
+            dr = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme);
+        }
+
+        final AnimationDrawable anim;
+        if (dr instanceof AnimationDrawable) {
+            anim = (AnimationDrawable) dr;
+        } else {
+            throw new XmlPullParserException(parser.getPositionDescription()
+                    + ": <transition> tag requires a 'drawable' attribute or "
+                    + "child tag defining a drawable of type <animation>");
+        }
+
+        return mState.addTransition(fromId, toId, anim, reversible);
+    }
+
+    private int parseItem(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
+            throws XmlPullParserException, IOException {
+        int drawableRes = 0;
+        int keyframeId = 0;
+
+        int j = 0;
+        final int numAttrs = attrs.getAttributeCount();
+        int[] states = new int[numAttrs];
+        for (int i = 0; i < numAttrs; i++) {
+            final int stateResId = attrs.getAttributeNameResource(i);
+            switch (stateResId) {
+                case 0:
+                    break;
+                case R.attr.id:
+                    keyframeId = attrs.getAttributeResourceValue(i, 0);
+                    break;
+                case R.attr.drawable:
+                    drawableRes = attrs.getAttributeResourceValue(i, 0);
+                    break;
+                default:
+                    final boolean hasState = attrs.getAttributeBooleanValue(i, false);
+                    states[j++] = hasState ? stateResId : -stateResId;
+            }
+        }
+        states = StateSet.trimStateSet(states, j);
+
+        final Drawable dr;
+        if (drawableRes != 0) {
+            dr = r.getDrawable(drawableRes);
+        } else {
+            int type;
+            while ((type = parser.next()) == XmlPullParser.TEXT) {
+            }
+            if (type != XmlPullParser.START_TAG) {
+                throw new XmlPullParserException(
+                        parser.getPositionDescription()
+                                + ": <item> tag requires a 'drawable' attribute or "
+                                + "child tag defining a drawable");
+            }
+            dr = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme);
+        }
+
+        return mState.addStateSet(states, dr, keyframeId);
+    }
+
+    @Override
+    public Drawable mutate() {
+        if (!mMutated) {
+            final AnimatedStateListState newState = new AnimatedStateListState(mState, this, null);
+            setConstantState(newState);
+            mMutated = true;
+        }
+
+        return this;
+    }
+
+    private final AnimatorListenerAdapter mAnimListener = new AnimatorListenerAdapter() {
+        @Override
+        public void onAnimationEnd(Animator anim) {
+            selectDrawable(mAnimToIndex);
+
+            mAnimToIndex = -1;
+            mAnimFromIndex = -1;
+            mAnim = null;
+        }
+    };
+
+    static class AnimatedStateListState extends StateListState {
+        private static final int REVERSE_SHIFT = 32;
+        private static final int REVERSE_MASK = 0x1;
+
+        final LongSparseLongArray mTransitions;
+        final SparseIntArray mStateIds;
+
+        AnimatedStateListState(AnimatedStateListState orig, AnimatedStateListDrawable owner,
+                Resources res) {
+            super(orig, owner, res);
+
+            if (orig != null) {
+                mTransitions = orig.mTransitions.clone();
+                mStateIds = orig.mStateIds.clone();
+            } else {
+                mTransitions = new LongSparseLongArray();
+                mStateIds = new SparseIntArray();
+            }
+        }
+
+        int addTransition(int fromId, int toId, AnimationDrawable anim, boolean reversible) {
+            final int pos = super.addChild(anim);
+            final long keyFromTo = generateTransitionKey(fromId, toId);
+            mTransitions.append(keyFromTo, pos);
+
+            if (reversible) {
+                final long keyToFrom = generateTransitionKey(toId, fromId);
+                mTransitions.append(keyToFrom, pos | (1L << REVERSE_SHIFT));
+            }
+
+            return addChild(anim);
+        }
+
+        int addStateSet(int[] stateSet, Drawable drawable, int id) {
+            final int index = super.addStateSet(stateSet, drawable);
+            mStateIds.put(index, id);
+            return index;
+        }
+
+        int indexOfKeyframe(int[] stateSet) {
+            final int index = super.indexOfStateSet(stateSet);
+            if (index >= 0) {
+                return index;
+            }
+
+            return super.indexOfStateSet(StateSet.WILD_CARD);
+        }
+
+        int getKeyframeIdAt(int index) {
+            return index < 0 ? 0 : mStateIds.get(index, 0);
+        }
+
+        int indexOfTransition(int fromId, int toId) {
+            final long keyFromTo = generateTransitionKey(fromId, toId);
+            return (int) mTransitions.get(keyFromTo, -1);
+        }
+
+        boolean isTransitionReversed(int fromId, int toId) {
+            final long keyFromTo = generateTransitionKey(fromId, toId);
+            return (mTransitions.get(keyFromTo, -1) >> REVERSE_SHIFT & REVERSE_MASK) == 1;
+        }
+
+        @Override
+        public Drawable newDrawable() {
+            return new AnimatedStateListDrawable(this, null);
+        }
+
+        @Override
+        public Drawable newDrawable(Resources res) {
+            return new AnimatedStateListDrawable(this, res);
+        }
+
+        private static long generateTransitionKey(int fromId, int toId) {
+            return (long) fromId << 32 | toId;
+        }
+    }
+
+    void setConstantState(AnimatedStateListState state) {
+        super.setConstantState(state);
+
+        mState = state;
+    }
+
+    private AnimatedStateListDrawable(AnimatedStateListState state, Resources res) {
+        super(null);
+
+        final AnimatedStateListState newState = new AnimatedStateListState(state, this, res);
+        setConstantState(newState);
+        onStateChange(getState());
+        jumpToCurrentState();
+    }
+
+    /**
+     * Interpolates between frames with respect to their individual durations.
+     */
+    private static class FrameInterpolator implements TimeInterpolator {
+        private int[] mFrameTimes;
+        private int mFrames;
+        private int mTotalDuration;
+
+        public FrameInterpolator(AnimationDrawable d, boolean reversed) {
+            updateFrames(d, reversed);
+        }
+
+        public int updateFrames(AnimationDrawable d, boolean reversed) {
+            final int N = d.getNumberOfFrames();
+            mFrames = N;
+
+            if (mFrameTimes == null || mFrameTimes.length < N) {
+                mFrameTimes = new int[N];
+            }
+
+            final int[] frameTimes = mFrameTimes;
+            int totalDuration = 0;
+            for (int i = 0; i < N; i++) {
+                final int duration = d.getDuration(reversed ? N - i - 1 : i);
+                frameTimes[i] = duration;
+                totalDuration += duration;
+            }
+
+            mTotalDuration = totalDuration;
+            return totalDuration;
+        }
+
+        public int getTotalDuration() {
+            return mTotalDuration;
+        }
+
+        @Override
+        public float getInterpolation(float input) {
+            final int elapsed = (int) (input * mTotalDuration + 0.5f);
+            final int N = mFrames;
+            final int[] frameTimes = mFrameTimes;
+
+            // Find the current frame and remaining time within that frame.
+            int remaining = elapsed;
+            int i = 0;
+            while (i < N && remaining >= frameTimes[i]) {
+                remaining -= frameTimes[i];
+                i++;
+            }
+
+            // Remaining time is relative of total duration.
+            final float frameElapsed;
+            if (i < N) {
+                frameElapsed = remaining / (float) mTotalDuration;
+            } else {
+                frameElapsed = 0;
+            }
+
+            return i / (float) N + frameElapsed;
+        }
+    }
+}
+
diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java
index 3f94e26..da4bc10 100644
--- a/graphics/java/android/graphics/drawable/AnimationDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java
@@ -94,7 +94,7 @@
         boolean changed = super.setVisible(visible, restart);
         if (visible) {
             if (changed || restart) {
-                setFrame(0, true, true);
+                setFrame(0, true, mCurFrame >= 0);
             }
         } else {
             unscheduleSelf(this);
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index b9d5e19..b939636 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -1039,6 +1039,8 @@
         final String name = parser.getName();
         if (name.equals("selector")) {
             drawable = new StateListDrawable();
+        } else if (name.equals("animated-selector")) {
+            drawable = new AnimatedStateListDrawable();
         } else if (name.equals("level-list")) {
             drawable = new LevelListDrawable();
         } else if (name.equals("layer-list")) {
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 1f8b51d..08fc99d 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -359,6 +359,16 @@
                 mDrawableContainerState.getOpacity();
     }
 
+    /** @hide */
+    public void setCurrentIndex(int index) {
+        selectDrawable(index);
+    }
+
+    /** @hide */
+    public int getCurrentIndex() {
+        return mCurIndex;
+    }
+
     public boolean selectDrawable(int idx) {
         if (idx == mCurIndex) {
             return false;
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index 271af2b..f22a063 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -55,8 +55,9 @@
  * @attr ref android.R.styleable#DrawableStates_state_pressed
  */
 public class StateListDrawable extends DrawableContainer {
+    private static final String TAG = StateListDrawable.class.getSimpleName();
+
     private static final boolean DEBUG = false;
-    private static final String TAG = "StateListDrawable";
 
     /**
      * To be proper, we should have a getter for dither (and alpha, etc.)
@@ -69,7 +70,8 @@
      * to improve the quality at negligible cost.
      */
     private static final boolean DEFAULT_DITHER = true;
-    private final StateListState mStateListState;
+
+    private StateListState mStateListState;
     private boolean mMutated;
 
     public StateListDrawable() {
@@ -274,7 +276,7 @@
         mStateListState.setLayoutDirection(layoutDirection);
     }
 
-    static final class StateListState extends DrawableContainerState {
+    static class StateListState extends DrawableContainerState {
         int[][] mStateSets;
 
         StateListState(StateListState orig, StateListDrawable owner, Resources res) {
@@ -293,7 +295,7 @@
             return pos;
         }
 
-        private int indexOfStateSet(int[] stateSet) {
+        int indexOfStateSet(int[] stateSet) {
             final int[][] stateSets = mStateSets;
             final int N = getChildCount();
             for (int i = 0; i < N; i++) {
@@ -323,11 +325,26 @@
         }
     }
 
+    void setConstantState(StateListState state) {
+        super.setConstantState(state);
+
+        mStateListState = state;
+    }
+
     private StateListDrawable(StateListState state, Resources res) {
-        StateListState as = new StateListState(state, this, res);
-        mStateListState = as;
-        setConstantState(as);
+        final StateListState newState = new StateListState(state, this, res);
+        setConstantState(newState);
         onStateChange(getState());
     }
+
+    /**
+     * This constructor exists so subclasses can avoid calling the default
+     * constructor and setting up a StateListDrawable-specific constant state.
+     */
+    StateListDrawable(StateListState state) {
+        if (state != null) {
+            setConstantState(state);
+        }
+    }
 }
 
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index c2ce6ed..2391e80 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -58,7 +58,7 @@
 
 void DisplayListRenderer::setViewport(int width, int height) {
     // TODO: DisplayListRenderer shouldn't have a projection matrix, as it should never be used
-    mViewProjMatrix.loadOrtho(0, width, height, 0, -1, 1);
+    mProjectionMatrix.loadOrtho(0, width, height, 0, -1, 1);
 
     initializeViewport(width, height);
 }
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 5a977c8..20b038d 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -171,7 +171,7 @@
 }
 
 void OpenGLRenderer::initViewport(int width, int height) {
-    mViewProjMatrix.loadOrtho(0, width, height, 0, -1, 1);
+    mProjectionMatrix.loadOrtho(0, width, height, 0, -1, 1);
 
     initializeViewport(width, height);
 }
@@ -628,7 +628,7 @@
     if (restoreOrtho) {
         const Rect& r = restored.viewport;
         glViewport(r.left, r.top, r.right, r.bottom);
-        mViewProjMatrix.load(removed.orthoMatrix); // TODO: should ortho be stored in 'restored'?
+        mProjectionMatrix.load(removed.orthoMatrix); // TODO: should ortho be stored in 'restored'?
     }
 
     if (restoreClip) {
@@ -854,7 +854,7 @@
     mSnapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom);
     mSnapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight());
     mSnapshot->height = bounds.getHeight();
-    mSnapshot->orthoMatrix.load(mViewProjMatrix);
+    mSnapshot->orthoMatrix.load(mProjectionMatrix);
 
     endTiling();
     debugOverdraw(false, false);
@@ -884,8 +884,7 @@
     // Change the ortho projection
     glViewport(0, 0, bounds.getWidth(), bounds.getHeight());
 
-    // TODO: determine best way to support 3d drawing within HW layers
-    mViewProjMatrix.loadOrtho(0.0f, bounds.getWidth(), bounds.getHeight(), 0.0f, -1.0f, 1.0f);
+    mProjectionMatrix.loadOrtho(0.0f, bounds.getWidth(), bounds.getHeight(), 0.0f, -1.0f, 1.0f);
 
     return true;
 }
@@ -1689,17 +1688,17 @@
 
 void OpenGLRenderer::setupDrawModelView(ModelViewMode mode, bool offset,
         float left, float top, float right, float bottom, bool ignoreTransform) {
-    mModelView.loadTranslate(left, top, 0.0f);
+    mModelViewMatrix.loadTranslate(left, top, 0.0f);
     if (mode == kModelViewMode_TranslateAndScale) {
-        mModelView.scale(right - left, bottom - top, 1.0f);
+        mModelViewMatrix.scale(right - left, bottom - top, 1.0f);
     }
 
     bool dirty = right - left > 0.0f && bottom - top > 0.0f;
     if (!ignoreTransform) {
-        mCaches.currentProgram->set(mViewProjMatrix, mModelView, *currentTransform(), offset);
+        mCaches.currentProgram->set(mProjectionMatrix, mModelViewMatrix, *currentTransform(), offset);
         if (dirty && mTrackDirtyRegions) dirtyLayer(left, top, right, bottom, *currentTransform());
     } else {
-        mCaches.currentProgram->set(mViewProjMatrix, mModelView, mat4::identity(), offset);
+        mCaches.currentProgram->set(mProjectionMatrix, mModelViewMatrix, mat4::identity(), offset);
         if (dirty && mTrackDirtyRegions) dirtyLayer(left, top, right, bottom);
     }
 }
@@ -1724,11 +1723,11 @@
             // compensate.
             mat4 modelViewWithoutTransform;
             modelViewWithoutTransform.loadInverse(*currentTransform());
-            modelViewWithoutTransform.multiply(mModelView);
-            mModelView.load(modelViewWithoutTransform);
+            modelViewWithoutTransform.multiply(mModelViewMatrix);
+            mModelViewMatrix.load(modelViewWithoutTransform);
         }
         mDrawModifiers.mShader->setupProgram(mCaches.currentProgram,
-                mModelView, *mSnapshot, &mTextureUnit);
+                mModelViewMatrix, *mSnapshot, &mTextureUnit);
     }
 }
 
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 1d46945..4f7f01e 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -930,8 +930,8 @@
      */
     Texture* getTexture(const SkBitmap* bitmap);
 
-    // Matrix used for view/projection in shaders
-    mat4 mViewProjMatrix;
+    // Ortho matrix used for projection in shaders
+    mat4 mProjectionMatrix;
 
     /**
      * Model-view matrix used to position/size objects
@@ -939,15 +939,15 @@
      * Stores operation-local modifications to the draw matrix that aren't incorporated into the
      * currentTransform().
      *
-     * If generated with kModelViewMode_Translate, the mModelView will reflect an x/y offset,
+     * If generated with kModelViewMode_Translate, mModelViewMatrix will reflect an x/y offset,
      * e.g. the offset in drawLayer(). If generated with kModelViewMode_TranslateAndScale,
-     * mModelView will reflect a translation and scale, e.g. the translation and scale required to
-     * make VBO 0 (a rect of (0,0,1,1)) scaled to match the x,y offset, and width/height of a
-     * bitmap.
+     * mModelViewMatrix will reflect a translation and scale, e.g. the translation and scale
+     * required to make VBO 0 (a rect of (0,0,1,1)) scaled to match the x,y offset, and width/height
+     * of a bitmap.
      *
      * Used as input to SkiaShader transformation.
      */
-    mat4 mModelView;
+    mat4 mModelViewMatrix;
 
     // State used to define the clipping region
     Rect mTilingClip;
diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp
index d22cb8a..08e9a1a 100644
--- a/libs/hwui/font/Font.cpp
+++ b/libs/hwui/font/Font.cpp
@@ -214,18 +214,28 @@
     int dstY = y + glyph->mBitmapTop;
 
     CacheTexture* cacheTexture = glyph->mCacheTexture;
-
-    uint32_t cacheWidth = cacheTexture->getWidth();
-    uint32_t startY = glyph->mStartY * cacheWidth;
-    uint32_t endY = startY + (glyph->mBitmapHeight * cacheWidth);
-
     PixelBuffer* pixelBuffer = cacheTexture->getPixelBuffer();
+
+    uint32_t formatSize = PixelBuffer::formatSize(pixelBuffer->getFormat());
+    uint32_t cacheWidth = cacheTexture->getWidth();
+    uint32_t srcStride = formatSize * cacheWidth;
+    uint32_t startY = glyph->mStartY * srcStride;
+    uint32_t endY = startY + (glyph->mBitmapHeight * srcStride);
+
     const uint8_t* cacheBuffer = pixelBuffer->map();
 
     for (uint32_t cacheY = startY, bitmapY = dstY * bitmapWidth; cacheY < endY;
-            cacheY += cacheWidth, bitmapY += bitmapWidth) {
-        memcpy(&bitmap[bitmapY + dstX], &cacheBuffer[cacheY + glyph->mStartX], glyph->mBitmapWidth);
+            cacheY += srcStride, bitmapY += bitmapWidth) {
+
+        if (formatSize == 1) {
+            memcpy(&bitmap[bitmapY + dstX], &cacheBuffer[cacheY + glyph->mStartX], glyph->mBitmapWidth);
+        } else {
+            for (uint32_t i = 0; i < glyph->mBitmapWidth; ++i) {
+                bitmap[bitmapY + dstX + i] = cacheBuffer[cacheY + (glyph->mStartX + i)*formatSize];
+            }
+        }
     }
+
 }
 
 void Font::drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset,
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 6b2a247..57274ee 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -37,7 +37,7 @@
     public static final int ENCODING_PCM_16BIT = 2;
     /** Audio data format: PCM 8 bit per sample. Not guaranteed to be supported by devices. */
     public static final int ENCODING_PCM_8BIT = 3;
-    /** @hide Candidate for public API */
+    /** Audio data format: single-precision floating-point per sample */
     public static final int ENCODING_PCM_FLOAT = 4;
 
     /** Invalid audio channel configuration */
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index dab6eed..1a64cff 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -42,7 +42,8 @@
  * The AudioTrack class manages and plays a single audio resource for Java applications.
  * It allows streaming of PCM audio buffers to the audio sink for playback. This is
  * achieved by "pushing" the data to the AudioTrack object using one of the
- *  {@link #write(byte[], int, int)} and {@link #write(short[], int, int)} methods.
+ *  {@link #write(byte[], int, int)}, {@link #write(short[], int, int)},
+ *  and {@link #write(float[], int, int, int)} methods.
  *
  * <p>An AudioTrack instance can operate under two modes: static or streaming.<br>
  * In Streaming mode, the application writes a continuous stream of data to the AudioTrack, using
@@ -72,7 +73,6 @@
  *
  * AudioTrack is not final and thus permits subclasses, but such use is not recommended.
  */
-// add {@link #write(float[], int, int)} when @hide removed
 public class AudioTrack
 {
     //---------------------------------------------------------
@@ -245,8 +245,8 @@
      * The encoding of the audio samples.
      * @see AudioFormat#ENCODING_PCM_8BIT
      * @see AudioFormat#ENCODING_PCM_16BIT
+     * @see AudioFormat#ENCODING_PCM_FLOAT
      */
-    // add @see AudioFormat#ENCODING_PCM_FLOAT when @hide removed
     private int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
     /**
      * Audio session ID
@@ -287,8 +287,9 @@
      *   See {@link AudioFormat#CHANNEL_OUT_MONO} and
      *   {@link AudioFormat#CHANNEL_OUT_STEREO}
      * @param audioFormat the format in which the audio data is represented.
-     *   See {@link AudioFormat#ENCODING_PCM_16BIT} and
-     *   {@link AudioFormat#ENCODING_PCM_8BIT}
+     *   See {@link AudioFormat#ENCODING_PCM_16BIT},
+     *   {@link AudioFormat#ENCODING_PCM_8BIT},
+     *   and {@link AudioFormat#ENCODING_PCM_FLOAT}.
      * @param bufferSizeInBytes the total size (in bytes) of the internal buffer where audio data is
      *   read from for playback.
      *   If track's creation mode is {@link #MODE_STREAM}, you can write data into
@@ -302,7 +303,6 @@
      * @param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM}
      * @throws java.lang.IllegalArgumentException
      */
-    // add {@link AudioFormat#ENCODING_PCM_FLOAT} to audioFormat section above, when @hide removed
     public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
             int bufferSizeInBytes, int mode)
     throws IllegalArgumentException {
@@ -332,7 +332,8 @@
      *   {@link AudioFormat#CHANNEL_OUT_STEREO}
      * @param audioFormat the format in which the audio data is represented.
      *   See {@link AudioFormat#ENCODING_PCM_16BIT} and
-     *   {@link AudioFormat#ENCODING_PCM_8BIT}
+     *   {@link AudioFormat#ENCODING_PCM_8BIT},
+     *   and {@link AudioFormat#ENCODING_PCM_FLOAT}.
      * @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is read
      *   from for playback. If using the AudioTrack in streaming mode, you can write data into
      *   this buffer in smaller chunks than this size. If using the AudioTrack in static mode,
@@ -344,7 +345,6 @@
      * @param sessionId Id of audio session the AudioTrack must be attached to
      * @throws java.lang.IllegalArgumentException
      */
-    // add {@link AudioFormat#ENCODING_PCM_FLOAT} to audioFormat section above, when @hide removed
     public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
             int bufferSizeInBytes, int mode, int sessionId)
     throws IllegalArgumentException {
@@ -469,7 +469,7 @@
         default:
             throw new IllegalArgumentException("Unsupported sample encoding."
                 + " Should be ENCODING_PCM_8BIT or ENCODING_PCM_16BIT"
-             // + " or ENCODING_PCM_FLOAT" when @hide removed
+                + " or ENCODING_PCM_FLOAT"
                 + ".");
         }
 
@@ -730,12 +730,12 @@
      *   {@link AudioFormat#CHANNEL_OUT_STEREO}
      * @param audioFormat the format in which the audio data is represented.
      *   See {@link AudioFormat#ENCODING_PCM_16BIT} and
-     *   {@link AudioFormat#ENCODING_PCM_8BIT}
+     *   {@link AudioFormat#ENCODING_PCM_8BIT},
+     *   and {@link AudioFormat#ENCODING_PCM_FLOAT}.
      * @return {@link #ERROR_BAD_VALUE} if an invalid parameter was passed,
      *   or {@link #ERROR} if unable to query for output properties,
      *   or the minimum buffer size expressed in bytes.
      */
-    // add {@link AudioFormat#ENCODING_PCM_FLOAT} to audioFormat section above, when @hide removed
     static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) {
         int channelCount = 0;
         switch(channelConfig) {
@@ -1259,7 +1259,6 @@
      * @return the number of floats that were written, or {@link #ERROR_INVALID_OPERATION}
      *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
      *    the parameters don't resolve to valid data and indexes.
-     * @hide candidate for public API
      */
     public int write(float[] audioData, int offsetInFloats, int sizeInFloats,
             @WriteMode int writeMode) {
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 115786c..34c55202 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -585,11 +585,63 @@
      * the codec. If you previously specified a surface when configuring this
      * video decoder you can optionally render the buffer.
      * @param index The index of a client-owned output buffer previously returned
-     *              in a call to {@link #dequeueOutputBuffer}.
+     *              from a call to {@link #dequeueOutputBuffer}.
      * @param render If a valid surface was specified when configuring the codec,
      *               passing true renders this output buffer to the surface.
      */
-    public native final void releaseOutputBuffer(int index, boolean render);
+    public final void releaseOutputBuffer(int index, boolean render) {
+        releaseOutputBuffer(index, render, false /* updatePTS */, 0 /* dummy */);
+    }
+
+    /**
+     * If you are done with a buffer, use this call to update its surface timestamp
+     * and return it to the codec to render it on the output surface. If you
+     * have not specified an output surface when configuring this video codec,
+     * this call will simply return the buffer to the codec.<p>
+     *
+     * The timestamp may have special meaning depending on the destination surface.
+     *
+     * <table>
+     * <tr><th>SurfaceView specifics</th></tr>
+     * <tr><td>
+     * If you render your buffer on a {@link android.view.SurfaceView},
+     * you can use the timestamp to render the buffer at a specific time (at the
+     * VSYNC at or after the buffer timestamp).  For this to work, the timestamp
+     * needs to be <i>reasonably close</i> to the current {@link System#nanoTime}.
+     * Currently, this is set as within one (1) second. A few notes:
+     *
+     * <ul>
+     * <li>the buffer will not be returned to the codec until the timestamp
+     * has passed and the buffer is no longer used by the {@link android.view.Surface}.
+     * <li>buffers are processed sequentially, so you may block subsequent buffers to
+     * be displayed on the {@link android.view.Surface}.  This is important if you
+     * want to react to user action, e.g. stop the video or seek.
+     * <li>if multiple buffers are sent to the {@link android.view.Surface} to be
+     * rendered at the same VSYNC, the last one will be shown, and the other ones
+     * will be dropped.
+     * <li>if the timestamp is <em>not</em> "reasonably close" to the current system
+     * time, the {@link android.view.Surface} will ignore the timestamp, and
+     * display the buffer at the earliest feasible time.  In this mode it will not
+     * drop frames.
+     * <li>for best performance and quality, call this method when you are about
+     * two VSYNCs' time before the desired render time.  For 60Hz displays, this is
+     * about 33 msec.
+     * </ul>
+     * </td></tr>
+     * </table>
+     *
+     * @param index The index of a client-owned output buffer previously returned
+     *              from a call to {@link #dequeueOutputBuffer}.
+     * @param renderTimestampNs The timestamp to associate with this buffer when
+     *              it is sent to the Surface.
+     */
+    public final void releaseOutputBuffer(int index, long renderTimestampNs) {
+        releaseOutputBuffer(
+                index, true /* render */, true /* updatePTS */, renderTimestampNs);
+    }
+
+    private native final void releaseOutputBuffer(
+            int index, boolean render, boolean updatePTS, long timeNs);
 
     /**
      * Signals end-of-stream on input.  Equivalent to submitting an empty buffer with
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index a710c03..4a7c096 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -260,7 +260,11 @@
     return OK;
 }
 
-status_t JMediaCodec::releaseOutputBuffer(size_t index, bool render) {
+status_t JMediaCodec::releaseOutputBuffer(
+        size_t index, bool render, bool updatePTS, int64_t timestampNs) {
+    if (updatePTS) {
+        return mCodec->renderOutputBufferAndRelease(index, timestampNs);
+    }
     return render
         ? mCodec->renderOutputBufferAndRelease(index)
         : mCodec->releaseOutputBuffer(index);
@@ -873,7 +877,8 @@
 }
 
 static void android_media_MediaCodec_releaseOutputBuffer(
-        JNIEnv *env, jobject thiz, jint index, jboolean render) {
+        JNIEnv *env, jobject thiz,
+        jint index, jboolean render, jboolean updatePTS, jlong timestampNs) {
     ALOGV("android_media_MediaCodec_renderOutputBufferAndRelease");
 
     sp<JMediaCodec> codec = getMediaCodec(env, thiz);
@@ -883,7 +888,7 @@
         return;
     }
 
-    status_t err = codec->releaseOutputBuffer(index, render);
+    status_t err = codec->releaseOutputBuffer(index, render, updatePTS, timestampNs);
 
     throwExceptionAsNecessary(env, err);
 }
@@ -1138,7 +1143,7 @@
     { "dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I",
       (void *)android_media_MediaCodec_dequeueOutputBuffer },
 
-    { "releaseOutputBuffer", "(IZ)V",
+    { "releaseOutputBuffer", "(IZZJ)V",
       (void *)android_media_MediaCodec_releaseOutputBuffer },
 
     { "signalEndOfInputStream", "()V",
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index 2f2ea96..bf9f4ea 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -79,7 +79,8 @@
     status_t dequeueOutputBuffer(
             JNIEnv *env, jobject bufferInfo, size_t *index, int64_t timeoutUs);
 
-    status_t releaseOutputBuffer(size_t index, bool render);
+    status_t releaseOutputBuffer(
+            size_t index, bool render, bool updatePTS, int64_t timestampNs);
 
     status_t signalEndOfInputStream();
 
diff --git a/packages/Keyguard/res/layout/keyguard_status_view.xml b/packages/Keyguard/res/layout/keyguard_status_view.xml
index 546ddd4..0d943ed 100644
--- a/packages/Keyguard/res/layout/keyguard_status_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_status_view.xml
@@ -28,7 +28,7 @@
     androidprv:layout_maxWidth="@dimen/keyguard_security_width"
     androidprv:layout_maxHeight="@dimen/keyguard_security_height"
     android:gravity="center_horizontal|top"
-    android:layout_marginTop="32dp"
+    android:layout_marginTop="48dp"
     android:layout_marginBottom="32dp"
     android:contentDescription="@string/keyguard_accessibility_status">
     <LinearLayout
diff --git a/packages/SystemUI/res/drawable/notification_header_bg.xml b/packages/SystemUI/res/drawable/notification_header_bg.xml
index c5ba18b..b6b2e9a 100644
--- a/packages/SystemUI/res/drawable/notification_header_bg.xml
+++ b/packages/SystemUI/res/drawable/notification_header_bg.xml
@@ -24,7 +24,7 @@
     </item>
     <item>
         <shape>
-            <solid android:color="#ff374248" />
+            <solid android:color="#ff384248" />
             <corners android:radius="@*android:dimen/notification_quantum_rounded_rect_radius" />
         </shape>
     </item>
diff --git a/packages/SystemUI/res/layout/heads_up.xml b/packages/SystemUI/res/layout/heads_up.xml
index 7d9cfa1..e4954e7 100644
--- a/packages/SystemUI/res/layout/heads_up.xml
+++ b/packages/SystemUI/res/layout/heads_up.xml
@@ -20,7 +20,7 @@
 <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:layout_width="@dimen/notification_panel_width"
         android:id="@+id/content_holder"
         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 1b35537..585658e 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -77,26 +77,24 @@
         <LinearLayout android:id="@+id/system_icon_area"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
-            android:orientation="horizontal">
-
-            <LinearLayout android:id="@+id/statusIcons"
+            android:orientation="horizontal"
+            >
+            <LinearLayout android:id="@+id/system_icons"
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
                 android:gravity="center_vertical"
-                android:orientation="horizontal"/>    
-    
-            <LinearLayout
-                android:id="@+id/signal_battery_cluster"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
-                android:paddingStart="2dp"
-                android:orientation="horizontal"
-                android:gravity="center"
                 >
-                <include layout="@layout/signal_cluster_view" 
+                <LinearLayout android:id="@+id/statusIcons"
+                    android:layout_width="wrap_content"
+                    android:layout_height="match_parent"
+                    android:gravity="center_vertical"
+                    android:orientation="horizontal"/>
+
+                <include layout="@layout/signal_cluster_view"
                     android:id="@+id/signal_cluster"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
+                    android:layout_marginStart="2dp"
                     />
                 <!-- battery must be padded below to match assets -->
                 <com.android.systemui.BatteryMeterView
@@ -107,7 +105,6 @@
                     android:layout_marginStart="4dip"
                     />
             </LinearLayout>
-    
             <com.android.systemui.statusbar.policy.Clock
                 android:id="@+id/clock"
                 android:textAppearance="@style/TextAppearance.StatusBar.Clock"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 5b3f365..d36f692 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -22,7 +22,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
     android:id="@+id/notification_panel"
-    android:layout_width="match_parent"
+    android:layout_width="0dp"
     android:layout_height="match_parent"
     >
 
@@ -34,15 +34,6 @@
         android:layout_gravity="bottom"
         />
 
-    <com.android.keyguard.CarrierText
-        android:id="@+id/keyguard_carrier_text"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="2dp"
-        android:layout_marginLeft="8dp"
-        android:ellipsize="marquee"
-        android:textAppearance="?android:attr/textAppearanceMedium" />
-
     <include
         layout="@layout/keyguard_status_view"
         android:layout_height="wrap_content"
@@ -61,7 +52,7 @@
     <com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer
         android:id="@+id/notification_container_parent"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
+        android:layout_height="wrap_content"
         android:clipToPadding="false"
         android:clipChildren="false">
 
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index adfa1e4..ac81e4e 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -65,6 +65,21 @@
             />
     </RelativeLayout>
 
+    <com.android.keyguard.CarrierText
+        android:id="@+id/keyguard_carrier_text"
+        android:layout_width="wrap_content"
+        android:layout_height="@dimen/status_bar_header_height_keyguard"
+        android:layout_marginLeft="8dp"
+        android:gravity="center_vertical"
+        android:ellipsize="marquee"
+        android:textAppearance="?android:attr/textAppearanceMedium" />
+
+    <FrameLayout android:id="@+id/system_icons_container"
+        android:layout_width="wrap_content"
+        android:layout_height="@dimen/status_bar_header_height"
+        android:layout_alignParentEnd="true"
+        android:layout_marginEnd="16dp"
+        />
     <TextView
         android:id="@+id/header_debug_info"
         android:visibility="invisible"
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index c29da18..e95f3c3 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -35,7 +35,10 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent" >
         <include layout="@layout/status_bar_expanded"
-            style="@style/StatusBarExpanded" />
+            android:layout_width="@dimen/notification_panel_width"
+            android:layout_height="match_parent"
+            android:layout_gravity="start|top"
+            android:visibility="gone" />
     </com.android.systemui.statusbar.phone.PanelHolder>
 
 </com.android.systemui.statusbar.phone.StatusBarWindowView>
diff --git a/packages/SystemUI/res/values-sw600dp/styles.xml b/packages/SystemUI/res/values-sw600dp/styles.xml
index 1ea9442..b7becac 100644
--- a/packages/SystemUI/res/values-sw600dp/styles.xml
+++ b/packages/SystemUI/res/values-sw600dp/styles.xml
@@ -18,10 +18,4 @@
     <style name="BrightnessDialogContainer" parent="@style/BaseBrightnessDialogContainer">
         <item name="android:layout_width">480dp</item>
     </style>
-
-    <style name="StatusBarExpanded">
-        <item name="android:layout_width">@dimen/notification_panel_width</item>
-        <item name="android:layout_height">match_parent</item>
-        <item name="android:layout_gravity">start|top</item>
-    </style>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index b6e6ee2..7c68600 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -153,11 +153,14 @@
     <dimen name="close_handle_underlap">32dp</dimen>
 
     <!-- Height of the status bar header bar -->
-    <dimen name="status_bar_header_height">48dp</dimen>
+    <dimen name="status_bar_header_height">56dp</dimen>
 
     <!-- Height of the status bar header bar when expanded -->
     <dimen name="status_bar_header_height_expanded">144dp</dimen>
 
+    <!-- Height of the status bar header bar when on Keyguard -->
+    <dimen name="status_bar_header_height_keyguard">40dp</dimen>
+
     <!-- Gravity for the notification panel -->
     <!-- 0x37 = fill_horizontal|top -->
     <integer name="notification_panel_layout_gravity">0x37</integer>
@@ -196,6 +199,9 @@
     <!-- Quick Settings CA Cert Warning tile geometry: gap between icon and text -->
     <dimen name="qs_cawarn_tile_margin_below_icon">3dp</dimen>
 
+    <!-- The width of the notification panel window: match_parent below sw600dp -->
+    <dimen name="notification_panel_width">-1dp</dimen>
+
     <!-- used by DessertCase -->
     <dimen name="dessert_case_cell_size">192dp</dimen>
 
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 6608c5d..8ab646d 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -171,10 +171,4 @@
 
     <style name="systemui_theme" parent="@android:style/Theme.DeviceDefault" />
 
-    <style name="StatusBarExpanded">
-        <item name="android:layout_width">match_parent</item>
-        <item name="android:layout_height">match_parent</item>
-        <item name="android:layout_gravity">start|top</item>
-    </style>
-
 </resources>
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 377ef9c..c74911f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -24,9 +24,11 @@
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
+import android.widget.LinearLayout;
 
 import com.android.systemui.R;
 import com.android.systemui.statusbar.ExpandableView;
@@ -424,6 +426,34 @@
     }
 
     @Override
+    public void setVisibility(int visibility) {
+        int oldVisibility = getVisibility();
+        super.setVisibility(visibility);
+        if (visibility != oldVisibility) {
+            reparentStatusIcons(visibility == VISIBLE);
+        }
+    }
+
+    /**
+     * When the notification panel gets expanded, we need to move the status icons in the header
+     * card.
+     */
+    private void reparentStatusIcons(boolean toHeader) {
+        if (mStatusBar == null) {
+            return;
+        }
+        LinearLayout systemIcons = mStatusBar.getSystemIcons();
+        if (systemIcons.getParent() != null) {
+            ((ViewGroup) systemIcons.getParent()).removeView(systemIcons);
+        }
+        if (toHeader) {
+            mHeader.attachSystemIcons(systemIcons);
+        } else {
+            mStatusBar.reattachSystemIcons();
+        }
+    }
+
+    @Override
     protected boolean isScrolledToBottom() {
         if (!isInSettings()) {
             return mNotificationStackScroller.isScrolledToBottom();
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 fa31b33..dad858e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -29,7 +29,6 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
 import android.animation.TimeInterpolator;
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
@@ -205,6 +204,7 @@
 
     // right-hand icons
     LinearLayout mSystemIconArea;
+    LinearLayout mSystemIcons;
 
     // left-hand icons
     LinearLayout mStatusIcons;
@@ -230,7 +230,7 @@
     QuickSettingsContainerView mSettingsContainer;
 
     // top bar
-    View mNotificationPanelHeader;
+    StatusBarHeaderView mHeader;
     View mKeyguardStatusView;
     KeyguardBottomAreaView mKeyguardBottomArea;
     boolean mLeaveOpenOnKeyguardHide;
@@ -247,7 +247,6 @@
     private int mCarrierLabelHeight;
     private TextView mEmergencyCallLabel;
     private int mStatusBarHeaderHeight;
-    private View mKeyguardCarrierLabel;
 
     private boolean mShowCarrierInPanel = false;
 
@@ -607,6 +606,7 @@
         mPixelFormat = PixelFormat.OPAQUE;
 
         mSystemIconArea = (LinearLayout) mStatusBarView.findViewById(R.id.system_icon_area);
+        mSystemIcons = (LinearLayout) mStatusBarView.findViewById(R.id.system_icons);
         mStatusIcons = (LinearLayout)mStatusBarView.findViewById(R.id.statusIcons);
         mNotificationIcons = (IconMerger)mStatusBarView.findViewById(R.id.notificationIcons);
         mMoreIcon = mStatusBarView.findViewById(R.id.moreIcon);
@@ -625,13 +625,12 @@
                 (NotificationOverflowContainer) LayoutInflater.from(mContext).inflate(
                         R.layout.status_bar_notification_keyguard_overflow, mStackScroller, false);
         mKeyguardIconOverflowContainer.setOnActivatedListener(this);
-        mKeyguardCarrierLabel = mStatusBarWindow.findViewById(R.id.keyguard_carrier_text);
         mKeyguardIconOverflowContainer.setOnClickListener(mOverflowClickListener);
         mStackScroller.addView(mKeyguardIconOverflowContainer);
 
         mExpandedContents = mStackScroller;
 
-        mNotificationPanelHeader = mStatusBarWindow.findViewById(R.id.header);
+        mHeader = (StatusBarHeaderView) mStatusBarWindow.findViewById(R.id.header);
         mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);
         mKeyguardBottomArea =
                 (KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
@@ -640,7 +639,7 @@
                 R.id.keyguard_indication_text);
         mDateView = (DateView)mStatusBarWindow.findViewById(R.id.date);
 
-        mDateTimeView = mNotificationPanelHeader.findViewById(R.id.datetime);
+        mDateTimeView = mHeader.findViewById(R.id.datetime);
         if (mDateTimeView != null) {
             mDateTimeView.setOnClickListener(mClockClickListener);
             mDateTimeView.setEnabled(true);
@@ -2716,20 +2715,15 @@
             mKeyguardBottomArea.setVisibility(View.VISIBLE);
             mKeyguardIndicationTextView.setVisibility(View.VISIBLE);
             mKeyguardIndicationTextView.switchIndication(mKeyguardHotwordPhrase);
-            mKeyguardCarrierLabel.setVisibility(View.VISIBLE);
-            mNotificationPanelHeader.setVisibility(View.GONE);
 
             mNotificationPanel.closeQs();
-            mSettingsContainer.setKeyguardShowing(true);
         } else {
             mKeyguardStatusView.setVisibility(View.GONE);
             mKeyguardBottomArea.setVisibility(View.GONE);
             mKeyguardIndicationTextView.setVisibility(View.GONE);
-            mKeyguardCarrierLabel.setVisibility(View.GONE);
-            mNotificationPanelHeader.setVisibility(View.VISIBLE);
-
-            mSettingsContainer.setKeyguardShowing(false);
         }
+        mSettingsContainer.setKeyguardShowing(mState == StatusBarState.KEYGUARD);
+        mHeader.setKeyguardShowing(mState == StatusBarState.KEYGUARD);
 
         updateStackScrollerState();
         updatePublicMode();
@@ -2885,4 +2879,15 @@
     public ViewGroup getQuickSettingsOverlayParent() {
         return mNotificationPanel;
     }
+
+    public LinearLayout getSystemIcons() {
+        return mSystemIcons;
+    }
+
+    /**
+     * Reattaches the system icons to its normal parent in collapsed status bar.
+     */
+    public void reattachSystemIcons() {
+        mSystemIconArea.addView(mSystemIcons, 0);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
index 8406565..e941d54 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
@@ -44,12 +44,16 @@
 
     public void init() {
         mLeftSide = mView.findViewById(R.id.notification_icon_area);
+        initStatus();
+        applyModeBackground(-1, getMode(), false /*animate*/);
+        applyMode(getMode(), false /*animate*/);
+    }
+
+    private void initStatus() {
         mStatusIcons = mView.findViewById(R.id.statusIcons);
         mSignalCluster = mView.findViewById(R.id.signal_cluster);
         mBattery = mView.findViewById(R.id.battery);
         mClock = mView.findViewById(R.id.clock);
-        applyModeBackground(-1, getMode(), false /*animate*/);
-        applyMode(getMode(), false /*animate*/);
     }
 
     public ObjectAnimator animateTransitionTo(View v, float toAlpha) {
@@ -79,6 +83,8 @@
 
     private void applyMode(int mode, boolean animate) {
         if (mLeftSide == null) return; // pre-init
+        if (mStatusIcons == null) initStatus();
+        if (mStatusIcons == null) return;
         float newAlpha = getNonBatteryClockAlphaFor(mode);
         float newAlphaBC = getBatteryClockAlpha(mode);
         if (mCurrentAnimation != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index fd53d15..67487ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -32,9 +32,15 @@
 
     private boolean mExpanded;
     private View mBackground;
+    private ViewGroup mSystemIconsContainer;
+    private View mDateTime;
+    private View mKeyguardCarrierText;
 
     private int mCollapsedHeight;
     private int mExpandedHeight;
+    private int mKeyguardHeight;
+
+    private boolean mKeyguardShowing;
 
     public StatusBarHeaderView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -44,18 +50,22 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
         mBackground = findViewById(R.id.background);
+        mSystemIconsContainer = (ViewGroup) findViewById(R.id.system_icons_container);
+        mDateTime = findViewById(R.id.datetime);
+        mKeyguardCarrierText = findViewById(R.id.keyguard_carrier_text);
         loadDimens();
     }
 
     private void loadDimens() {
-        mCollapsedHeight = getResources().getDimensionPixelSize(
-                R.dimen.status_bar_header_height);
+        mCollapsedHeight = getResources().getDimensionPixelSize(R.dimen.status_bar_header_height);
         mExpandedHeight = getResources().getDimensionPixelSize(
                 R.dimen.status_bar_header_height_expanded);
+        mKeyguardHeight = getResources().getDimensionPixelSize(
+                R.dimen.status_bar_header_height_keyguard);
     }
 
     public int getCollapsedHeight() {
-        return mCollapsedHeight;
+        return mKeyguardShowing ? mKeyguardHeight : mCollapsedHeight;
     }
 
     public int getExpandedHeight() {
@@ -63,11 +73,29 @@
     }
 
     public void setExpanded(boolean expanded) {
-        if (expanded != mExpanded) {
-            ViewGroup.LayoutParams lp = getLayoutParams();
-            lp.height = expanded ? mExpandedHeight : mCollapsedHeight;
+        mExpanded = expanded;
+        updateHeights();
+    }
+
+    private void updateHeights() {
+        int height;
+        if (mExpanded) {
+            height = mExpandedHeight;
+        } else if (mKeyguardShowing) {
+            height = mKeyguardHeight;
+        } else {
+            height = mCollapsedHeight;
+        }
+        ViewGroup.LayoutParams lp = getLayoutParams();
+        if (lp.height != height) {
+            lp.height = height;
             setLayoutParams(lp);
-            mExpanded = expanded;
+        }
+        int systemIconsContainerHeight = mKeyguardShowing ? mKeyguardHeight : mCollapsedHeight;
+        lp = mSystemIconsContainer.getLayoutParams();
+        if (lp.height != systemIconsContainerHeight) {
+            lp.height = systemIconsContainerHeight;
+            mSystemIconsContainer.setLayoutParams(lp);
         }
     }
 
@@ -88,4 +116,21 @@
     public View getBackgroundView() {
         return mBackground;
     }
+
+    public void attachSystemIcons(LinearLayout systemIcons) {
+        mSystemIconsContainer.addView(systemIcons);
+    }
+
+    public void setKeyguardShowing(boolean keyguardShowing) {
+        mKeyguardShowing = keyguardShowing;
+        mBackground.setVisibility(keyguardShowing ? View.INVISIBLE : View.VISIBLE);
+        mDateTime.setVisibility(keyguardShowing ? View.INVISIBLE : View.VISIBLE);
+        mKeyguardCarrierText.setVisibility(keyguardShowing ? View.VISIBLE : View.GONE);
+        if (keyguardShowing) {
+            setZ(0);
+        } else {
+            setTranslationZ(0);
+        }
+        updateHeights();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index c2061f3..a4c9df5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -79,9 +79,8 @@
                         | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
                 PixelFormat.TRANSLUCENT);
 
-        mLp.width = ViewGroup.LayoutParams.MATCH_PARENT;
         mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
-        mLp.gravity = Gravity.TOP;
+        mLp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
         mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
         mLp.setTitle("StatusBar");
         mLp.packageName = mContext.getPackageName();
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index ea9de1e..82c13e0 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -360,8 +360,9 @@
     // Lock held on mVibrations
     private void startVibrationLocked(final Vibration vib) {
         try {
-            if (mLowPowerMode && vib.mStreamHint != AudioManager.STREAM_RING)
-                    return;
+            if (mLowPowerMode && vib.mStreamHint != AudioManager.STREAM_RING) {
+                return;
+            }
 
             int mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE,
                     vib.mStreamHint, vib.mUid, vib.mOpPkg);
@@ -443,7 +444,7 @@
                 }
 
                 mLowPowerMode = Settings.Global.getInt(mContext.getContentResolver(),
-                     Settings.Global.LOW_POWER_MODE, 0) != 0;
+                         Settings.Global.LOW_POWER_MODE, 0) != 0;
 
                 if (mVibrateInputDevicesSetting) {
                     if (!mInputDeviceListenerRegistered) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 9f6dd0b..5358c1a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -35,6 +35,7 @@
 import android.appwidget.AppWidgetManager;
 import android.graphics.Rect;
 import android.os.BatteryStats;
+import android.os.PersistableBundle;
 import android.service.voice.IVoiceInteractionSession;
 import android.util.ArrayMap;
 
@@ -5429,22 +5430,21 @@
     }
 
     @Override
-    public final void activityPaused(IBinder token) {
+    public final void activityPaused(IBinder token, PersistableBundle persistentState) {
         final long origId = Binder.clearCallingIdentity();
         synchronized(this) {
             ActivityStack stack = ActivityRecord.getStackLocked(token);
             if (stack != null) {
-                stack.activityPausedLocked(token, false);
+                stack.activityPausedLocked(token, false, persistentState);
             }
         }
         Binder.restoreCallingIdentity(origId);
     }
 
     @Override
-    public final void activityStopped(IBinder token, Bundle icicle, Bitmap thumbnail,
-            CharSequence description) {
-        if (localLOGV) Slog.v(
-            TAG, "Activity stopped: token=" + token);
+    public final void activityStopped(IBinder token, Bundle icicle,
+            PersistableBundle persistentState, CharSequence description) {
+        if (localLOGV) Slog.v(TAG, "Activity stopped: token=" + token);
 
         // Refuse possible leaked file descriptors
         if (icicle != null && icicle.hasFileDescriptors()) {
@@ -5456,7 +5456,7 @@
         synchronized (this) {
             ActivityRecord r = ActivityRecord.isInStackLocked(token);
             if (r != null) {
-                r.task.stack.activityStoppedLocked(r, icicle, thumbnail, description);
+                r.task.stack.activityStoppedLocked(r, icicle, persistentState, description);
             }
         }
 
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index efd2b57..8391f79 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import android.os.PersistableBundle;
 import android.os.Trace;
 import com.android.internal.app.ResolverActivity;
 import com.android.server.AttributeCache;
@@ -117,6 +118,7 @@
     ProcessRecord app;      // if non-null, hosting application
     ActivityState state;    // current state we are in
     Bundle  icicle;         // last saved activity state
+    PersistableBundle persistentState; // last persistently saved activity state
     boolean frontOfTask;    // is this the root activity of its task?
     boolean launchFailed;   // set if a launched failed, to abort on 2nd try
     boolean haveState;      // have we gotten the last activity state?
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 442da31..7c29d85 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -68,6 +68,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.Trace;
@@ -276,7 +277,7 @@
                         if (r.app != null) {
                             mService.logAppTooSlow(r.app, r.pauseTime, "pausing " + r);
                         }
-                        activityPausedLocked(r.appToken, true);
+                        activityPausedLocked(r.appToken, true, r.persistentState);
                     }
                 } break;
                 case LAUNCH_TICK_MSG: {
@@ -860,13 +861,15 @@
         }
     }
 
-    final void activityPausedLocked(IBinder token, boolean timeout) {
+    final void activityPausedLocked(IBinder token, boolean timeout,
+            PersistableBundle persistentState) {
         if (DEBUG_PAUSE) Slog.v(
             TAG, "Activity paused: token=" + token + ", timeout=" + timeout);
 
         final ActivityRecord r = isInStackLocked(token);
         if (r != null) {
             mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
+            r.persistentState = persistentState;
             if (mPausingActivity == r) {
                 if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r
                         + (timeout ? " (due to timeout)" : " (pause complete)"));
@@ -881,13 +884,14 @@
         }
     }
 
-    final void activityStoppedLocked(ActivityRecord r, Bundle icicle, Bitmap thumbnail,
-            CharSequence description) {
+    final void activityStoppedLocked(ActivityRecord r, Bundle icicle,
+            PersistableBundle persistentState, CharSequence description) {
         if (r.state != ActivityState.STOPPING) {
             Slog.i(TAG, "Activity reported stop, but no longer stopping: " + r);
             mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
             return;
         }
+        r.persistentState = persistentState;
         if (DEBUG_SAVED_STATE) Slog.i(TAG, "Saving icicle of " + r + ": " + icicle);
         if (icicle != null) {
             // If icicle is null, this is happening due to a timeout, so we
@@ -895,7 +899,7 @@
             r.icicle = icicle;
             r.haveState = true;
             r.launchCount = 0;
-            r.updateThumbnail(thumbnail, description);
+            r.updateThumbnail(null, description);
         }
         if (!r.stopped) {
             if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r + " (stop complete)");
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index ce3d853..6f62a03 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1026,10 +1026,10 @@
             r.clearOptionsLocked();
             app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                     System.identityHashCode(r), r.info,
-                    new Configuration(mService.mConfiguration), r.compat,
-                    r.task.voiceInteractor, app.repProcState, r.icicle, results, newIntents,
-                    !andResume, mService.isNextTransitionForward(), profileFile, profileFd,
-                    profileAutoStop, options);
+                    new Configuration(mService.mConfiguration), r.compat, r.task.voiceInteractor,
+                    app.repProcState, r.icicle, r.persistentState, results, newIntents, !andResume,
+                    mService.isNextTransitionForward(), profileFile, profileFd, profileAutoStop,
+                    options);
 
             if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
                 // This may be a heavy-weight process!  Note that the package
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 3ae0fd5..3d5fb57 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -518,6 +518,11 @@
                 // Brighten quickly.
                 slow = false;
             }
+            // If low power mode is enabled, brightness level
+            // would be scaled down to half
+            if (mPowerRequest.lowPowerMode) {
+                target = target/2;
+            }
             animateScreenBrightness(clampScreenBrightness(target),
                     slow ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);
         } else {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c8b61f1..a7f4b28 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -613,6 +613,12 @@
         private final AtomicLong mLastWritten = new AtomicLong(0);
         private final AtomicBoolean mBackgroundWriteRunning = new AtomicBoolean(false);
 
+        private boolean mIsFirstBoot = false;
+
+        boolean isFirstBoot() {
+            return mIsFirstBoot;
+        }
+
         void write(boolean force) {
             if (force) {
                 write();
@@ -701,6 +707,7 @@
                         pkg.mLastPackageUsageTimeInMills = timeInMillis;
                     }
                 } catch (FileNotFoundException expected) {
+                    mIsFirstBoot = true;
                 } catch (IOException e) {
                     Log.w(TAG, "Failed to read package usage times", e);
                 } finally {
@@ -1745,7 +1752,7 @@
 
     @Override
     public boolean isFirstBoot() {
-        return !mRestoredSettings;
+        return !mRestoredSettings || mPackageUsage.isFirstBoot();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 6d2e8592..47a8b2e 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -1634,6 +1634,8 @@
 
             mDisplayPowerRequest.blockScreenOn = mScreenOnBlocker.isHeld();
 
+            mDisplayPowerRequest.lowPowerMode = mLowPowerModeEnabled;
+
             mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
                     mRequestWaitForNegativeProximity);
             mRequestWaitForNegativeProximity = false;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 637beec..836a19c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -5038,6 +5038,10 @@
             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
         }
 
+        if (token == null) {
+            throw new IllegalArgumentException("token == null");
+        }
+
         mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
                 KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
     }
@@ -5049,6 +5053,10 @@
             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
         }
 
+        if (token == null) {
+            throw new IllegalArgumentException("token == null");
+        }
+
         mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
                 KeyguardDisableHandler.KEYGUARD_REENABLE, token));
     }
@@ -5062,6 +5070,11 @@
             != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
         }
+
+        if (callback == null) {
+            throw new IllegalArgumentException("callback == null");
+        }
+
         mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
             @Override
             public void onKeyguardExitResult(boolean success) {