Merge "add DeviceInfo"
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ba28e81..b62a5ee 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1450,6 +1450,8 @@
   <java-symbol type="anim" name="dock_left_exit" />
   <java-symbol type="anim" name="dock_right_enter" />
   <java-symbol type="anim" name="dock_right_exit" />
+  <java-symbol type="anim" name="fade_in" />
+  <java-symbol type="anim" name="fade_out" />
   <java-symbol type="anim" name="voice_activity_close_exit" />
   <java-symbol type="anim" name="voice_activity_close_enter" />
   <java-symbol type="anim" name="voice_activity_open_exit" />
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index 1770a06..cd47ac1 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -70,9 +70,7 @@
     private static final int SECONDS_MS = 1000;
     private static final int MINUTES_MS = 60 * SECONDS_MS;
 
-    private static final int[] MINUTE_BUCKETS = DEBUG
-            ? new int[] { 0, 1, 2, 5, 15, 30, 45, 60, 120, 180, 240, 480 }
-            : ZenModeConfig.MINUTE_BUCKETS;
+    private static final int[] MINUTE_BUCKETS = ZenModeConfig.MINUTE_BUCKETS;
     private static final int MIN_BUCKET_MINUTES = MINUTE_BUCKETS[0];
     private static final int MAX_BUCKET_MINUTES = MINUTE_BUCKETS[MINUTE_BUCKETS.length - 1];
     private static final int DEFAULT_BUCKET_INDEX = Arrays.binarySearch(MINUTE_BUCKETS, 60);
@@ -604,13 +602,6 @@
         if (DEBUG) Log.d(mTag, "bind i=" + mZenConditions.indexOfChild(row) + " first=" + first
                 + " condition=" + conditionId);
         tag.rb.setEnabled(enabled);
-        final boolean checked = (mSessionExitCondition != null
-                    || mAttachedZen != Global.ZEN_MODE_OFF)
-                && (sameConditionId(mSessionExitCondition, tag.condition));
-        if (checked != tag.rb.isChecked()) {
-            if (DEBUG) Log.d(mTag, "bind checked=" + checked + " condition=" + conditionId);
-            tag.rb.setChecked(checked);
-        }
         tag.rb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
             @Override
             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 209751e..121ef21 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2532,6 +2532,12 @@
                     return R.anim.dock_right_enter;
                 }
             }
+        } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) {
+            if (transit == TRANSIT_ENTER) {
+                return R.anim.fade_in;
+            } else if (transit == TRANSIT_EXIT) {
+                return R.anim.fade_out;
+            }
         }
 
         if (transit == TRANSIT_PREVIEW_DONE) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 9143097..58ba24e 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -274,11 +274,11 @@
             // If we're animating with a saved surface, we're already visible.
             // Return true so that the alpha doesn't get cleared.
             if (!win.mAppFreezing
-                    && (win.mViewVisibility == View.VISIBLE
-                    || mAnimatingWithSavedSurface
-                    || (win.mWinAnimator.isAnimating() &&
-                            !service.mAppTransition.isTransitionSet()))
-                    && !win.mDestroying && win.isDrawnLw()) {
+                    && (win.mViewVisibility == View.VISIBLE || mAnimatingWithSavedSurface
+                            || (win.mWinAnimator.isAnimating()
+                                    && !service.mAppTransition.isTransitionSet()))
+                    && !win.mDestroying
+                    && win.isDrawnLw()) {
                 return true;
             }
         }
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index eafc3c6..77ae35a 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -122,10 +122,10 @@
         if (forceUpdate && mView != null) {
             removeDivider();
         }
-        TaskStack stack = mDisplayContent.getDockedStackLocked();
-        if (stack != null && mView == null) {
+        TaskStack stack = mDisplayContent.mService.mStackIdToStack.get(DOCKED_STACK_ID);
+        if (stack != null && stack.hasWindowWithFinalVisibility() && mView == null) {
             addDivider(configuration);
-        } else if (stack == null && mView != null) {
+        } else if ((stack == null || !stack.isVisibleLocked()) && mView != null) {
             removeDivider();
         }
     }
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index f72384c..bb3d6f7 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -700,4 +700,26 @@
         }
         return false;
     }
+
+    /**
+     * Returns true if this stack has a window that is fully visible, doesn't perform an entry
+     * animation and is just positioned where it's supposed to be.
+     */
+    boolean hasWindowWithFinalVisibility() {
+        for (int i = mTasks.size() - 1; i >= 0; i--) {
+            Task task = mTasks.get(i);
+            for (int j = task.mAppTokens.size() - 1; j >= 0; j--) {
+                final AppWindowToken token = task.mAppTokens.get(j);
+                if (token.mAppAnimator.animating || token.mWillReplaceWindow) {
+                    continue;
+                }
+                WindowState win = token.findMainWindow();
+                if (win != null && !win.mWinAnimator.mEnterAnimationPending
+                        && !win.mWinAnimator.mEnteringAnimation) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b3f9ddb..3da6dee 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -19,6 +19,7 @@
 import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.StatusBarManager.DISABLE_MASK;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
@@ -31,8 +32,6 @@
 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
-import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
-import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
@@ -46,6 +45,8 @@
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY;
+import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
 import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
 
 import static com.android.server.wm.WindowState.BOUNDS_FOR_TOUCH;
@@ -2537,11 +2538,8 @@
             Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
             Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Configuration outConfig,
             Surface outSurface) {
-        boolean toBeDisplayed = false;
-        boolean inTouchMode;
+        int result = 0;
         boolean configChanged;
-        boolean surfaceChanged = false;
-        boolean dragResizing = false;
         boolean hasStatusBarPermission =
                 mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR)
                         == PackageManager.PERMISSION_GRANTED;
@@ -2558,31 +2556,21 @@
                 win.setRequestedSize(requestedWidth, requestedHeight);
             }
 
-            if (attrs != null) {
-                mPolicy.adjustWindowParamsLw(attrs);
-            }
-
-            // if they don't have the permission, mask out the status bar bits
-            int systemUiVisibility = 0;
-            if (attrs != null) {
-                systemUiVisibility = (attrs.systemUiVisibility|attrs.subtreeSystemUiVisibility);
-                if ((systemUiVisibility & StatusBarManager.DISABLE_MASK) != 0) {
-                    if (!hasStatusBarPermission) {
-                        systemUiVisibility &= ~StatusBarManager.DISABLE_MASK;
-                    }
-                }
-            }
-
-            if (attrs != null && seq == win.mSeq) {
-                win.mSystemUiVisibility = systemUiVisibility;
-            }
-
-            winAnimator.mSurfaceDestroyDeferred =
-                    (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
-
             int attrChanges = 0;
             int flagChanges = 0;
             if (attrs != null) {
+                mPolicy.adjustWindowParamsLw(attrs);
+                // if they don't have the permission, mask out the status bar bits
+                if (seq == win.mSeq) {
+                    int systemUiVisibility = attrs.systemUiVisibility
+                            | attrs.subtreeSystemUiVisibility;
+                    if ((systemUiVisibility & DISABLE_MASK) != 0) {
+                        if (!hasStatusBarPermission) {
+                            systemUiVisibility &= ~DISABLE_MASK;
+                        }
+                    }
+                    win.mSystemUiVisibility = systemUiVisibility;
+                }
                 if (win.mAttrs.type != attrs.type) {
                     throw new IllegalArgumentException(
                             "Window type can not be changed after the window is added.");
@@ -2597,30 +2585,15 @@
 
             if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility
                     + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
-
+            winAnimator.mSurfaceDestroyDeferred = (flags & RELAYOUT_DEFER_SURFACE_DESTROY) != 0;
             win.mEnforceSizeCompat =
                     (win.mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
-
             if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
                 winAnimator.mAlpha = attrs.alpha;
             }
-
-            final boolean scaledWindow =
-                ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0);
-
-            if (scaledWindow) {
-                // requested{Width|Height} Surface's physical size
-                // attrs.{width|height} Size on screen
-                win.mHScale = (attrs.width  != requestedWidth)  ?
-                        (attrs.width  / (float)requestedWidth) : 1.0f;
-                win.mVScale = (attrs.height != requestedHeight) ?
-                        (attrs.height / (float)requestedHeight) : 1.0f;
-            } else {
-                win.mHScale = win.mVScale = 1;
-            }
+            win.setWindowScale(requestedWidth, requestedHeight);
 
             boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0;
-
             final boolean isDefaultDisplay = win.isDefaultDisplay();
             boolean focusMayChange = isDefaultDisplay && (win.mViewVisibility != viewVisibility
                     || ((flagChanges & FLAG_NOT_FOCUSABLE) != 0)
@@ -2644,78 +2617,10 @@
             }
             if (viewVisibility == View.VISIBLE &&
                     (win.mAppToken == null || !win.mAppToken.clientHidden)) {
-                toBeDisplayed = !win.isVisibleLw();
-                if (win.mExiting) {
-                    winAnimator.cancelExitAnimationForNextAnimationLocked();
-                    win.mExiting = false;
-                }
-                if (win.mDestroying) {
-                    win.mDestroying = false;
-                    mDestroySurface.remove(win);
-                }
-                if (oldVisibility == View.GONE) {
-                    winAnimator.mEnterAnimationPending = true;
-                }
-                winAnimator.mEnteringAnimation = true;
-                if (toBeDisplayed) {
-                    if ((win.mAttrs.softInputMode & SOFT_INPUT_MASK_ADJUST)
-                            == SOFT_INPUT_ADJUST_RESIZE) {
-                        win.mLayoutNeeded = true;
-                    }
-                    if (win.isDrawnLw() && okToDisplay()) {
-                        winAnimator.applyEnterAnimationLocked();
-                    }
-                    if ((win.mAttrs.flags
-                            & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
-                        if (DEBUG_VISIBILITY) Slog.v(TAG,
-                                "Relayout window turning screen on: " + win);
-                        win.mTurnOnScreen = true;
-                    }
-                    if (win.isConfigChanged()) {
-                        if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + win
-                                + " visible with new config: " + mCurConfiguration);
-                        outConfig.setTo(mCurConfiguration);
-                    }
-                }
-                if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
-                    // If the format can be changed in place yaay!
-                    // If not, fall back to a surface re-build
-                    if (!winAnimator.tryChangeFormatInPlaceLocked()) {
-                        winAnimator.destroySurfaceLocked();
-                        toBeDisplayed = true;
-                        surfaceChanged = true;
-                    }
-                }
-
-                // If we're starting a drag-resize, we'll be changing the surface size as well as
-                // notifying the client to render to with an offset from the surface's top-left.
-                if (win.isDragResizeChanged()) {
-                    win.setDragResizing();
-                    if (win.mHasSurface) {
-                        winAnimator.preserveSurfaceLocked();
-                        toBeDisplayed = true;
-                    }
-                }
-                dragResizing = win.isDragResizing();
-                if (win.isAnimatingWithSavedSurface()) {
-                    // If we're animating with a saved surface now, request client to report draw.
-                    // We still need to know when the real thing is drawn.
-                    toBeDisplayed = true;
-                }
+                result = relayoutVisibleWindow(outConfig, result, win, winAnimator, attrChanges,
+                        oldVisibility);
                 try {
-                    if (!win.mHasSurface) {
-                        surfaceChanged = true;
-                    }
-                    SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
-                    if (surfaceControl != null) {
-                        outSurface.copyFrom(surfaceControl);
-                        if (SHOW_TRANSACTIONS) Slog.i(TAG,
-                                "  OUT SURFACE " + outSurface + ": copied");
-                    } else {
-                        // For some reason there isn't a surface.  Clear the
-                        // caller's object so they see the same state.
-                        outSurface.release();
-                    }
+                    result = createSurfaceControl(outSurface, result, win, winAnimator);
                 } catch (Exception e) {
                     mInputMonitor.updateInputWindowsLw(true /*force*/);
 
@@ -2725,27 +2630,14 @@
                     Binder.restoreCallingIdentity(origId);
                     return 0;
                 }
-                if (toBeDisplayed) {
+                if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
                     focusMayChange = isDefaultDisplay;
                 }
-                if (win.mAttrs.type == TYPE_INPUT_METHOD
-                        && mInputMethodWindow == null) {
+                if (win.mAttrs.type == TYPE_INPUT_METHOD && mInputMethodWindow == null) {
                     mInputMethodWindow = win;
                     imMayMove = true;
                 }
-                if (win.mAttrs.type == TYPE_BASE_APPLICATION
-                        && win.mAppToken != null
-                        && win.mAppToken.startingWindow != null) {
-                    // Special handling of starting window over the base
-                    // window of the app: propagate lock screen flags to it,
-                    // to provide the correct semantics while starting.
-                    final int mask =
-                        WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
-                        | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
-                        | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
-                    WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs;
-                    sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask);
-                }
+                win.adjustStartingWindowFlags();
             } else {
                 winAnimator.mEnterAnimationPending = false;
                 winAnimator.mEnteringAnimation = false;
@@ -2759,41 +2651,14 @@
                     // don't want to destroy the saved surface.
                     // If we are not currently running the exit animation, we
                     // need to see about starting one.
-                    if (!win.mExiting && !win.isAnimatingWithSavedSurface()) {
-                        surfaceChanged = true;
-                        // Try starting an animation; if there isn't one, we
-                        // can destroy the surface right away.
-                        int transit = WindowManagerPolicy.TRANSIT_EXIT;
-                        if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
-                            transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
-                        }
-                        if (win.isWinVisibleLw() &&
-                                winAnimator.applyAnimationLocked(transit, false)) {
-                            focusMayChange = isDefaultDisplay;
-                            win.mExiting = true;
-                        } else if (win.mWinAnimator.isAnimating()) {
-                            // Currently in a hide animation... turn this into
-                            // an exit.
-                            win.mExiting = true;
-                        } else if (mWallpaperControllerLocked.isWallpaperTarget(win)) {
-                            // If the wallpaper is currently behind this
-                            // window, we need to change both of them inside
-                            // of a transaction to avoid artifacts.
-                            win.mExiting = true;
-                            win.mWinAnimator.mAnimating = true;
-                        } else {
-                            if (mInputMethodWindow == win) {
-                                mInputMethodWindow = null;
-                            }
-                            if (!win.shouldSaveSurface()) {
-                                winAnimator.destroySurfaceLocked();
-                            }
-                        }
-                        //TODO (multidisplay): Magnification is supported only for the default
-                        if (mAccessibilityController != null
-                                && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
-                            mAccessibilityController.onWindowTransitionLocked(win, transit);
-                        }
+                    final boolean notExitingOrAnimating =
+                            !win.mExiting && !win.isAnimatingWithSavedSurface();
+                    result |= notExitingOrAnimating
+                            ? RELAYOUT_RES_SURFACE_CHANGED : 0;
+                    if (notExitingOrAnimating) {
+                        focusMayChange = tryStartingAnimation(win, winAnimator, isDefaultDisplay,
+                                focusMayChange);
+
                     }
                 }
 
@@ -2812,6 +2677,7 @@
 
             // updateFocusedWindowLocked() already assigned layers so we only need to
             // reassign them at this point if the IM window state gets shuffled
+            boolean toBeDisplayed = (result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
             if (imMayMove && (moveInputMethodWindowsIfNeededLocked(false) || toBeDisplayed)) {
                 // Little hack here -- we -should- be able to rely on the
                 // function to return true if the IME has moved and needs
@@ -2855,7 +2721,7 @@
             if (localLOGV || DEBUG_FOCUS) Slog.v(
                 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
 
-            inTouchMode = mInTouchMode;
+            result |= mInTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0;
 
             mInputMonitor.updateInputWindowsLw(true /*force*/);
 
@@ -2867,13 +2733,108 @@
         if (configChanged) {
             sendNewConfiguration();
         }
-
         Binder.restoreCallingIdentity(origId);
+        return result;
+    }
 
-        return (inTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0)
-                | (toBeDisplayed ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0)
-                | (surfaceChanged ? WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED : 0)
-                | (dragResizing ? WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING : 0);
+    private boolean tryStartingAnimation(WindowState win, WindowStateAnimator winAnimator,
+            boolean isDefaultDisplay, boolean focusMayChange) {
+        // Try starting an animation; if there isn't one, we
+        // can destroy the surface right away.
+        int transit = WindowManagerPolicy.TRANSIT_EXIT;
+        if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
+            transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
+        }
+        if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) {
+            focusMayChange = isDefaultDisplay;
+            win.mExiting = true;
+        } else if (win.mWinAnimator.isAnimating()) {
+            // Currently in a hide animation... turn this into
+            // an exit.
+            win.mExiting = true;
+        } else if (mWallpaperControllerLocked.isWallpaperTarget(win)) {
+            // If the wallpaper is currently behind this
+            // window, we need to change both of them inside
+            // of a transaction to avoid artifacts.
+            win.mExiting = true;
+            win.mWinAnimator.mAnimating = true;
+        } else {
+            if (mInputMethodWindow == win) {
+                mInputMethodWindow = null;
+            }
+            if (!win.shouldSaveSurface()) {
+                winAnimator.destroySurfaceLocked();
+            }
+        }
+        //TODO (multidisplay): Magnification is supported only for the default
+        if (mAccessibilityController != null
+                && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
+            mAccessibilityController.onWindowTransitionLocked(win, transit);
+        }
+        return focusMayChange;
+    }
+
+    private int createSurfaceControl(Surface outSurface, int result, WindowState win,
+            WindowStateAnimator winAnimator) {
+        if (!win.mHasSurface) {
+            result |= RELAYOUT_RES_SURFACE_CHANGED;
+        }
+        SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
+        if (surfaceControl != null) {
+            outSurface.copyFrom(surfaceControl);
+            if (SHOW_TRANSACTIONS) Slog.i(TAG, "  OUT SURFACE " + outSurface + ": copied");
+        } else {
+            // For some reason there isn't a surface.  Clear the
+            // caller's object so they see the same state.
+            outSurface.release();
+        }
+        return result;
+    }
+
+    private int relayoutVisibleWindow(Configuration outConfig, int result, WindowState win,
+            WindowStateAnimator winAnimator, int attrChanges, int oldVisibility) {
+        result |= !win.isVisibleLw() ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0;
+        if (win.mExiting) {
+            winAnimator.cancelExitAnimationForNextAnimationLocked();
+            win.mExiting = false;
+        }
+        if (win.mDestroying) {
+            win.mDestroying = false;
+            mDestroySurface.remove(win);
+        }
+        if (oldVisibility == View.GONE) {
+            winAnimator.mEnterAnimationPending = true;
+        }
+        winAnimator.mEnteringAnimation = true;
+        if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
+            win.prepareWindowToDisplayDuringRelayout(outConfig);
+        }
+        if ((attrChanges& LayoutParams.FORMAT_CHANGED) != 0) {
+            // If the format can be changed in place yaay!
+            // If not, fall back to a surface re-build
+            if (!winAnimator.tryChangeFormatInPlaceLocked()) {
+                winAnimator.destroySurfaceLocked();
+                result |= RELAYOUT_RES_SURFACE_CHANGED
+                        | WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
+            }
+        }
+
+        // If we're starting a drag-resize, we'll be changing the surface size as well as
+        // notifying the client to render to with an offset from the surface's top-left.
+        if (win.isDragResizeChanged()) {
+            win.setDragResizing();
+            if (win.mHasSurface) {
+                winAnimator.preserveSurfaceLocked();
+                result |= WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
+            }
+        }
+        result |= win.isDragResizing() ? WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING : 0;
+        if (win.isAnimatingWithSavedSurface()) {
+            // If we're animating with a saved surface now, request client to report draw.
+            // We still need to know when the real thing is drawn.
+            result |= WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
+        }
+        return result;
     }
 
     public void performDeferredDestroyWindow(Session session, IWindow client) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 3b0fc4f..03a8ab5 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -18,12 +18,19 @@
 
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
 import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
+import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
+import static android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
@@ -606,7 +613,7 @@
         final int ph = mContainingFrame.height();
 
         int w,h;
-        if ((mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0) {
+        if ((mAttrs.flags & FLAG_SCALED) != 0) {
             if (mAttrs.width < 0) {
                 w = pw;
             } else if (mEnforceSizeCompat) {
@@ -1447,6 +1454,54 @@
         }
     }
 
+    void prepareWindowToDisplayDuringRelayout(Configuration outConfig) {
+        if ((mAttrs.softInputMode & SOFT_INPUT_MASK_ADJUST)
+                == SOFT_INPUT_ADJUST_RESIZE) {
+            mLayoutNeeded = true;
+        }
+        if (isDrawnLw() && mService.okToDisplay()) {
+            mWinAnimator.applyEnterAnimationLocked();
+        }
+        if ((mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0) {
+            if (DEBUG_VISIBILITY) Slog.v(TAG, "Relayout window turning screen on: " + this);
+            mTurnOnScreen = true;
+        }
+        if (isConfigChanged()) {
+            if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + this + " visible with new config: "
+                    + mService.mCurConfiguration);
+            outConfig.setTo(mService.mCurConfiguration);
+        }
+    }
+
+    void adjustStartingWindowFlags() {
+        if (mAttrs.type == TYPE_BASE_APPLICATION && mAppToken != null
+                && mAppToken.startingWindow != null) {
+            // Special handling of starting window over the base
+            // window of the app: propagate lock screen flags to it,
+            // to provide the correct semantics while starting.
+            final int mask = FLAG_SHOW_WHEN_LOCKED | FLAG_DISMISS_KEYGUARD
+                    | FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
+            WindowManager.LayoutParams sa = mAppToken.startingWindow.mAttrs;
+            sa.flags = (sa.flags & ~mask) | (mAttrs.flags & mask);
+        }
+    }
+
+    void setWindowScale(int requestedWidth, int requestedHeight) {
+        final boolean scaledWindow = (mAttrs.flags & FLAG_SCALED) != 0;
+
+        if (scaledWindow) {
+            // requested{Width|Height} Surface's physical size
+            // attrs.{width|height} Size on screen
+            // TODO: We don't check if attrs != null here. Is it implicitly checked?
+            mHScale = (mAttrs.width  != requestedWidth)  ?
+                    (mAttrs.width  / (float)requestedWidth) : 1.0f;
+            mVScale = (mAttrs.height != requestedHeight) ?
+                    (mAttrs.height / (float)requestedHeight) : 1.0f;
+        } else {
+            mHScale = mVScale = 1;
+        }
+    }
+
     private class DeathRecipient implements IBinder.DeathRecipient {
         @Override
         public void binderDied() {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index ec97ba8..9f37169 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -437,11 +437,16 @@
             mWin.mChildWindows.get(i).mWinAnimator.finishExit();
         }
 
-        if (mEnteringAnimation && mWin.mAppToken == null) {
-            try {
-                mEnteringAnimation = false;
-                mWin.mClient.dispatchWindowShown();
-            } catch (RemoteException e) {
+        if (mEnteringAnimation) {
+            mEnteringAnimation = false;
+            mService.requestTraversal();
+            // System windows don't have an activity and an app token as a result, but need a way
+            // to be informed about their entrance animation end.
+            if (mWin.mAppToken == null) {
+                try {
+                    mWin.mClient.dispatchWindowShown();
+                } catch (RemoteException e) {
+                }
             }
         }
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java
index 9588035..80d7c68 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java
@@ -21,6 +21,7 @@
 
 import android.graphics.BlendComposite;
 import android.graphics.BlendComposite.BlendingMode;
+import android.graphics.PorterDuff;
 import android.graphics.PorterDuff.Mode;
 import android.graphics.PorterDuffColorFilter_Delegate;
 import android.graphics.PorterDuffXfermode_Delegate;
@@ -34,6 +35,8 @@
  */
 public final class PorterDuffUtility {
 
+    private static final int MODES_COUNT = Mode.values().length;
+
     // Make the class non-instantiable.
     private PorterDuffUtility() {
     }
@@ -43,12 +46,11 @@
      * {@link Mode#SRC_OVER} for invalid modes.
      */
     public static Mode getPorterDuffMode(int porterDuffMode) {
-        Mode[] values = Mode.values();
-        if (porterDuffMode >= 0 && porterDuffMode < values.length) {
-            return values[porterDuffMode];
+        if (porterDuffMode >= 0 && porterDuffMode < MODES_COUNT) {
+            return PorterDuff.intToMode(porterDuffMode);
         }
         Bridge.getLog().error(LayoutLog.TAG_BROKEN,
-                String.format("Unknown PorterDuff.Mode: %1$d", porterDuffMode), null /*data*/);
+                String.format("Unknown PorterDuff.Mode: %1$d", porterDuffMode), null);
         assert false;
         return Mode.SRC_OVER;
     }