Merge changes I6b641d6b,Id573a309

* changes:
  Renamed NonClientDecorView to DecorCaptionView
  Control display of shadows for multi-window in DecorView
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 077cebc..4c221fc5 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -25,8 +25,8 @@
 import com.android.internal.view.menu.MenuPopupHelper;
 import com.android.internal.widget.ActionBarContextView;
 import com.android.internal.widget.BackgroundFallback;
+import com.android.internal.widget.DecorCaptionView;
 import com.android.internal.widget.FloatingToolbar;
-import com.android.internal.widget.NonClientDecorView;
 
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
@@ -88,6 +88,18 @@
 
     private static final boolean SWEEP_OPEN_MENU = false;
 
+    // The height of a window which has focus in DIP.
+    private final static int DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP = 20;
+    // The height of a window which has not in DIP.
+    private final static int DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP = 5;
+
+    // Cludge to address b/22668382: Set the shadow size to the maximum so that the layer
+    // size calculation takes the shadow size into account. We set the elevation currently
+    // to max until the first layout command has been executed.
+    private boolean mAllowUpdateElevation = false;
+
+    private boolean mElevationAdjustedForStack = false;
+
     int mDefaultOpacity = PixelFormat.OPAQUE;
 
     /** The feature ID of the panel, or -1 if this is the application's DecorView */
@@ -101,8 +113,7 @@
 
     private final Rect mFrameOffsets = new Rect();
 
-    // True if a non client area decor exists.
-    private boolean mHasNonClientDecor = false;
+    private boolean mHasCaption = false;
 
     private boolean mChanging;
 
@@ -161,18 +172,18 @@
     private Rect mTempRect;
     private Rect mOutsets = new Rect();
 
-    // This is the non client decor view for the window, containing the caption and window control
+    // This is the caption view for the window, containing the caption and window control
     // buttons. The visibility of this decor depends on the workspace and the window type.
     // If the window type does not require such a view, this member might be null.
-    NonClientDecorView mNonClientDecorView;
+    DecorCaptionView mDecorCaptionView;
 
-    // The non client decor needs to adapt to the used workspace. Since querying and changing the
-    // workspace is expensive, this is the workspace value the window is currently set up for.
-    int mWorkspaceId;
+    // Stack window is currently in. Since querying and changing the stack is expensive,
+    // this is the stack value the window is currently set up for.
+    int mStackId;
 
     private boolean mWindowResizeCallbacksAdded = false;
 
-    public BackdropFrameRenderer mBackdropFrameRenderer = null;
+    BackdropFrameRenderer mBackdropFrameRenderer = null;
     private Drawable mResizingBackgroundDrawable;
     private Drawable mCaptionBackgroundDrawable;
 
@@ -191,7 +202,7 @@
         setWindow(window);
     }
 
-    public void setBackgroundFallback(int resId) {
+    void setBackgroundFallback(int resId) {
         mBackgroundFallback.setDrawable(resId != 0 ? getContext().getDrawable(resId) : null);
         setWillNotDraw(getBackground() == null && !mBackgroundFallback.hasFallback());
     }
@@ -351,10 +362,10 @@
     @Override
     public boolean onInterceptTouchEvent(MotionEvent event) {
         int action = event.getAction();
-        if (mHasNonClientDecor && mNonClientDecorView.mVisible) {
-            // Don't dispatch ACTION_DOWN to the non client decor if the window is
-            // resizable and the event was (starting) outside the window.
-            // Window resizing events should be handled by WindowManager.
+        if (mHasCaption && isShowingCaption()) {
+            // Don't dispatch ACTION_DOWN to the captionr if the window is resizable and the event
+            // was (starting) outside the window. Window resizing events should be handled by
+            // WindowManager.
             // TODO: Investigate how to handle the outside touch in window manager
             //       without generating these events.
             //       Currently we receive these because we need to enlarge the window's
@@ -630,6 +641,11 @@
         if (mOutsets.top > 0) {
             offsetTopAndBottom(-mOutsets.top);
         }
+
+        // If the application changed its SystemUI metrics, we might also have to adapt
+        // our shadow elevation.
+        updateElevation();
+        mAllowUpdateElevation = true;
     }
 
     @Override
@@ -781,11 +797,11 @@
         }
     }
 
-    public void startChanging() {
+    void startChanging() {
         mChanging = true;
     }
 
-    public void finishChanging() {
+    void finishChanging() {
         mChanging = false;
         drawableChanged();
     }
@@ -1138,7 +1154,7 @@
         invalidate();
 
         int opacity = PixelFormat.OPAQUE;
-        if (windowHasShadow()) {
+        if (ActivityManager.StackId.hasWindowShadow(mStackId)) {
             // If the window has a shadow, it must be translucent.
             opacity = PixelFormat.TRANSLUCENT;
         } else{
@@ -1213,6 +1229,8 @@
         if (mFloatingActionMode != null) {
             mFloatingActionMode.onWindowFocusChanged(hasWindowFocus);
         }
+
+        updateElevation();
     }
 
     @Override
@@ -1495,38 +1513,19 @@
     }
 
     /**
-     * Informs the decor if a non client decor is attached and visible.
+     * Informs the decor if the caption is attached and visible.
      * @param attachedAndVisible true when the decor is visible.
-     * Note that this will even be called if there is no non client decor.
+     * Note that this will even be called if there is no caption.
      **/
-    void enableNonClientDecor(boolean attachedAndVisible) {
-        if (mHasNonClientDecor != attachedAndVisible) {
-            mHasNonClientDecor = attachedAndVisible;
+    void enableCaption(boolean attachedAndVisible) {
+        if (mHasCaption != attachedAndVisible) {
+            mHasCaption = attachedAndVisible;
             if (getForeground() != null) {
                 drawableChanged();
             }
         }
     }
 
-    /**
-     * Returns true if the window has a non client decor.
-     * @return If there is a non client decor - even if it is not visible.
-     **/
-    private boolean windowHasNonClientDecor() {
-        return mHasNonClientDecor;
-    }
-
-    /**
-     * Returns true if the Window is free floating and has a shadow (although at some times
-     * it might not be displaying it, e.g. during a resize). Note that non overlapping windows
-     * do not have a shadow since it could not be seen anyways (a small screen / tablet
-     * "tiles" the windows side by side but does not overlap them).
-     * @return Returns true when the window has a shadow created by the non client decor.
-     **/
-    private boolean windowHasShadow() {
-        return windowHasNonClientDecor() && ActivityManager.StackId.hasWindowShadow(mWorkspaceId);
-    }
-
     void setWindow(PhoneWindow phoneWindow) {
         mWindow = phoneWindow;
         Context context = getContext();
@@ -1537,91 +1536,89 @@
     }
 
     void onConfigurationChanged() {
-        if (mNonClientDecorView != null) {
-            int workspaceId = getWorkspaceId();
-            if (mWorkspaceId != workspaceId) {
-                mWorkspaceId = workspaceId;
+        int workspaceId = getStackId();
+        if (mDecorCaptionView != null) {
+            if (mStackId != workspaceId) {
+                mStackId = workspaceId;
                 // We might have to change the kind of surface before we do anything else.
-                mNonClientDecorView.onConfigurationChanged(
-                        ActivityManager.StackId.hasWindowDecor(mWorkspaceId),
-                        ActivityManager.StackId.hasWindowShadow(mWorkspaceId));
-                enableNonClientDecor(ActivityManager.StackId.hasWindowDecor(workspaceId));
+                mDecorCaptionView.onConfigurationChanged(
+                        ActivityManager.StackId.hasWindowDecor(mStackId));
+                enableCaption(ActivityManager.StackId.hasWindowDecor(workspaceId));
             }
         }
+        initializeElevation();
     }
 
     View onResourcesLoaded(LayoutInflater inflater, int layoutResource) {
-        mWorkspaceId = getWorkspaceId();
+        mStackId = getStackId();
 
         mResizingBackgroundDrawable = getResizingBackgroundDrawable(
                 mWindow.mBackgroundResource, mWindow.mBackgroundFallbackResource);
         mCaptionBackgroundDrawable =
-                getContext().getDrawable(R.drawable.non_client_decor_title_focused);
+                getContext().getDrawable(R.drawable.decor_caption_title_focused);
 
         if (mBackdropFrameRenderer != null) {
             mBackdropFrameRenderer.onResourcesLoaded(
                     this, mResizingBackgroundDrawable, mCaptionBackgroundDrawable);
         }
 
-        mNonClientDecorView = createNonClientDecorView(inflater);
+        mDecorCaptionView = createDecorCaptionView(inflater);
         final View root = inflater.inflate(layoutResource, null);
-        if (mNonClientDecorView != null) {
-            if (mNonClientDecorView.getParent() == null) {
-                addView(mNonClientDecorView,
+        if (mDecorCaptionView != null) {
+            if (mDecorCaptionView.getParent() == null) {
+                addView(mDecorCaptionView,
                         new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
             }
-            mNonClientDecorView.addView(root,
+            mDecorCaptionView.addView(root,
                     new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
         } else {
             addView(root, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
         }
         mContentRoot = (ViewGroup) root;
+        initializeElevation();
         return root;
     }
 
-    // Free floating overlapping windows require a non client decor with a caption and shadow..
-    private NonClientDecorView createNonClientDecorView(LayoutInflater inflater) {
-        NonClientDecorView nonClientDecorView = null;
-        for (int i = getChildCount() - 1; i >= 0 && nonClientDecorView == null; i--) {
+    // Free floating overlapping windows require a caption.
+    private DecorCaptionView createDecorCaptionView(LayoutInflater inflater) {
+        DecorCaptionView DecorCaptionView = null;
+        for (int i = getChildCount() - 1; i >= 0 && DecorCaptionView == null; i--) {
             View view = getChildAt(i);
-            if (view instanceof NonClientDecorView) {
+            if (view instanceof DecorCaptionView) {
                 // The decor was most likely saved from a relaunch - so reuse it.
-                nonClientDecorView = (NonClientDecorView) view;
+                DecorCaptionView = (DecorCaptionView) view;
                 removeViewAt(i);
             }
         }
         final WindowManager.LayoutParams attrs = mWindow.getAttributes();
-        boolean isApplication = attrs.type == TYPE_BASE_APPLICATION ||
+        final boolean isApplication = attrs.type == TYPE_BASE_APPLICATION ||
                 attrs.type == TYPE_APPLICATION;
-        // Only a non floating application window on one of the allowed workspaces can get a non
-        // client decor.
-        final boolean hasNonClientDecor = ActivityManager.StackId.hasWindowDecor(mWorkspaceId);
-        if (!mWindow.isFloating() && isApplication && hasNonClientDecor) {
+        // Only a non floating application window on one of the allowed workspaces can get a caption
+        if (!mWindow.isFloating() && isApplication
+                && ActivityManager.StackId.hasWindowDecor(mStackId)) {
             // Dependent on the brightness of the used title we either use the
             // dark or the light button frame.
-            if (nonClientDecorView == null) {
+            if (DecorCaptionView == null) {
                 Context context = getContext();
                 TypedValue value = new TypedValue();
                 context.getTheme().resolveAttribute(R.attr.colorPrimary, value, true);
                 inflater = inflater.from(context);
                 if (Color.luminance(value.data) < 0.5) {
-                    nonClientDecorView = (NonClientDecorView) inflater.inflate(
-                            R.layout.non_client_decor_dark, null);
+                    DecorCaptionView = (DecorCaptionView) inflater.inflate(
+                            R.layout.decor_caption_dark, null);
                 } else {
-                    nonClientDecorView = (NonClientDecorView) inflater.inflate(
-                            R.layout.non_client_decor_light, null);
+                    DecorCaptionView = (DecorCaptionView) inflater.inflate(
+                            R.layout.decor_caption_light, null);
                 }
             }
-            nonClientDecorView.setPhoneWindow(mWindow,
-                    ActivityManager.StackId.hasWindowDecor(mWorkspaceId),
-                    ActivityManager.StackId.hasWindowShadow(mWorkspaceId));
+            DecorCaptionView.setPhoneWindow(mWindow, true /*showDecor*/);
         } else {
-            nonClientDecorView = null;
+            DecorCaptionView = null;
         }
 
-        // Tell the decor if it has a visible non client decor.
-        enableNonClientDecor(nonClientDecorView != null && hasNonClientDecor);
-        return nonClientDecorView;
+        // Tell the decor if it has a visible caption.
+        enableCaption(DecorCaptionView != null);
+        return DecorCaptionView;
     }
 
     /**
@@ -1652,12 +1649,12 @@
     }
 
     /**
-     * Returns the Id of the workspace which contains this window.
-     * Note that if no workspace can be determined - which usually means that it was not
-     * created for an activity - the fullscreen workspace ID will be returned.
-     * @return Returns the workspace stack id which contains this window.
+     * Returns the Id of the stack which contains this window.
+     * Note that if no stack can be determined - which usually means that it was not
+     * created for an activity - the fullscreen stack ID will be returned.
+     * @return Returns the stack id which contains this window.
      **/
-    private int getWorkspaceId() {
+    private int getStackId() {
         int workspaceId = INVALID_STACK_ID;
         final Window.WindowControllerCallback callback = mWindow.getWindowControllerCallback();
         if (callback != null) {
@@ -1674,12 +1671,12 @@
     }
 
     void clearContentView() {
-        if (mNonClientDecorView != null) {
-            if (mNonClientDecorView.getChildCount() > 1) {
-                mNonClientDecorView.removeViewAt(1);
+        if (mDecorCaptionView != null) {
+            if (mDecorCaptionView.getChildCount() > 1) {
+                mDecorCaptionView.removeViewAt(1);
             }
         } else {
-            // This window doesn't have non client decor, so we need to just remove the
+            // This window doesn't have caption, so we need to just remove the
             // children of the decor view.
             removeAllViews();
         }
@@ -1749,18 +1746,60 @@
         }
     }
 
+    /**
+     * The elevation gets set for the first time and the framework needs to be informed that
+     * the surface layer gets created with the shadow size in mind.
+     */
+    private void initializeElevation() {
+        // TODO(skuhne): Call setMaxElevation here accordingly after b/22668382 got fixed.
+        mAllowUpdateElevation = false;
+        updateElevation();
+    }
+
     private void updateElevation() {
-        if (mNonClientDecorView != null) {
-            mNonClientDecorView.updateElevation();
+        float elevation = 0;
+        final boolean wasAdjustedForStack = mElevationAdjustedForStack;
+        // Do not use a shadow when we are in resizing mode (mBackdropFrameRenderer not null)
+        // since the shadow is bound to the content size and not the target size.
+        if (ActivityManager.StackId.hasWindowShadow(mStackId)
+                && mBackdropFrameRenderer == null) {
+            elevation = hasWindowFocus() ?
+                    DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP : DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
+            // TODO(skuhne): Remove this if clause once b/22668382 got fixed.
+            if (!mAllowUpdateElevation) {
+                elevation = DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP;
+            }
+            // Convert the DP elevation into physical pixels.
+            elevation = dipToPx(elevation);
+            mElevationAdjustedForStack = true;
+        } else {
+            mElevationAdjustedForStack = false;
+        }
+
+        // Don't change the elevation if we didn't previously adjust it for the stack it was in
+        // or it didn't change.
+        if ((wasAdjustedForStack || mElevationAdjustedForStack)
+                && getElevation() != elevation) {
+            mWindow.setElevation(elevation);
         }
     }
 
     boolean isShowingCaption() {
-        return mNonClientDecorView != null && mNonClientDecorView.isShowingDecor();
+        return mDecorCaptionView != null && mDecorCaptionView.isCaptionShowing();
     }
 
     int getCaptionHeight() {
-        return isShowingCaption() ? mNonClientDecorView.getDecorCaptionHeight() : 0;
+        return isShowingCaption() ? mDecorCaptionView.getCaptionHeight() : 0;
+    }
+
+    /**
+     * Converts a DIP measure into physical pixels.
+     * @param dip The dip value.
+     * @return Returns the number of pixels.
+     */
+    private float dipToPx(float dip) {
+        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip,
+                getResources().getDisplayMetrics());
     }
 
     private static class ColorViewState {
diff --git a/core/java/com/android/internal/widget/DecorCaptionView.java b/core/java/com/android/internal/widget/DecorCaptionView.java
new file mode 100644
index 0000000..e22bd10
--- /dev/null
+++ b/core/java/com/android/internal/widget/DecorCaptionView.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+
+import android.content.Context;
+import android.os.RemoteException;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.view.ViewGroup;
+import android.view.ViewOutlineProvider;
+import android.view.Window;
+import android.util.Log;
+
+import com.android.internal.R;
+import com.android.internal.policy.PhoneWindow;
+
+/**
+ * This class represents the special screen elements to control a window on freeform
+ * environment.
+ * As such this class handles the following things:
+ * <ul>
+ * <li>The caption, containing the system buttons like maximize, close and such as well as
+ * allowing the user to drag the window around.</li>
+ * After creating the view, the function
+ * {@link #setPhoneWindow} needs to be called to make
+ * the connection to it's owning PhoneWindow.
+ * Note: At this time the application can change various attributes of the DecorView which
+ * will break things (in settle/unexpected ways):
+ * <ul>
+ * <li>setOutlineProvider</li>
+ * <li>setSurfaceFormat</li>
+ * <li>..</li>
+ * </ul>
+ */
+public class DecorCaptionView extends LinearLayout
+        implements View.OnClickListener, View.OnTouchListener {
+    private final static String TAG = "DecorCaptionView";
+    private PhoneWindow mOwner = null;
+    private boolean mShow = false;
+
+    // True if the window is being dragged.
+    private boolean mDragging = false;
+
+    // True when the left mouse button got released while dragging.
+    private boolean mLeftMouseButtonReleased;
+
+    public DecorCaptionView(Context context) {
+        super(context);
+    }
+
+    public DecorCaptionView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public DecorCaptionView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    public void setPhoneWindow(PhoneWindow owner, boolean show) {
+        mOwner = owner;
+        mShow = show;
+        updateCaptionVisibility();
+        // By changing the outline provider to BOUNDS, the window can remove its
+        // background without removing the shadow.
+        mOwner.getDecorView().setOutlineProvider(ViewOutlineProvider.BOUNDS);
+
+        findViewById(R.id.maximize_window).setOnClickListener(this);
+        findViewById(R.id.close_window).setOnClickListener(this);
+    }
+
+    @Override
+    public boolean onTouch(View v, MotionEvent e) {
+        // Note: There are no mixed events. When a new device gets used (e.g. 1. Mouse, 2. touch)
+        // the old input device events get cancelled first. So no need to remember the kind of
+        // input device we are listening to.
+        switch (e.getActionMasked()) {
+            case MotionEvent.ACTION_DOWN:
+                if (!mShow) {
+                    // When there is no caption we should not react to anything.
+                    return false;
+                }
+                // A drag action is started if we aren't dragging already and the starting event is
+                // either a left mouse button or any other input device.
+                if (!mDragging &&
+                        (e.getToolType(e.getActionIndex()) != MotionEvent.TOOL_TYPE_MOUSE ||
+                                (e.getButtonState() & MotionEvent.BUTTON_PRIMARY) != 0)) {
+                    mDragging = true;
+                    mLeftMouseButtonReleased = false;
+                    startMovingTask(e.getRawX(), e.getRawY());
+                }
+                break;
+
+            case MotionEvent.ACTION_MOVE:
+                if (mDragging && !mLeftMouseButtonReleased) {
+                    if (e.getToolType(e.getActionIndex()) == MotionEvent.TOOL_TYPE_MOUSE &&
+                            (e.getButtonState() & MotionEvent.BUTTON_PRIMARY) == 0) {
+                        // There is no separate mouse button up call and if the user mixes mouse
+                        // button drag actions, we stop dragging once he releases the button.
+                        mLeftMouseButtonReleased = true;
+                        break;
+                    }
+                }
+                break;
+
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_CANCEL:
+                if (!mDragging) {
+                    break;
+                }
+                // Abort the ongoing dragging.
+                mDragging = false;
+                return true;
+        }
+        return mDragging;
+    }
+
+    /**
+     * The phone window configuration has changed and the caption needs to be updated.
+     * @param show True if the caption should be shown.
+     */
+    public void onConfigurationChanged(boolean show) {
+        mShow = show;
+        updateCaptionVisibility();
+    }
+
+    @Override
+    public void onClick(View view) {
+        if (view.getId() == R.id.maximize_window) {
+            maximizeWindow();
+        } else if (view.getId() == R.id.close_window) {
+            mOwner.dispatchOnWindowDismissed(true /*finishTask*/);
+        }
+    }
+
+    @Override
+    public void addView(View child, int index, ViewGroup.LayoutParams params) {
+        // Make sure that we never get more then one client area in our view.
+        if (index >= 2 || getChildCount() >= 2) {
+            throw new IllegalStateException("DecorCaptionView can only handle 1 client view");
+        }
+        super.addView(child, index, params);
+    }
+
+    /**
+     * Determine if the workspace is entirely covered by the window.
+     * @return Returns true when the window is filling the entire screen/workspace.
+     **/
+    private boolean isFillingScreen() {
+        return (0 != ((getWindowSystemUiVisibility() | getSystemUiVisibility()) &
+                (View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
+                        View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_LOW_PROFILE)));
+    }
+
+    /**
+     * Updates the visibility of the caption.
+     **/
+    private void updateCaptionVisibility() {
+        // Don't show the caption if the window has e.g. entered full screen.
+        boolean invisible = isFillingScreen() || !mShow;
+        View caption = getChildAt(0);
+        caption.setVisibility(invisible ? GONE : VISIBLE);
+        caption.setOnTouchListener(this);
+    }
+
+    /**
+     * Maximize the window by moving it to the maximized workspace stack.
+     **/
+    private void maximizeWindow() {
+        Window.WindowControllerCallback callback = mOwner.getWindowControllerCallback();
+        if (callback != null) {
+            try {
+                callback.changeWindowStack(FULLSCREEN_WORKSPACE_STACK_ID);
+            } catch (RemoteException ex) {
+                Log.e(TAG, "Cannot change task workspace.");
+            }
+        }
+    }
+
+    public boolean isCaptionShowing() {
+        return mShow;
+    }
+
+    public int getCaptionHeight() {
+        final View caption = getChildAt(0);
+        return (caption != null) ? caption.getHeight() : 0;
+    }
+}
diff --git a/core/java/com/android/internal/widget/NonClientDecorView.java b/core/java/com/android/internal/widget/NonClientDecorView.java
deleted file mode 100644
index 33b8e05..0000000
--- a/core/java/com/android/internal/widget/NonClientDecorView.java
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.widget;
-
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
-
-import android.content.Context;
-import android.os.RemoteException;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-import android.widget.LinearLayout;
-import android.view.ViewGroup;
-import android.view.ViewOutlineProvider;
-import android.view.Window;
-import android.util.Log;
-import android.util.TypedValue;
-
-import com.android.internal.R;
-import com.android.internal.policy.DecorView;
-import com.android.internal.policy.PhoneWindow;
-
-/**
- * This class represents the special screen elements to control a window on free form
- * environment. All thse screen elements are added in the "non client area" which is the area of
- * the window which is handled by the OS and not the application.
- * As such this class handles the following things:
- * <ul>
- * <li>The caption, containing the system buttons like maximize, close and such as well as
- * allowing the user to drag the window around.</li>
- * <li>The shadow - which is changing dependent on the window focus.</li>
- * <li>The border around the client area (if there is one).</li>
- * <li>The resize handles which allow to resize the window.</li>
- * </ul>
- * After creating the view, the function
- * {@link #setPhoneWindow} needs to be called to make
- * the connection to it's owning PhoneWindow.
- * Note: At this time the application can change various attributes of the DecorView which
- * will break things (in settle/unexpected ways):
- * <ul>
- * <li>setElevation</li>
- * <li>setOutlineProvider</li>
- * <li>setSurfaceFormat</li>
- * <li>..</li>
- * </ul>
- * This will be mitigated once b/22527834 will be addressed.
- */
-public class NonClientDecorView extends LinearLayout
-        implements View.OnClickListener, View.OnTouchListener {
-    private final static String TAG = "NonClientDecorView";
-    // The height of a window which has focus in DIP.
-    private final int DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP = 20;
-    // The height of a window which has not in DIP.
-    private final int DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP = 5;
-    private PhoneWindow mOwner = null;
-    private boolean mWindowHasShadow = false;
-    private boolean mShowDecor = false;
-
-    // True if the window is being dragged.
-    private boolean mDragging = false;
-
-    // True when the left mouse button got released while dragging.
-    private boolean mLeftMouseButtonReleased;
-
-    // True if this window is resizable (which is currently only true when the decor is shown).
-    public boolean mVisible = false;
-
-    // The current focus state of the window for updating the window elevation.
-    private boolean mWindowHasFocus = true;
-
-    // Cludge to address b/22668382: Set the shadow size to the maximum so that the layer
-    // size calculation takes the shadow size into account. We set the elevation currently
-    // to max until the first layout command has been executed.
-    private boolean mAllowUpdateElevation = false;
-
-    public NonClientDecorView(Context context) {
-        super(context);
-    }
-
-    public NonClientDecorView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public NonClientDecorView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-    }
-
-    public void setPhoneWindow(PhoneWindow owner, boolean showDecor, boolean windowHasShadow) {
-        mOwner = owner;
-        mWindowHasShadow = windowHasShadow;
-        mShowDecor = showDecor;
-        updateCaptionVisibility();
-        if (mWindowHasShadow) {
-            initializeElevation();
-        }
-        // By changing the outline provider to BOUNDS, the window can remove its
-        // background without removing the shadow.
-        mOwner.getDecorView().setOutlineProvider(ViewOutlineProvider.BOUNDS);
-
-        findViewById(R.id.maximize_window).setOnClickListener(this);
-        findViewById(R.id.close_window).setOnClickListener(this);
-    }
-
-    @Override
-    public boolean onTouch(View v, MotionEvent e) {
-        // Note: There are no mixed events. When a new device gets used (e.g. 1. Mouse, 2. touch)
-        // the old input device events get cancelled first. So no need to remember the kind of
-        // input device we are listening to.
-        switch (e.getActionMasked()) {
-            case MotionEvent.ACTION_DOWN:
-                if (!mShowDecor) {
-                    // When there is no decor we should not react to anything.
-                    return false;
-                }
-                // A drag action is started if we aren't dragging already and the starting event is
-                // either a left mouse button or any other input device.
-                if (!mDragging &&
-                        (e.getToolType(e.getActionIndex()) != MotionEvent.TOOL_TYPE_MOUSE ||
-                                (e.getButtonState() & MotionEvent.BUTTON_PRIMARY) != 0)) {
-                    mDragging = true;
-                    mLeftMouseButtonReleased = false;
-                    startMovingTask(e.getRawX(), e.getRawY());
-                }
-                break;
-
-            case MotionEvent.ACTION_MOVE:
-                if (mDragging && !mLeftMouseButtonReleased) {
-                    if (e.getToolType(e.getActionIndex()) == MotionEvent.TOOL_TYPE_MOUSE &&
-                            (e.getButtonState() & MotionEvent.BUTTON_PRIMARY) == 0) {
-                        // There is no separate mouse button up call and if the user mixes mouse
-                        // button drag actions, we stop dragging once he releases the button.
-                        mLeftMouseButtonReleased = true;
-                        break;
-                    }
-                }
-                break;
-
-            case MotionEvent.ACTION_UP:
-            case MotionEvent.ACTION_CANCEL:
-                if (!mDragging) {
-                    break;
-                }
-                // Abort the ongoing dragging.
-                mDragging = false;
-                return true;
-        }
-        return mDragging;
-    }
-
-    /**
-     * The phone window configuration has changed and the decor needs to be updated.
-     * @param showDecor True if the decor should be shown.
-     * @param windowHasShadow True when the window should show a shadow.
-     **/
-    public void onConfigurationChanged(boolean showDecor, boolean windowHasShadow) {
-        mShowDecor = showDecor;
-        updateCaptionVisibility();
-        if (windowHasShadow != mWindowHasShadow) {
-            mWindowHasShadow = windowHasShadow;
-            initializeElevation();
-        }
-    }
-
-    @Override
-    public void onClick(View view) {
-        if (view.getId() == R.id.maximize_window) {
-            maximizeWindow();
-        } else if (view.getId() == R.id.close_window) {
-            mOwner.dispatchOnWindowDismissed(true /*finishTask*/);
-        }
-    }
-
-    @Override
-    public void onWindowFocusChanged(boolean hasWindowFocus) {
-        mWindowHasFocus = hasWindowFocus;
-        updateElevation();
-        super.onWindowFocusChanged(hasWindowFocus);
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        // If the application changed its SystemUI metrics, we might also have to adapt
-        // our shadow elevation.
-        updateElevation();
-        mAllowUpdateElevation = true;
-
-        super.onLayout(changed, left, top, right, bottom);
-    }
-
-    @Override
-    public void addView(View child, int index, ViewGroup.LayoutParams params) {
-        // Make sure that we never get more then one client area in our view.
-        if (index >= 2 || getChildCount() >= 2) {
-            throw new IllegalStateException("NonClientDecorView can only handle 1 client view");
-        }
-        super.addView(child, index, params);
-    }
-
-    /**
-     * Determine if the workspace is entirely covered by the window.
-     * @return Returns true when the window is filling the entire screen/workspace.
-     **/
-    private boolean isFillingScreen() {
-        return (0 != ((getWindowSystemUiVisibility() | getSystemUiVisibility()) &
-                (View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
-                        View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_LOW_PROFILE)));
-    }
-
-    /**
-     * Updates the visibility of the caption.
-     **/
-    private void updateCaptionVisibility() {
-        // Don't show the decor if the window has e.g. entered full screen.
-        boolean invisible = isFillingScreen() || !mShowDecor;
-        View caption = getChildAt(0);
-        caption.setVisibility(invisible ? GONE : VISIBLE);
-        caption.setOnTouchListener(this);
-        mVisible = !invisible;
-    }
-
-    /**
-     * The elevation gets set for the first time and the framework needs to be informed that
-     * the surface layer gets created with the shadow size in mind.
-     **/
-    private void initializeElevation() {
-        // TODO(skuhne): Call setMaxElevation here accordingly after b/22668382 got fixed.
-        mAllowUpdateElevation = false;
-        if (mWindowHasShadow) {
-            updateElevation();
-        } else {
-            mOwner.setElevation(0);
-        }
-    }
-
-    /**
-     * The shadow height gets controlled by the focus to visualize highlighted windows.
-     * Note: This will overwrite application elevation properties.
-     * Note: Windows which have (temporarily) changed their attributes to cover the SystemUI
-     *       will get no shadow as they are expected to be "full screen".
-     **/
-    public void updateElevation() {
-        float elevation = 0;
-        // Do not use a shadow when we are in resizing mode (mRenderer not null) since the shadow
-        // is bound to the content size and not the target size.
-        if (mWindowHasShadow
-                && ((DecorView) mOwner.getDecorView()).mBackdropFrameRenderer == null) {
-            boolean fill = isFillingScreen();
-            elevation = fill ? 0 :
-                    (mWindowHasFocus ? DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP :
-                            DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP);
-            // TODO(skuhne): Remove this if clause once b/22668382 got fixed.
-            if (!mAllowUpdateElevation && !fill) {
-                elevation = DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP;
-            }
-            // Convert the DP elevation into physical pixels.
-            elevation = dipToPx(elevation);
-        }
-        // Don't change the elevation if it didn't change since it can require some time.
-        if (mOwner.getDecorView().getElevation() != elevation) {
-            mOwner.setElevation(elevation);
-        }
-    }
-
-    /**
-     * Converts a DIP measure into physical pixels.
-     * @param dip The dip value.
-     * @return Returns the number of pixels.
-     */
-    private float dipToPx(float dip) {
-        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip,
-                getResources().getDisplayMetrics());
-    }
-
-    /**
-     * Maximize the window by moving it to the maximized workspace stack.
-     **/
-    private void maximizeWindow() {
-        Window.WindowControllerCallback callback = mOwner.getWindowControllerCallback();
-        if (callback != null) {
-            try {
-                callback.changeWindowStack(FULLSCREEN_WORKSPACE_STACK_ID);
-            } catch (RemoteException ex) {
-                Log.e(TAG, "Cannot change task workspace.");
-            }
-        }
-    }
-
-    public boolean isShowingDecor() {
-        return mShowDecor;
-    }
-
-    public int getDecorCaptionHeight() {
-        final View caption = getChildAt(0);
-        return (caption != null) ? caption.getHeight() : 0;
-    }
-}
diff --git a/core/res/res/drawable/non_client_decor_title.xml b/core/res/res/drawable/decor_caption_title.xml
similarity index 84%
rename from core/res/res/drawable/non_client_decor_title.xml
rename to core/res/res/drawable/decor_caption_title.xml
index e50daea..591605d3 100644
--- a/core/res/res/drawable/non_client_decor_title.xml
+++ b/core/res/res/drawable/decor_caption_title.xml
@@ -16,6 +16,6 @@
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_window_focused="true"
-          android:drawable="@drawable/non_client_decor_title_focused" />
-    <item android:drawable="@drawable/non_client_decor_title_unfocused" />
+          android:drawable="@drawable/decor_caption_title_focused" />
+    <item android:drawable="@drawable/decor_caption_title_unfocused" />
 </selector>
diff --git a/core/res/res/drawable/non_client_decor_title_focused.xml b/core/res/res/drawable/decor_caption_title_focused.xml
similarity index 100%
rename from core/res/res/drawable/non_client_decor_title_focused.xml
rename to core/res/res/drawable/decor_caption_title_focused.xml
diff --git a/core/res/res/drawable/non_client_decor_title_unfocused.xml b/core/res/res/drawable/decor_caption_title_unfocused.xml
similarity index 100%
rename from core/res/res/drawable/non_client_decor_title_unfocused.xml
rename to core/res/res/drawable/decor_caption_title_unfocused.xml
diff --git a/core/res/res/layout/non_client_decor_dark.xml b/core/res/res/layout/decor_caption_dark.xml
similarity index 90%
rename from core/res/res/layout/non_client_decor_dark.xml
rename to core/res/res/layout/decor_caption_dark.xml
index 40b8960..86d68af 100644
--- a/core/res/res/layout/non_client_decor_dark.xml
+++ b/core/res/res/layout/decor_caption_dark.xml
@@ -17,7 +17,7 @@
 */
 -->
 
-<com.android.internal.widget.NonClientDecorView xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.internal.widget.DecorCaptionView xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
@@ -26,7 +26,7 @@
         android:layout_width="match_parent"
         android:layout_gravity="end"
         android:layout_height="wrap_content"
-        android:background="@drawable/non_client_decor_title"
+        android:background="@drawable/decor_caption_title"
         android:focusable="false"
         android:descendantFocusability="blocksDescendants" >
         <LinearLayout
@@ -53,4 +53,4 @@
             android:contentDescription="@string/close_button_text"
             android:background="@drawable/decor_close_button_dark" />
     </LinearLayout>
-</com.android.internal.widget.NonClientDecorView>
+</com.android.internal.widget.DecorCaptionView>
diff --git a/core/res/res/layout/non_client_decor_light.xml b/core/res/res/layout/decor_caption_light.xml
similarity index 90%
rename from core/res/res/layout/non_client_decor_light.xml
rename to core/res/res/layout/decor_caption_light.xml
index c75d526..ee03545 100644
--- a/core/res/res/layout/non_client_decor_light.xml
+++ b/core/res/res/layout/decor_caption_light.xml
@@ -17,7 +17,7 @@
 */
 -->
 
-<com.android.internal.widget.NonClientDecorView xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.internal.widget.DecorCaptionView xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
@@ -26,7 +26,7 @@
         android:layout_width="match_parent"
         android:layout_gravity="end"
         android:layout_height="wrap_content"
-        android:background="@drawable/non_client_decor_title"
+        android:background="@drawable/decor_caption_title"
         android:focusable="false"
         android:descendantFocusability="blocksDescendants" >
         <LinearLayout
@@ -53,4 +53,4 @@
             android:contentDescription="@string/close_button_text"
             android:background="@drawable/decor_close_button_light" />
     </LinearLayout>
-</com.android.internal.widget.NonClientDecorView>
+</com.android.internal.widget.DecorCaptionView>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 556467a..7ce9d8d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1957,9 +1957,9 @@
   <java-symbol type="id" name="maximize_window" />
   <java-symbol type="id" name="close_window" />
   <java-symbol type="id" name="client_decor_placeholder" />
-  <java-symbol type="layout" name="non_client_decor_light" />
-  <java-symbol type="layout" name="non_client_decor_dark" />
-  <java-symbol type="drawable" name="non_client_decor_title_focused" />
+  <java-symbol type="layout" name="decor_caption_light" />
+  <java-symbol type="layout" name="decor_caption_dark" />
+  <java-symbol type="drawable" name="decor_caption_title_focused" />
 
   <!-- From TelephonyProvider -->
   <java-symbol type="xml" name="apns" />