Merge "Mechanical code clean-ups in MSG_UNBIND handler."
diff --git a/core/jni/android_util_PathParser.cpp b/core/jni/android_util_PathParser.cpp
index bf6ffc54..245aa0f 100644
--- a/core/jni/android_util_PathParser.cpp
+++ b/core/jni/android_util_PathParser.cpp
@@ -19,6 +19,7 @@
#include <PathParser.h>
#include <SkPath.h>
+#include <android/log.h>
#include "core_jni_helpers.h"
namespace android {
@@ -27,10 +28,14 @@
jint strLength) {
const char* pathString = env->GetStringUTFChars(inputPathStr, NULL);
SkPath* skPath = reinterpret_cast<SkPath*>(skPathHandle);
- bool hasValidData = android::uirenderer::PathParser::parseStringForSkPath(skPath, pathString,
- strLength);
+
+ android::uirenderer::PathParser::ParseResult result;
+ android::uirenderer::PathParser::parseStringForSkPath(skPath, &result, pathString, strLength);
env->ReleaseStringUTFChars(inputPathStr, pathString);
- return hasValidData;
+ if (result.failureOccurred) {
+ ALOGE(result.failureMessage.c_str());
+ }
+ return !result.failureOccurred;
}
static const JNINativeMethod gMethods[] = {
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 9c75b7a..b87d9e2 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -411,7 +411,7 @@
<bool translatable="false" name="config_wifi_revert_country_code_on_cellular_loss">false</bool>
<!-- Boolean indicating whether or not wifi firmware debugging is enabled -->
- <bool translatable="false" name="config_wifi_enable_wifi_firmware_debugging">false</bool>
+ <bool translatable="false" name="config_wifi_enable_wifi_firmware_debugging">true</bool>
<!-- Integer specifying the basic autojoin parameters -->
<integer translatable="false" name="config_wifi_framework_5GHz_preference_boost_threshold">-65</integer>
diff --git a/libs/hwui/PathParser.cpp b/libs/hwui/PathParser.cpp
index 61b9d21..35230ff 100644
--- a/libs/hwui/PathParser.cpp
+++ b/libs/hwui/PathParser.cpp
@@ -18,6 +18,7 @@
#include "jni.h"
+#include <errno.h>
#include <utils/Log.h>
#include <sstream>
#include <stdlib.h>
@@ -97,14 +98,31 @@
*outEndPosition = currentIndex;
}
+static float parseFloat(PathParser::ParseResult* result, const char* startPtr, size_t expectedLength) {
+ char* endPtr = NULL;
+ float currentValue = strtof(startPtr, &endPtr);
+ if ((currentValue == HUGE_VALF || currentValue == -HUGE_VALF) && errno == ERANGE) {
+ result->failureOccurred = true;
+ result->failureMessage = "Float out of range: ";
+ result->failureMessage.append(startPtr, expectedLength);
+ }
+ if (currentValue == 0 && endPtr == startPtr) {
+ // No conversion is done.
+ result->failureOccurred = true;
+ result->failureMessage = "Float format error when parsing: ";
+ result->failureMessage.append(startPtr, expectedLength);
+ }
+ return currentValue;
+}
+
/**
-* Parse the floats in the string.
-* This is an optimized version of parseFloat(s.split(",|\\s"));
-*
-* @param s the string containing a command and list of floats
-* @return array of floats
-*/
-static void getFloats(std::vector<float>* outPoints, const char* pathStr, int start, int end) {
+ * Parse the floats in the string.
+ *
+ * @param s the string containing a command and list of floats
+ * @return true on success
+ */
+static void getFloats(std::vector<float>* outPoints, PathParser::ParseResult* result,
+ const char* pathStr, int start, int end) {
if (pathStr[start] == 'z' || pathStr[start] == 'Z') {
return;
@@ -120,7 +138,12 @@
extract(&endPosition, &endWithNegOrDot, pathStr, startPosition, end);
if (startPosition < endPosition) {
- outPoints->push_back(strtof(&pathStr[startPosition], NULL));
+ float currentValue = parseFloat(result, &pathStr[startPosition],
+ end - startPosition);
+ if (result->failureOccurred) {
+ return;
+ }
+ outPoints->push_back(currentValue);
}
if (endWithNegOrDot) {
@@ -130,10 +153,14 @@
startPosition = endPosition + 1;
}
}
+ return;
}
-void PathParser::getPathDataFromString(PathData* data, const char* pathStr, size_t strLen) {
+void PathParser::getPathDataFromString(PathData* data, ParseResult* result,
+ const char* pathStr, size_t strLen) {
if (pathStr == NULL) {
+ result->failureOccurred = true;
+ result->failureMessage = "Path string cannot be NULL.";
return;
}
@@ -143,7 +170,10 @@
while (end < strLen) {
end = nextStart(pathStr, strLen, end);
std::vector<float> points;
- getFloats(&points, pathStr, start, end);
+ getFloats(&points, result, pathStr, start, end);
+ if (result->failureOccurred) {
+ return;
+ }
data->verbs.push_back(pathStr[start]);
data->verbSizes.push_back(points.size());
data->points.insert(data->points.end(), points.begin(), points.end());
@@ -151,16 +181,11 @@
end++;
}
- if ((end - start) == 1 && pathStr[start] != '\0') {
+ if ((end - start) == 1 && start < strLen) {
data->verbs.push_back(pathStr[start]);
data->verbSizes.push_back(0);
}
-
- int i = 0;
- while(pathStr[i] != '\0') {
- i++;
- }
-
+ return;
}
void PathParser::dump(const PathData& data) {
@@ -169,6 +194,7 @@
for (size_t i = 0; i < data.verbs.size(); i++) {
std::ostringstream os;
os << data.verbs[i];
+ os << ", verb size: " << data.verbSizes[i];
for (size_t j = 0; j < data.verbSizes[i]; j++) {
os << " " << data.points[start + j];
}
@@ -183,16 +209,20 @@
ALOGD("points are : %s", os.str().c_str());
}
-bool PathParser::parseStringForSkPath(SkPath* skPath, const char* pathStr, size_t strLen) {
+void PathParser::parseStringForSkPath(SkPath* skPath, ParseResult* result, const char* pathStr, size_t strLen) {
PathData pathData;
- getPathDataFromString(&pathData, pathStr, strLen);
-
+ getPathDataFromString(&pathData, result, pathStr, strLen);
+ if (result->failureOccurred) {
+ return;
+ }
// Check if there is valid data coming out of parsing the string.
if (pathData.verbs.size() == 0) {
- return false;
+ result->failureOccurred = true;
+ result->failureMessage = "No verbs found in the string for pathData";
+ return;
}
VectorDrawablePath::verbsToPath(skPath, &pathData);
- return true;
+ return;
}
}; // namespace uirenderer
diff --git a/libs/hwui/PathParser.h b/libs/hwui/PathParser.h
index d30bb0f..a9c1e60 100644
--- a/libs/hwui/PathParser.h
+++ b/libs/hwui/PathParser.h
@@ -23,17 +23,25 @@
#include <android/log.h>
#include <cutils/compiler.h>
+#include <string>
+
namespace android {
namespace uirenderer {
+
class PathParser {
public:
+ struct ANDROID_API ParseResult {
+ bool failureOccurred = false;
+ std::string failureMessage;
+ };
/**
* Parse the string literal and create a Skia Path. Return true on success.
*/
- ANDROID_API static bool parseStringForSkPath(SkPath* outPath, const char* pathStr,
- size_t strLength);
- static void getPathDataFromString(PathData* outData, const char* pathStr, size_t strLength);
+ ANDROID_API static void parseStringForSkPath(SkPath* outPath, ParseResult* result,
+ const char* pathStr, size_t strLength);
+ static void getPathDataFromString(PathData* outData, ParseResult* result,
+ const char* pathStr, size_t strLength);
static void dump(const PathData& data);
};
diff --git a/libs/hwui/VectorDrawablePath.cpp b/libs/hwui/VectorDrawablePath.cpp
index 115435c..05ea2da 100644
--- a/libs/hwui/VectorDrawablePath.cpp
+++ b/libs/hwui/VectorDrawablePath.cpp
@@ -37,8 +37,11 @@
};
VectorDrawablePath::VectorDrawablePath(const char* pathStr, size_t strLength) {
- PathParser::getPathDataFromString(&mData, pathStr, strLength);
- verbsToPath(&mSkPath, &mData);
+ PathParser::ParseResult result;
+ PathParser::getPathDataFromString(&mData, &result, pathStr, strLength);
+ if (!result.failureOccurred) {
+ verbsToPath(&mSkPath, &mData);
+ }
}
VectorDrawablePath::VectorDrawablePath(const PathData& data) {
@@ -80,7 +83,7 @@
for (unsigned int i = 0; i < data->verbs.size(); i++) {
size_t verbSize = data->verbSizes[i];
resolver.addCommand(outPath, previousCommand, data->verbs[i], &data->points, start,
- start + verbSize - 1u);
+ start + verbSize);
previousCommand = data->verbs[i];
start += verbSize;
}
@@ -254,7 +257,7 @@
arcToBezier(p, cx, cy, a, b, x0, y0, thetaD, eta0, sweep);
}
-
+// Use the given verb, and points in the range [start, end) to insert a command into the SkPath.
void PathResolver::addCommand(SkPath* outPath, char previousCmd,
char cmd, const std::vector<float>* points, size_t start, size_t end) {
@@ -305,7 +308,7 @@
break;
}
- for (unsigned int k = start; k <= end; k += incr) {
+ for (unsigned int k = start; k < end; k += incr) {
switch (cmd) {
case 'm': // moveto - Start a new sub-path (relative)
currentX += points->at(k + 0);
diff --git a/libs/hwui/microbench/PathParserBench.cpp b/libs/hwui/microbench/PathParserBench.cpp
index 198035e..171078d 100644
--- a/libs/hwui/microbench/PathParserBench.cpp
+++ b/libs/hwui/microbench/PathParserBench.cpp
@@ -28,9 +28,10 @@
const char* pathString = "M 1 1 m 2 2, l 3 3 L 3 3 H 4 h4 V5 v5, Q6 6 6 6 q 6 6 6 6t 7 7 T 7 7 C 8 8 8 8 8 8 c 8 8 8 8 8 8 S 9 9 9 9 s 9 9 9 9 A 10 10 0 1 1 10 10 a 10 10 0 1 1 10 10";
SkPath skPath;
size_t length = strlen(pathString);
+ PathParser::ParseResult result;
StartBenchmarkTiming();
for (int i = 0; i < iter; i++) {
- PathParser::parseStringForSkPath(&skPath, pathString, length);
+ PathParser::parseStringForSkPath(&skPath, &result, pathString, length);
}
StopBenchmarkTiming();
}
diff --git a/libs/hwui/unit_tests/PathParserTests.cpp b/libs/hwui/unit_tests/PathParserTests.cpp
index 60ea219..c99d7b0 100644
--- a/libs/hwui/unit_tests/PathParserTests.cpp
+++ b/libs/hwui/unit_tests/PathParserTests.cpp
@@ -164,16 +164,37 @@
};
+struct StringPath {
+ const char* stringPath;
+ bool isValid;
+};
+
+const StringPath sStringPaths[] = {
+ {"3e...3", false},
+ {"L.M.F.A.O", false},
+ {"m 1 1", true},
+ {"z", true},
+ {"1-2e34567", false}
+};
+
TEST(PathParser, parseStringForData) {
for (TestData testData: sTestDataSet) {
+ PathParser::ParseResult result;
// Test generated path data against the given data.
PathData pathData;
size_t length = strlen(testData.pathString);
- PathParser::getPathDataFromString(&pathData, testData.pathString, length);
- PathParser::dump(pathData);
+ PathParser::getPathDataFromString(&pathData, &result, testData.pathString, length);
EXPECT_EQ(testData.pathData, pathData);
}
+ for (StringPath stringPath : sStringPaths) {
+ PathParser::ParseResult result;
+ PathData pathData;
+ SkPath skPath;
+ PathParser::getPathDataFromString(&pathData, &result,
+ stringPath.stringPath, strlen(stringPath.stringPath));
+ EXPECT_EQ(stringPath.isValid, !result.failureOccurred);
+ }
}
TEST(PathParser, createSkPathFromPathData) {
@@ -188,21 +209,25 @@
TEST(PathParser, parseStringForSkPath) {
for (TestData testData: sTestDataSet) {
+ PathParser::ParseResult result;
size_t length = strlen(testData.pathString);
// Check the return value as well as the SkPath generated.
SkPath actualPath;
- bool hasValidData = PathParser::parseStringForSkPath(&actualPath, testData.pathString,
- length);
+ PathParser::parseStringForSkPath(&actualPath, &result, testData.pathString, length);
+ bool hasValidData = !result.failureOccurred;
EXPECT_EQ(hasValidData, testData.pathData.verbs.size() > 0);
SkPath expectedPath;
testData.skPathLamda(&expectedPath);
EXPECT_EQ(expectedPath, actualPath);
}
- SkPath path;
- EXPECT_FALSE(PathParser::parseStringForSkPath(&path, "l", 1));
- EXPECT_FALSE(PathParser::parseStringForSkPath(&path, "1 1", 3));
- EXPECT_FALSE(PathParser::parseStringForSkPath(&path, "LMFAO", 5));
- EXPECT_TRUE(PathParser::parseStringForSkPath(&path, "m1 1", 4));
+
+ for (StringPath stringPath : sStringPaths) {
+ PathParser::ParseResult result;
+ SkPath skPath;
+ PathParser::parseStringForSkPath(&skPath, &result, stringPath.stringPath,
+ strlen(stringPath.stringPath));
+ EXPECT_EQ(stringPath.isValid, !result.failureOccurred);
+ }
}
}; // namespace uirenderer
diff --git a/packages/SystemUI/res/anim/recents_fast_toggle_app_home_exit.xml b/packages/SystemUI/res/anim/recents_fast_toggle_app_home_exit.xml
new file mode 100644
index 0000000..69edcc7
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_fast_toggle_app_home_exit.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, 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.
+*/
+-->
+<!-- Recents Activity -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false"
+ android:zAdjustment="top">
+ <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
+ android:fillEnabled="true"
+ android:fillBefore="true" android:fillAfter="true"
+ android:duration="250"/>
+</set>
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 6fe6909..50aa2f7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -401,17 +401,22 @@
ActivityManager.RunningTaskInfo runningTask = ssp.getTopMostTask();
// Return early if there is no running task
if (runningTask == null) return;
- // Return early if the running task is in the home stack (optimization)
- if (SystemServicesProxy.isHomeStack(runningTask.stackId)) return;
// Find the task in the recents list
+ boolean isTopTaskHome = SystemServicesProxy.isHomeStack(runningTask.stackId);
ArrayList<Task> tasks = focusedStack.getTasks();
Task toTask = null;
ActivityOptions launchOpts = null;
int taskCount = tasks.size();
for (int i = taskCount - 1; i >= 1; i--) {
Task task = tasks.get(i);
- if (task.key.id == runningTask.id) {
+ if (isTopTaskHome) {
+ toTask = tasks.get(i - 1);
+ launchOpts = ActivityOptions.makeCustomAnimation(mContext,
+ R.anim.recents_launch_next_affiliated_task_target,
+ R.anim.recents_fast_toggle_app_home_exit);
+ break;
+ } else if (task.key.id == runningTask.id) {
toTask = tasks.get(i - 1);
launchOpts = ActivityOptions.makeCustomAnimation(mContext,
R.anim.recents_launch_prev_affiliated_task_target,
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 38bd71d..a96bd2c 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -67,7 +67,7 @@
private final WindowSurfacePlacer mWindowPlacerLocked;
/** Is any window animating? */
- boolean mAnimating;
+ private boolean mAnimating;
/** Is any app window animating? */
boolean mAppWindowAnimating;
@@ -168,7 +168,8 @@
appAnimator.wasAnimating = appAnimator.animating;
if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) {
appAnimator.animating = true;
- mAnimating = mAppWindowAnimating = true;
+ setAnimating(true);
+ mAppWindowAnimating = true;
} else if (appAnimator.wasAnimating) {
// stopped animating, do one more pass through the layout
setAppLayoutChanges(appAnimator,
@@ -186,7 +187,8 @@
final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator;
appAnimator.wasAnimating = appAnimator.animating;
if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) {
- mAnimating = mAppWindowAnimating = true;
+ setAnimating(true);
+ mAppWindowAnimating = true;
} else if (appAnimator.wasAnimating) {
// stopped animating, do one more pass through the layout
setAppLayoutChanges(appAnimator,
@@ -282,7 +284,7 @@
final boolean wasAnimating = winAnimator.mWasAnimating;
final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime);
winAnimator.mWasAnimating = nowAnimating;
- mAnimating |= nowAnimating;
+ orAnimating(nowAnimating);
if (DEBUG_WALLPAPER) {
Slog.v(TAG, win + ": wasAnimating=" + wasAnimating +
@@ -546,7 +548,7 @@
}
}
}
- mAnimating = true;
+ setAnimating(true);
}
// If this window's app token is running a detached wallpaper
@@ -617,7 +619,7 @@
// We can now show all of the drawn windows!
if (!mService.mOpeningApps.contains(wtoken)) {
- mAnimating |= appAnimator.showAllWindowsLocked();
+ orAnimating(appAnimator.showAllWindowsLocked());
}
}
}
@@ -636,7 +638,7 @@
mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
boolean wasAnimating = mAnimating;
- mAnimating = false;
+ setAnimating(false);
mAppWindowAnimating = false;
if (DEBUG_WINDOW_TRACE) {
Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
@@ -657,7 +659,7 @@
displayAnimator.mScreenRotationAnimation;
if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
if (screenRotationAnimation.stepAnimationLocked(mCurrentTime)) {
- mAnimating = true;
+ setAnimating(true);
} else {
mBulkUpdateParams |= SET_UPDATE_ROTATION;
screenRotationAnimation.kill();
@@ -697,7 +699,7 @@
screenRotationAnimation.updateSurfacesInTransaction();
}
- mAnimating |= mService.getDisplayContentLocked(displayId).animateDimLayers();
+ orAnimating(mService.getDisplayContentLocked(displayId).animateDimLayers());
//TODO (multidisplay): Magnification is supported only for the default display.
if (mService.mAccessibilityController != null
@@ -920,4 +922,16 @@
private class DisplayContentsAnimator {
ScreenRotationAnimation mScreenRotationAnimation = null;
}
+
+ boolean isAnimating() {
+ return mAnimating;
+ }
+
+ void setAnimating(boolean animating) {
+ mAnimating = animating;
+ }
+
+ void orAnimating(boolean animating) {
+ mAnimating |= animating;
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 490f5d8..92eacd6 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2725,8 +2725,6 @@
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
}
- final int oldSurfaceResizeGeneration = winAnimator.mSurfaceResizeGeneration;
-
win.setDisplayLayoutNeeded();
win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
configChanged = updateOrientationFromAppTokensLocked(false);
@@ -2739,7 +2737,8 @@
if (win.mAppToken != null) {
win.mAppToken.updateReportedVisibilityLocked();
}
- if (winAnimator.mSurfaceResizeGeneration != oldSurfaceResizeGeneration) {
+ if (winAnimator.mReportSurfaceResized) {
+ winAnimator.mReportSurfaceResized = false;
result |= WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED;
}
outFrame.set(win.mCompatFrame);
@@ -7688,7 +7687,7 @@
synchronized (mWindowMap) {
// Since we're holding both mWindowMap and mAnimator we don't need to
// hold mAnimator.mLayoutToAnim.
- if (mAnimator.mAnimating || mAnimationScheduled) {
+ if (mAnimator.isAnimating() || mAnimationScheduled) {
// If we are animating, don't do the gc now but
// delay a bit so we don't interrupt the animation.
sendEmptyMessageDelayed(H.FORCE_GC, 2000);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 4b2edf6..f7805b1 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -99,7 +99,11 @@
* we must tell them application to resize (and thus redraw itself).
*/
boolean mSurfaceResized;
- int mSurfaceResizeGeneration;
+ /**
+ * Whether we should inform the client on next relayoutWindow that
+ * the surface has been resized since last time.
+ */
+ boolean mReportSurfaceResized;
WindowSurfaceController mSurfaceController;
private WindowSurfaceController mPendingDestroySurface;
@@ -497,7 +501,7 @@
}
if (mDrawState == DRAW_PENDING) {
if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION)
- Slog.v(TAG, "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING " + this + " in "
+ Slog.v(TAG, "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING " + mWin + " in "
+ mSurfaceController);
if (DEBUG_STARTING_WINDOW && startingWindow) {
Slog.v(TAG, "Draw state now committed in " + mWin);
@@ -529,7 +533,7 @@
mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
result = performShowLocked();
}
- if (mDestroyPreservedSurfaceUponRedraw && result) {
+ if (mDestroyPreservedSurfaceUponRedraw) {
mService.mDestroyPreservedSurface.add(mWin);
}
return result;
@@ -1085,7 +1089,7 @@
} else if (w.mDecorFrame.isEmpty()) {
// Windows without policy decor aren't cropped.
w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
- } else if (w.mAttrs.type == LayoutParams.TYPE_WALLPAPER && mAnimator.mAnimating) {
+ } else if (w.mAttrs.type == LayoutParams.TYPE_WALLPAPER && mAnimator.isAnimating()) {
// If we're animating, the wallpaper crop should only be updated at the end of the
// animation.
mTmpClipRect.set(w.mSystemDecorRect);
@@ -1125,12 +1129,8 @@
// The clip rect was generated assuming (0,0) as the window origin,
// so we need to translate to match the actual surface coordinates.
clipRect.offset(attrs.surfaceInsets.left, attrs.surfaceInsets.top);
- // We don't want to clip to stack bounds windows that are currently doing entrance
- // animation for docked window, otherwise the animating window will be suddenly cut off.
- if (!(mAnimator.mAnimating && w.inDockedWorkspace())) {
- adjustCropToStackBounds(w, clipRect, isFreeformResizing);
- }
+ adjustCropToStackBounds(w, clipRect, isFreeformResizing);
w.transformFromScreenToSurfaceSpace(clipRect);
@@ -1143,31 +1143,40 @@
private void adjustCropToStackBounds(WindowState w, Rect clipRect, boolean isFreeformResizing) {
final AppWindowToken appToken = w.mAppToken;
final Task task = w.getTask();
- // We don't apply the the stack bounds to the window that is being replaced, because it was
- // living in a different stack. If we suddenly crop it to the new stack bounds, it might
- // get cut off. We don't want it to happen, so we let it ignore the stack bounds until it
- // gets removed. The window that will replace it will abide them.
- if (task != null && appToken.mCropWindowsToStack && !appToken.mWillReplaceWindow) {
- TaskStack stack = task.mStack;
- stack.getDimBounds(mTmpStackBounds);
- // When we resize we use the big surface approach, which means we can't trust the
- // window frame bounds anymore. Instead, the window will be placed at 0, 0, but to avoid
- // hardcoding it, we use surface coordinates.
- final int frameX = isFreeformResizing ? (int) mSurfaceController.getX() :
- w.mFrame.left + mWin.mXOffset - w.getAttrs().surfaceInsets.left;
- final int frameY = isFreeformResizing ? (int) mSurfaceController.getY() :
- w.mFrame.top + mWin.mYOffset - w.getAttrs().surfaceInsets.top;
- // We need to do some acrobatics with surface position, because their clip region is
- // relative to the inside of the surface, but the stack bounds aren't.
- clipRect.left = Math.max(0,
- Math.max(mTmpStackBounds.left, frameX + clipRect.left) - frameX);
- clipRect.top = Math.max(0,
- Math.max(mTmpStackBounds.top, frameY + clipRect.top) - frameY);
- clipRect.right = Math.max(0,
- Math.min(mTmpStackBounds.right, frameX + clipRect.right) - frameX);
- clipRect.bottom = Math.max(0,
- Math.min(mTmpStackBounds.bottom, frameY + clipRect.bottom) - frameY);
+ if (task == null || !appToken.mCropWindowsToStack) {
+ return;
}
+
+ // We don't apply the stack bounds crop if:
+ // 1. The window is currently animating docked mode, otherwise the animating window will be
+ // suddenly cut off.
+ // 2. The window that is being replaced during animation, because it was living in a
+ // different stack. If we suddenly crop it to the new stack bounds, it might get cut off.
+ // We don't want it to happen, so we let it ignore the stack bounds until it gets removed.
+ // The window that will replace it will abide them.
+ if (isAnimating() && (appToken.mWillReplaceWindow || w.inDockedWorkspace())) {
+ return;
+ }
+
+ final TaskStack stack = task.mStack;
+ stack.getDimBounds(mTmpStackBounds);
+ // When we resize we use the big surface approach, which means we can't trust the
+ // window frame bounds anymore. Instead, the window will be placed at 0, 0, but to avoid
+ // hardcoding it, we use surface coordinates.
+ final int frameX = isFreeformResizing ? (int) mSurfaceController.getX() :
+ w.mFrame.left + mWin.mXOffset - w.getAttrs().surfaceInsets.left;
+ final int frameY = isFreeformResizing ? (int) mSurfaceController.getY() :
+ w.mFrame.top + mWin.mYOffset - w.getAttrs().surfaceInsets.top;
+ // We need to do some acrobatics with surface position, because their clip region is
+ // relative to the inside of the surface, but the stack bounds aren't.
+ clipRect.left = Math.max(0,
+ Math.max(mTmpStackBounds.left, frameX + clipRect.left) - frameX);
+ clipRect.top = Math.max(0,
+ Math.max(mTmpStackBounds.top, frameY + clipRect.top) - frameY);
+ clipRect.right = Math.max(0,
+ Math.min(mTmpStackBounds.right, frameX + clipRect.right) - frameX);
+ clipRect.bottom = Math.max(0,
+ Math.min(mTmpStackBounds.bottom, frameY + clipRect.bottom) - frameY);
}
void setSurfaceBoundariesLocked(final boolean recoveringMemory) {
@@ -1184,7 +1193,7 @@
recoveringMemory);
if (mSurfaceResized) {
- mSurfaceResizeGeneration++;
+ mReportSurfaceResized = true;
mAnimator.setPendingLayoutChanges(w.getDisplayId(),
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
w.applyDimLayerIfNeeded();
@@ -1413,7 +1422,7 @@
// Force the show in the next prepareSurfaceLocked() call.
mLastAlpha = -1;
if (DEBUG_SURFACE_TRACE || DEBUG_ANIM)
- Slog.v(TAG, "performShowLocked: mDrawState=HAS_DRAWN in " + this);
+ Slog.v(TAG, "performShowLocked: mDrawState=HAS_DRAWN in " + mWin);
mDrawState = HAS_DRAWN;
mService.scheduleAnimationLocked();
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 3b57634..ae96658 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -542,11 +542,8 @@
mService.scheduleAnimationLocked();
- if (DEBUG_WINDOW_TRACE) {
- Slog.e(TAG,
- "performSurfacePlacementInner exit: animating="
- + mService.mAnimator.mAnimating);
- }
+ if (DEBUG_WINDOW_TRACE) Slog.e(TAG,
+ "performSurfacePlacementInner exit: animating=" + mService.mAnimator.isAnimating());
}
private void applySurfaceChangesTransaction(boolean recoveringMemory, int numDisplays,
@@ -1184,7 +1181,7 @@
">>> OPEN TRANSACTION handleAppTransitionReadyLocked()");
SurfaceControl.openTransaction();
try {
- mService.mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
+ mService.mAnimator.orAnimating(appAnimator.showAllWindowsLocked());
} finally {
SurfaceControl.closeTransaction();
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
@@ -1467,7 +1464,7 @@
appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator);
}
mService.mAnimator.mAppWindowAnimating |= appAnimator.isAnimating();
- mService.mAnimator.mAnimating |= appAnimator.showAllWindowsLocked();
+ mService.mAnimator.orAnimating(appAnimator.showAllWindowsLocked());
}
}
}