Merge "Add flags word to initialization." into klp-dev
diff --git a/api/current.txt b/api/current.txt
index 78abd53..fe0fd6e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -22819,6 +22819,15 @@
     method public android.os.IBinder onBind(android.content.Intent);
     method public abstract void onStartHotwordRecognition(android.speech.hotword.HotwordRecognitionService.Callback);
     method public abstract void onStopHotwordRecognition();
+    field public static final int ERROR_AUDIO = 1; // 0x1
+    field public static final int ERROR_CLIENT = 4; // 0x4
+    field public static final int ERROR_FAILED = 3; // 0x3
+    field public static final int ERROR_RECOGNIZER_BUSY = 2; // 0x2
+    field public static final int ERROR_SERVICE_ALREADY_STARTED = 6; // 0x6
+    field public static final int ERROR_TIMEOUT = 5; // 0x5
+    field public static final int ERROR_UNAVAILABLE = 7; // 0x7
+    field public static final int EVENT_TYPE_PROMPT_CHANGED = 1; // 0x1
+    field public static final java.lang.String KEY_PROMPT_TEXT = "prompt_text";
     field public static final java.lang.String SERVICE_INTERFACE = "android.speech.hotword.HotwordRecognitionService";
   }
 
@@ -28372,6 +28381,7 @@
     method public android.view.ViewPropertyAnimator setInterpolator(android.animation.TimeInterpolator);
     method public android.view.ViewPropertyAnimator setListener(android.animation.Animator.AnimatorListener);
     method public android.view.ViewPropertyAnimator setStartDelay(long);
+    method public android.view.ViewPropertyAnimator setUpdateListener(android.animation.ValueAnimator.AnimatorUpdateListener);
     method public void start();
     method public android.view.ViewPropertyAnimator translationX(float);
     method public android.view.ViewPropertyAnimator translationXBy(float);
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 9f462aa..e914604 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1745,6 +1745,9 @@
      * @param extras any extras to pass to the SyncAdapter.
      */
     public static void requestSync(Account account, String authority, Bundle extras) {
+        if (extras == null) {
+            throw new IllegalArgumentException("Must specify extras.");
+        }
         SyncRequest request =
             new SyncRequest.Builder()
                 .setSyncAdapter(account, authority)
diff --git a/core/java/android/speech/hotword/HotwordRecognitionService.java b/core/java/android/speech/hotword/HotwordRecognitionService.java
index 7a26e0c..9a59f19 100644
--- a/core/java/android/speech/hotword/HotwordRecognitionService.java
+++ b/core/java/android/speech/hotword/HotwordRecognitionService.java
@@ -47,6 +47,39 @@
     /** Debugging flag */
     private static final boolean DBG = false;
 
+    /**
+     * Key used to retrieve a string to be displayed to the user passed to the
+     * {@link android.speech.hotword.HotwordRecognitionListener#onHotwordEvent(int, Bundle)} method.
+     */
+    public static final String KEY_PROMPT_TEXT = "prompt_text";
+
+    /**
+     * Event type used to indicate to the user that the prompt for
+     * hotword recognition has changed.
+     */
+    public static final int EVENT_TYPE_PROMPT_CHANGED = 1;
+
+    /** Audio recording error. */
+    public static final int ERROR_AUDIO = 1;
+
+    /** RecognitionService busy. */
+    public static final int ERROR_RECOGNIZER_BUSY = 2;
+
+    /** This indicates a permanent failure and the clients shouldn't retry on this */
+    public static final int ERROR_FAILED = 3;
+
+    /** Client-side errors */
+    public static final int ERROR_CLIENT = 4;
+
+    /** The service timed out */
+    public static final int ERROR_TIMEOUT = 5;
+
+    /** The service received concurrent start calls */
+    public static final int ERROR_SERVICE_ALREADY_STARTED = 6;
+
+    /** Hotword recognition is unavailable on the device */
+    public static final int ERROR_UNAVAILABLE = 7;
+
     private static final int MSG_START_RECOGNITION = 1;
     private static final int MSG_STOP_RECOGNITION = 2;
 
@@ -94,7 +127,7 @@
             HotwordRecognitionService.this.onStartHotwordRecognition(mCurrentCallback);
         } else {
             try {
-                listener.onHotwordError(HotwordRecognizer.ERROR_RECOGNIZER_BUSY);
+                listener.onHotwordError(ERROR_RECOGNIZER_BUSY);
             } catch (RemoteException e) {
                 if (DBG) Log.d(TAG, "onError call from startRecognition failed");
             }
@@ -105,10 +138,10 @@
     private void dispatchStopRecognition(IHotwordRecognitionListener listener) {
         try {
             if (mCurrentCallback == null) {
-                listener.onHotwordError(HotwordRecognizer.ERROR_CLIENT);
+                listener.onHotwordError(ERROR_CLIENT);
                 Log.w(TAG, "stopRecognition called with no preceding startRecognition - ignoring");
             } else if (mCurrentCallback.mListener.asBinder() != listener.asBinder()) {
-                listener.onHotwordError(HotwordRecognizer.ERROR_RECOGNIZER_BUSY);
+                listener.onHotwordError(ERROR_RECOGNIZER_BUSY);
                 Log.w(TAG, "stopRecognition called by a different caller - ignoring");
             } else { // the correct state
                 mCurrentCallback.onHotwordRecognitionStopped();
@@ -192,7 +225,7 @@
         }
         try {
             Log.e(TAG, "Recognition service called without HOTWORD_RECOGNITION permissions");
-            listener.onHotwordError(HotwordRecognizer.ERROR_FAILED);
+            listener.onHotwordError(ERROR_FAILED);
         } catch (RemoteException e) {
             Log.e(TAG, "onHotwordError(ERROR_FAILED) message failed", e);
         }
diff --git a/core/java/android/speech/hotword/HotwordRecognizer.java b/core/java/android/speech/hotword/HotwordRecognizer.java
index 939c11d..9f05f31 100644
--- a/core/java/android/speech/hotword/HotwordRecognizer.java
+++ b/core/java/android/speech/hotword/HotwordRecognizer.java
@@ -50,39 +50,6 @@
     /** Log messages identifier */
     private static final String TAG = "HotwordRecognizer";
 
-    /**
-     * Key used to retrieve a string to be displayed to the user passed to the
-     * {@link android.speech.hotword.HotwordRecognitionListener#onHotwordEvent(int, Bundle)} method.
-     */
-    public static final String PROMPT_TEXT = "prompt_text";
-
-    /**
-     * Event type used to indicate to the user that the hotword service has changed
-     * its state.
-     */
-    public static final int EVENT_TYPE_STATE_CHANGED = 1;
-
-    /** Audio recording error. */
-    public static final int ERROR_AUDIO = 1;
-
-    /** RecognitionService busy. */
-    public static final int ERROR_RECOGNIZER_BUSY = 2;
-
-    /** This indicates a permanent failure and the clients shouldn't retry on this */
-    public static final int ERROR_FAILED = 3;
-
-    /** Client-side errors */
-    public static final int ERROR_CLIENT = 4;
-
-    /** The service timed out */
-    public static final int ERROR_TIMEOUT = 5;
-
-    /** The service received concurrent start calls */
-    public static final int ERROR_SERVICE_ALREADY_STARTED = 6;
-
-    /** Hotword recognition is unavailable on the device */
-    public static final int ERROR_UNAVAILABLE = 7;
-
     /** action codes */
     private static final int MSG_START = 1;
     private static final int MSG_STOP = 2;
@@ -209,7 +176,7 @@
 
             if (mServiceComponent == null) {
                 Log.e(TAG, "no selected voice recognition service");
-                mListener.onHotwordError(ERROR_CLIENT);
+                mListener.onHotwordError(HotwordRecognitionService.ERROR_CLIENT);
                 return;
             } else {
                 serviceIntent.setComponent(mServiceComponent);
@@ -219,12 +186,12 @@
                 Log.e(TAG, "bind to recognition service failed");
                 mConnection = null;
                 mService = null;
-                mListener.onHotwordError(ERROR_CLIENT);
+                mListener.onHotwordError(HotwordRecognitionService.ERROR_CLIENT);
                 return;
             }
             putMessage(Message.obtain(mHandler, MSG_START));
         } else {
-            mListener.onHotwordError(ERROR_SERVICE_ALREADY_STARTED);
+            mListener.onHotwordError(HotwordRecognitionService.ERROR_SERVICE_ALREADY_STARTED);
             return;
         }
     }
@@ -252,7 +219,7 @@
             if (DBG) Log.d(TAG, "service startRecognition command succeeded");
         } catch (final RemoteException e) {
             Log.e(TAG, "startRecognition() failed", e);
-            mListener.onHotwordError(ERROR_CLIENT);
+            mListener.onHotwordError(HotwordRecognitionService.ERROR_CLIENT);
         }
     }
 
@@ -268,7 +235,7 @@
             if (DBG) Log.d(TAG, "service stopRecognition command succeeded");
         } catch (final RemoteException e) {
             Log.e(TAG, "stopRecognition() failed", e);
-            mListener.onHotwordError(ERROR_CLIENT);
+            mListener.onHotwordError(HotwordRecognitionService.ERROR_CLIENT);
         } finally {
             mPendingTasks.clear();
             mService = null;
@@ -281,7 +248,7 @@
         if (mService != null) {
             return true;
         }
-        mListener.onHotwordError(ERROR_CLIENT);
+        mListener.onHotwordError(HotwordRecognitionService.ERROR_CLIENT);
         Log.e(TAG, "not connected to the recognition service");
         return false;
     }
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index e6bf420..cea7e49 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -93,11 +93,16 @@
     private boolean mInterpolatorSet = false;
 
     /**
-     * Listener for the lifecycle events of the underlying 
+     * Listener for the lifecycle events of the underlying ValueAnimator object.
      */
     private Animator.AnimatorListener mListener = null;
 
     /**
+     * Listener for the update events of the underlying ValueAnimator object.
+     */
+    private ValueAnimator.AnimatorUpdateListener mUpdateListener = null;
+
+    /**
      * A lazily-created ValueAnimator used in order to get some default animator properties
      * (duration, start delay, interpolator, etc.).
      */
@@ -353,7 +358,10 @@
      * Sets a listener for events in the underlying Animators that run the property
      * animations.
      *
-     * @param listener The listener to be called with AnimatorListener events.
+     * @see Animator.AnimatorListener
+     *
+     * @param listener The listener to be called with AnimatorListener events. A value of
+     * <code>null</code> removes any existing listener.
      * @return This object, allowing calls to methods in this class to be chained.
      */
     public ViewPropertyAnimator setListener(Animator.AnimatorListener listener) {
@@ -362,6 +370,25 @@
     }
 
     /**
+     * Sets a listener for update events in the underlying ValueAnimator that runs
+     * the property animations. Note that the underlying animator is animating between
+     * 0 and 1 (these values are then turned into the actual property values internally
+     * by ViewPropertyAnimator). So the animator cannot give information on the current
+     * values of the properties being animated by this ViewPropertyAnimator, although
+     * the view object itself can be queried to get the current values.
+     *
+     * @see android.animation.ValueAnimator.AnimatorUpdateListener
+     *
+     * @param listener The listener to be called with update events. A value of
+     * <code>null</code> removes any existing listener.
+     * @return This object, allowing calls to methods in this class to be chained.
+     */
+    public ViewPropertyAnimator setUpdateListener(ValueAnimator.AnimatorUpdateListener listener) {
+        mUpdateListener = listener;
+        return this;
+    }
+
+    /**
      * Starts the currently pending property animations immediately. Calling <code>start()</code>
      * is optional because all animations start automatically at the next opportunity. However,
      * if the animations are needed to start immediately and synchronously (not at the time when
@@ -1073,6 +1100,9 @@
             } else {
                 mView.invalidateViewProperty(false, false);
             }
+            if (mUpdateListener != null) {
+                mUpdateListener.onAnimationUpdate(animation);
+            }
         }
     }
 }
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 16beb02..f9bb233 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -189,7 +189,13 @@
                     mSize, bitmap->getSize());
             return false;
         }
-        bitmap->setPixelRef(mPixelRef);
+
+        // Create a new pixelref with the new ctable that wraps the previous pixelref
+        SkPixelRef* pr = new AndroidPixelRef(*static_cast<AndroidPixelRef*>(mPixelRef), ctable);
+
+        bitmap->setPixelRef(pr)->unref();
+        // since we're already allocated, we lockPixels right away
+        // HeapAllocator/JavaPixelAllocator behaves this way too
         bitmap->lockPixels();
         return true;
     }
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index ef5b7c9..1ff0d635 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -414,7 +414,8 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 AndroidPixelRef::AndroidPixelRef(JNIEnv* env, void* storage, size_t size, jbyteArray storageObj,
-        SkColorTable* ctable) : SkMallocPixelRef(storage, size, ctable, (storageObj == NULL)) {
+        SkColorTable* ctable) : SkMallocPixelRef(storage, size, ctable, (storageObj == NULL)),
+        fWrappedPixelRef(NULL) {
     SkASSERT(storage);
     SkASSERT(env);
 
@@ -431,8 +432,25 @@
 
 }
 
+AndroidPixelRef::AndroidPixelRef(AndroidPixelRef& wrappedPixelRef, SkColorTable* ctable) :
+        SkMallocPixelRef(wrappedPixelRef.getAddr(), wrappedPixelRef.getSize(), ctable, false),
+        fWrappedPixelRef(wrappedPixelRef.fWrappedPixelRef ?
+            wrappedPixelRef.fWrappedPixelRef : &wrappedPixelRef)
+{
+    SkASSERT(fWrappedPixelRef);
+    SkSafeRef(fWrappedPixelRef);
+
+    // don't need to initialize these, as all the relevant logic delegates to the wrapped ref
+    fStorageObj = NULL;
+    fHasGlobalRef = false;
+    fGlobalRefCnt = 0;
+    fOnJavaHeap = false;
+}
+
 AndroidPixelRef::~AndroidPixelRef() {
-    if (fOnJavaHeap) {
+    if (fWrappedPixelRef) {
+        SkSafeUnref(fWrappedPixelRef);
+    } else if (fOnJavaHeap) {
         JNIEnv* env = vm2env(fVM);
 
         if (fStorageObj && fHasGlobalRef) {
@@ -441,15 +459,27 @@
         fStorageObj = NULL;
     }
 }
+jbyteArray AndroidPixelRef::getStorageObj() {
+    if (fWrappedPixelRef) {
+        return fWrappedPixelRef->fStorageObj;
+    }
+    return fStorageObj;
+}
 
 void AndroidPixelRef::setLocalJNIRef(jbyteArray arr) {
-    if (!fHasGlobalRef) {
+    if (fWrappedPixelRef) {
+        // delegate java obj management to the wrapped ref
+        fWrappedPixelRef->setLocalJNIRef(arr);
+    } else if (!fHasGlobalRef) {
         fStorageObj = arr;
     }
 }
 
 void AndroidPixelRef::globalRef(void* localref) {
-    if (fOnJavaHeap && sk_atomic_inc(&fGlobalRefCnt) == 0) {
+    if (fWrappedPixelRef) {
+        // delegate java obj management to the wrapped ref
+        fWrappedPixelRef->globalRef(localref);
+    } else if (fOnJavaHeap && sk_atomic_inc(&fGlobalRefCnt) == 0) {
         JNIEnv *env = vm2env(fVM);
 
         // If JNI ref was passed, it is always used
@@ -473,7 +503,10 @@
 }
 
 void AndroidPixelRef::globalUnref() {
-    if (fOnJavaHeap && sk_atomic_dec(&fGlobalRefCnt) == 1) {
+    if (fWrappedPixelRef) {
+        // delegate java obj management to the wrapped ref
+        fWrappedPixelRef->globalUnref();
+    } else if (fOnJavaHeap && sk_atomic_dec(&fGlobalRefCnt) == 1) {
         JNIEnv *env = vm2env(fVM);
         if (!fHasGlobalRef) {
             SkDebugf("We don't have a global ref!");
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 5a2a6f8..f4590b9 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -91,9 +91,16 @@
     AndroidPixelRef(JNIEnv* env, void* storage, size_t size, jbyteArray storageObj,
                     SkColorTable* ctable);
 
+    /**
+     * Creates an AndroidPixelRef that wraps (and refs) another to reuse/share
+     * the same storage and java byte array refcounting, yet have a different
+     * color table.
+     */
+    AndroidPixelRef(AndroidPixelRef& wrappedPixelRef, SkColorTable* ctable);
+
     virtual ~AndroidPixelRef();
 
-    jbyteArray getStorageObj() { return fStorageObj; }
+    jbyteArray getStorageObj();
 
     void setLocalJNIRef(jbyteArray arr);
 
@@ -110,6 +117,8 @@
     virtual void globalUnref();
 
 private:
+    AndroidPixelRef* const fWrappedPixelRef; // if set, delegate memory management calls to this
+
     JavaVM* fVM;
     bool fOnJavaHeap; // If true, the memory was allocated on the Java heap
 
diff --git a/graphics/java/android/graphics/PixelFormat.java b/graphics/java/android/graphics/PixelFormat.java
index 0230583..d96d6d8 100644
--- a/graphics/java/android/graphics/PixelFormat.java
+++ b/graphics/java/android/graphics/PixelFormat.java
@@ -19,16 +19,16 @@
 public class PixelFormat
 {
     /* these constants need to match those in hardware/hardware.h */
-    
+
     public static final int UNKNOWN     = 0;
 
     /** System chooses a format that supports translucency (many alpha bits) */
     public static final int TRANSLUCENT = -3;
 
-    /** 
+    /**
      * System chooses a format that supports transparency
-     * (at least 1 alpha bit) 
-     */    
+     * (at least 1 alpha bit)
+     */
     public static final int TRANSPARENT = -2;
 
     /** System chooses an opaque format (no alpha bits required) */
@@ -54,28 +54,28 @@
 
 
     /**
-     * @deprecated use {@link android.graphics.ImageFormat#NV16 
+     * @deprecated use {@link android.graphics.ImageFormat#NV16
      * ImageFormat.NV16} instead.
      */
     @Deprecated
     public static final int YCbCr_422_SP= 0x10;
 
     /**
-     * @deprecated use {@link android.graphics.ImageFormat#NV21 
+     * @deprecated use {@link android.graphics.ImageFormat#NV21
      * ImageFormat.NV21} instead.
      */
     @Deprecated
     public static final int YCbCr_420_SP= 0x11;
 
     /**
-     * @deprecated use {@link android.graphics.ImageFormat#YUY2 
+     * @deprecated use {@link android.graphics.ImageFormat#YUY2
      * ImageFormat.YUY2} instead.
      */
     @Deprecated
     public static final int YCbCr_422_I = 0x14;
 
     /**
-     * @deprecated use {@link android.graphics.ImageFormat#JPEG 
+     * @deprecated use {@link android.graphics.ImageFormat#JPEG
      * ImageFormat.JPEG} instead.
      */
     @Deprecated
@@ -95,6 +95,7 @@
             case RGB_565:
             case RGBA_5551:
             case RGBA_4444:
+            case LA_88:
                 info.bitsPerPixel = 16;
                 info.bytesPerPixel = 2;
                 break;
@@ -131,7 +132,7 @@
         }
         return false;
     }
-    
+
     public int  bytesPerPixel;
     public int  bitsPerPixel;
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index 78b842c..40a1af6 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -50,6 +50,7 @@
 import android.os.UserManager;
 import android.provider.Settings;
 import android.speech.hotword.HotwordRecognitionListener;
+import android.speech.hotword.HotwordRecognitionService;
 import android.speech.hotword.HotwordRecognizer;
 import android.telephony.TelephonyManager;
 import android.util.AttributeSet;
@@ -1775,11 +1776,13 @@
 
         public void onHotwordEvent(int eventType, Bundle eventBundle) {
             if (DEBUG) Log.d(TAG, "onHotwordEvent: " + eventType);
-            if (eventType == HotwordRecognizer.EVENT_TYPE_STATE_CHANGED) {
-                if (eventBundle != null && eventBundle.containsKey(HotwordRecognizer.PROMPT_TEXT)) {
-                    new KeyguardMessageArea.Helper(
-                            (View) getSecurityView(mCurrentSecuritySelection))
-                        .setMessage(eventBundle.getString(HotwordRecognizer.PROMPT_TEXT),true);
+            if (eventType == HotwordRecognitionService.EVENT_TYPE_PROMPT_CHANGED) {
+                if (eventBundle != null
+                        && eventBundle.containsKey(HotwordRecognitionService.KEY_PROMPT_TEXT)) {
+                    new KeyguardMessageArea
+                        .Helper((View) getSecurityView(mCurrentSecuritySelection))
+                        .setMessage(eventBundle.getString(
+                                HotwordRecognitionService.KEY_PROMPT_TEXT),true);
                 }
             }
         }