Merge "Make outline and shadow APIs public"
diff --git a/api/current.txt b/api/current.txt
index 8311ffc..6728823 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -345,6 +345,7 @@
     field public static final int canRetrieveWindowContent = 16843653; // 0x1010385
     field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
     field public static final deprecated int capitalize = 16843113; // 0x1010169
+    field public static final int castsShadow = 16843778; // 0x1010402
     field public static final int category = 16843752; // 0x10103e8
     field public static final int centerBright = 16842956; // 0x10100cc
     field public static final int centerColor = 16843275; // 0x101020b
@@ -28690,7 +28691,9 @@
     method protected float getBottomFadingEdgeStrength();
     method protected int getBottomPaddingOffset();
     method public float getCameraDistance();
+    method public final boolean getCastsShadow();
     method public android.graphics.Rect getClipBounds();
+    method public final boolean getClipToOutline();
     method public java.lang.CharSequence getContentDescription();
     method public final android.content.Context getContext();
     method protected android.view.ContextMenu.ContextMenuInfo getContextMenuInfo();
@@ -28742,6 +28745,7 @@
     method public int getNextFocusRightId();
     method public int getNextFocusUpId();
     method public android.view.View.OnFocusChangeListener getOnFocusChangeListener();
+    method public final void getOutline(android.graphics.Path);
     method public int getOverScrollMode();
     method public android.view.ViewOverlay getOverlay();
     method public int getPaddingBottom();
@@ -28957,8 +28961,10 @@
     method public void setBackgroundResource(int);
     method public final void setBottom(int);
     method public void setCameraDistance(float);
+    method public void setCastsShadow(boolean);
     method public void setClickable(boolean);
     method public void setClipBounds(android.graphics.Rect);
+    method public void setClipToOutline(boolean);
     method public void setContentDescription(java.lang.CharSequence);
     method public void setDrawingCacheBackgroundColor(int);
     method public void setDrawingCacheEnabled(boolean);
@@ -29004,6 +29010,7 @@
     method public void setOnLongClickListener(android.view.View.OnLongClickListener);
     method public void setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener);
     method public void setOnTouchListener(android.view.View.OnTouchListener);
+    method public void setOutline(android.graphics.Path);
     method public void setOverScrollMode(int);
     method public void setPadding(int, int, int, int);
     method public void setPaddingRelative(int, int, int, int);
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index 9aecbea..dfc74ea 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -484,9 +484,9 @@
      *
      * If set to true, camera distance will be ignored. Defaults to false.
      */
-    public void setSharesGlobalCamera(boolean sharesGlobalCamera) {
+    public void setUsesGlobalCamera(boolean usesGlobalCamera) {
         if (hasNativeDisplayList()) {
-            nSetSharesGlobalCamera(mFinalizer.mNativeDisplayList, sharesGlobalCamera);
+            nSetUsesGlobalCamera(mFinalizer.mNativeDisplayList, usesGlobalCamera);
         }
     }
 
@@ -1116,7 +1116,7 @@
     private static native void nSetOutline(long displayList, long nativePath);
     private static native void nSetClipToOutline(long displayList, boolean clipToOutline);
     private static native void nSetCastsShadow(long displayList, boolean castsShadow);
-    private static native void nSetSharesGlobalCamera(long displayList, boolean sharesGlobalCamera);
+    private static native void nSetUsesGlobalCamera(long displayList, boolean usesGlobalCamera);
     private static native void nSetAlpha(long displayList, float alpha);
     private static native void nSetHasOverlappingRendering(long displayList,
             boolean hasOverlappingRendering);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 49dc572..f10a271 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2393,7 +2393,7 @@
      * Flag indicating that view will be transformed by the global camera if rotated in 3d, or given
      * a non-0 Z translation.
      */
-    static final int PFLAG3_SHARES_GLOBAL_CAMERA = 0x200;
+    static final int PFLAG3_USES_GLOBAL_CAMERA = 0x200;
 
     /* End of masks for mPrivateFlags3 */
 
@@ -4037,6 +4037,11 @@
                 case R.styleable.View_layerType:
                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
                     break;
+                case R.styleable.View_castsShadow:
+                    if (a.getBoolean(attr, false)) {
+                        mPrivateFlags3 |= PFLAG3_CASTS_SHADOW;
+                    }
+                    break;
                 case R.styleable.View_textDirection:
                     // Clear any text direction flag already set
                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
@@ -10809,9 +10814,20 @@
     }
 
     /**
-     * @hide
+     * Copies the Outline of the View into the Path parameter.
+     * <p>
+     * If the outline is not set, the parameter Path is set to empty.
+     *
+     * @param outline Path into which View's outline will be copied. Must be non-null.
+     *
+     * @see #setOutline(Path)
+     * @see #getClipToOutline()
+     * @see #setClipToOutline(boolean)
      */
-    public final void getOutline(Path outline) {
+    public final void getOutline(@NonNull Path outline) {
+        if (outline == null) {
+            throw new IllegalArgumentException("Path must be non-null");
+        }
         if (mOutline == null) {
             outline.reset();
         } else {
@@ -10820,30 +10836,58 @@
     }
 
     /**
-     * @hide
+     * Sets the outline of the view, which defines the shape of the shadow it
+     * casts, and can used for clipping.
+     * <p>
+     * If the outline is not set, or {@link Path#isEmpty()}, shadows will be
+     * cast from the bounds of the View, and clipToOutline will be ignored.
+     *
+     * @param outline The new outline of the view. Must be non-null.
+     *
+     * @see #getOutline(Path)
+     * @see #getClipToOutline()
+     * @see #setClipToOutline(boolean)
      */
-    public void setOutline(Path path) {
+    public void setOutline(@NonNull Path outline) {
+        if (outline == null) {
+            throw new IllegalArgumentException("Path must be non-null");
+        }
         // always copy the path since caller may reuse
         if (mOutline == null) {
-            mOutline = new Path(path);
+            mOutline = new Path(outline);
         } else {
-            mOutline.set(path);
+            mOutline.set(outline);
         }
 
         if (mDisplayList != null) {
-            mDisplayList.setOutline(path);
+            mDisplayList.setOutline(outline);
         }
     }
 
     /**
-     * @hide
+     * Returns whether the outline of the View will be used for clipping.
+     *
+     * @see #getOutline(Path)
+     * @see #setOutline(Path)
      */
     public final boolean getClipToOutline() {
         return ((mPrivateFlags3 & PFLAG3_CLIP_TO_OUTLINE) != 0);
     }
 
     /**
-     * @hide
+     * Sets whether the outline of the View will be used for clipping.
+     * <p>
+     * The current implementation of outline clipping uses Canvas#clipPath(),
+     * and thus does not support anti-aliasing, and is expensive in terms of
+     * graphics performance. Therefore, it is strongly recommended that this
+     * property only be set temporarily, as in an animation. For the same
+     * reasons, there is no parallel XML attribute for this property.
+     * <p>
+     * If the outline of the view is not set or is empty, no clipping will be
+     * performed.
+     *
+     * @see #getOutline(Path)
+     * @see #setOutline(Path)
      */
     public void setClipToOutline(boolean clipToOutline) {
         // TODO : Add a fast invalidation here.
@@ -10860,14 +10904,35 @@
     }
 
     /**
-     * @hide
+     * Returns whether the View will cast shadows when its
+     * {@link #setTranslationZ(float) z translation} is greater than 0, or it is
+     * rotated in 3D.
+     *
+     * @see #setTranslationZ(float)
+     * @see #setRotationX(float)
+     * @see #setRotationY(float)
+     * @see #setCastsShadow(boolean)
+     * @attr ref android.R.styleable#View_castsShadow
      */
     public final boolean getCastsShadow() {
         return ((mPrivateFlags3 & PFLAG3_CASTS_SHADOW) != 0);
     }
 
     /**
-     * @hide
+     * Set to true to enable this View to cast shadows.
+     * <p>
+     * If enabled, and the View has a z translation greater than 0, or is
+     * rotated in 3D, the shadow will be cast onto the current
+     * {@link ViewGroup#setIsolatedZVolume(boolean) isolated Z volume},
+     * at the z = 0 plane.
+     * <p>
+     * The shape of the shadow being cast is defined by the
+     * {@link #setOutline(Path) outline} of the view, or the rectangular bounds
+     * of the view if the outline is not set or is empty.
+     *
+     * @see #setTranslationZ(float)
+     * @see #getCastsShadow()
+     * @attr ref android.R.styleable#View_castsShadow
      */
     public void setCastsShadow(boolean castsShadow) {
         // TODO : Add a fast invalidation here.
@@ -10884,25 +10949,46 @@
     }
 
     /**
+     * Returns whether the View will be transformed by the global camera.
+     *
+     * @see #setUsesGlobalCamera(boolean)
+     *
      * @hide
      */
-    public final boolean getSharesGlobalCamera() {
-        return ((mPrivateFlags3 & PFLAG3_SHARES_GLOBAL_CAMERA) != 0);
+    public final boolean getUsesGlobalCamera() {
+        return ((mPrivateFlags3 & PFLAG3_USES_GLOBAL_CAMERA) != 0);
     }
 
     /**
+     * Sets whether the View should be transformed by the global camera.
+     * <p>
+     * If the view has a Z translation or 3D rotation, perspective from the
+     * global camera will be applied. This enables an app to transform multiple
+     * views in 3D with coherent perspective projection among them all.
+     * <p>
+     * Setting this to true will cause {@link #setCameraDistance() camera distance}
+     * to be ignored, as the global camera's position will dictate perspective
+     * transform.
+     * <p>
+     * This should not be used in conjunction with {@link android.graphics.Camera}.
+     *
+     * @see #getUsesGlobalCamera()
+     * @see #setTranslationZ(float)
+     * @see #setRotationX(float)
+     * @see #setRotationY(float)
+     *
      * @hide
      */
-    public void setSharesGlobalCamera(boolean sharesGlobalCamera) {
+    public void setUsesGlobalCamera(boolean usesGlobalCamera) {
         // TODO : Add a fast invalidation here.
-        if (getSharesGlobalCamera() != sharesGlobalCamera) {
-            if (sharesGlobalCamera) {
-                mPrivateFlags3 |= PFLAG3_SHARES_GLOBAL_CAMERA;
+        if (getUsesGlobalCamera() != usesGlobalCamera) {
+            if (usesGlobalCamera) {
+                mPrivateFlags3 |= PFLAG3_USES_GLOBAL_CAMERA;
             } else {
-                mPrivateFlags3 &= ~PFLAG3_SHARES_GLOBAL_CAMERA;
+                mPrivateFlags3 &= ~PFLAG3_USES_GLOBAL_CAMERA;
             }
             if (mDisplayList != null) {
-                mDisplayList.setSharesGlobalCamera(sharesGlobalCamera);
+                mDisplayList.setUsesGlobalCamera(usesGlobalCamera);
             }
         }
     }
@@ -14536,7 +14622,7 @@
             displayList.setOutline(mOutline);
             displayList.setClipToOutline(getClipToOutline());
             displayList.setCastsShadow(getCastsShadow());
-            displayList.setSharesGlobalCamera(getSharesGlobalCamera());
+            displayList.setUsesGlobalCamera(getUsesGlobalCamera());
             float alpha = 1;
             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index c3bf533..9cd3c9d 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3176,6 +3176,7 @@
      * @return True if the group should be an isolated Z volume with its own Z
      *         ordering space, false if its decendents should inhabit the
      *         inherited Z ordering volume.
+     * @attr ref android.R.styleable#ViewGroup_isolatedZVolume
      */
     public void setIsolatedZVolume(boolean isolateZVolume) {
         boolean previousValue = (mGroupFlags & FLAG_ISOLATED_Z_VOLUME) != 0;
diff --git a/core/jni/android_view_DisplayList.cpp b/core/jni/android_view_DisplayList.cpp
index de68b97..e47e23c 100644
--- a/core/jni/android_view_DisplayList.cpp
+++ b/core/jni/android_view_DisplayList.cpp
@@ -142,10 +142,10 @@
     displayList->setCastsShadow(castsShadow);
 }
 
-static void android_view_DisplayList_setSharesGlobalCamera(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, jboolean sharesGlobalCamera) {
+static void android_view_DisplayList_setUsesGlobalCamera(JNIEnv* env,
+        jobject clazz, jlong displayListPtr, jboolean usesGlobalCamera) {
     DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
-    displayList->setSharesGlobalCamera(sharesGlobalCamera);
+    displayList->setUsesGlobalCamera(usesGlobalCamera);
 }
 
 static void android_view_DisplayList_setAlpha(JNIEnv* env,
@@ -420,7 +420,7 @@
     { "nSetOutline",           "(JJ)V",  (void*) android_view_DisplayList_setOutline },
     { "nSetClipToOutline",     "(JZ)V",  (void*) android_view_DisplayList_setClipToOutline },
     { "nSetCastsShadow",       "(JZ)V",  (void*) android_view_DisplayList_setCastsShadow },
-    { "nSetSharesGlobalCamera","(JZ)V",  (void*) android_view_DisplayList_setSharesGlobalCamera },
+    { "nSetUsesGlobalCamera",  "(JZ)V",  (void*) android_view_DisplayList_setUsesGlobalCamera },
     { "nSetAlpha",             "(JF)V",  (void*) android_view_DisplayList_setAlpha },
     { "nSetHasOverlappingRendering", "(JZ)V",
             (void*) android_view_DisplayList_setHasOverlappingRendering },
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 2d9c959..c5524d7 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2123,6 +2123,10 @@
         <!-- scale of the view in the y direction. -->
         <attr name="scaleY" format="float" />
 
+        <!-- Defines whether the View casts a shadow when it has a 3D rotation or Z
+             translation.-->
+        <attr name="castsShadow" format="boolean" />
+
         <!-- Determines which side the vertical scroll bar should be placed on. -->
         <attr name="verticalScrollbarPosition">
             <!-- Place the scroll bar wherever the system default determines. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 722f965..794d6a5 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2108,6 +2108,7 @@
   <public type="attr" name="toSceneName" />
   <public type="attr" name="sharedElementName" />
   <public type="attr" name="transitionGroup" />
+  <public type="attr" name="castsShadow" />
 
   <public type="id" name="shared_element_name" />
 
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index a5e66fa..6144f3d 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -232,7 +232,7 @@
     mOutline.rewind();
     mClipToOutline = false;
     mCastsShadow = false;
-    mSharesGlobalCamera = false;
+    mUsesGlobalCamera = false;
     mAlpha = 1;
     mHasOverlappingRendering = true;
     mTranslationX = 0;
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index c3d9fd7..9487fae 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -196,8 +196,8 @@
         mCastsShadow = castsShadow;
     }
 
-    void setSharesGlobalCamera(bool sharesGlobalCamera) {
-        mSharesGlobalCamera = sharesGlobalCamera;
+    void setUsesGlobalCamera(bool usesGlobalCamera) {
+        mUsesGlobalCamera = usesGlobalCamera;
     }
 
     void setProjectBackwards(bool shouldProject) {
@@ -621,7 +621,7 @@
     SkPath mOutline;
     bool mClipToOutline;
     bool mCastsShadow;
-    bool mSharesGlobalCamera; // TODO: respect value when rendering
+    bool mUsesGlobalCamera; // TODO: respect value when rendering
     float mAlpha;
     bool mHasOverlappingRendering;
     float mTranslationX, mTranslationY, mTranslationZ;