Merge "Defines MediaPlayer APIs to support multiple audio/video/timedtext tracks."
diff --git a/api/current.txt b/api/current.txt
index 6bac58a..93d9d44 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -26377,6 +26377,7 @@
ctor public EdgeEffect(android.content.Context);
method public boolean draw(android.graphics.Canvas);
method public void finish();
+ method public android.graphics.Rect getBounds();
method public boolean isFinished();
method public void onAbsorb(int);
method public void onPull(float);
diff --git a/cmds/system_server/library/Android.mk b/cmds/system_server/library/Android.mk
index 7d08a8c..9f92330 100644
--- a/cmds/system_server/library/Android.mk
+++ b/cmds/system_server/library/Android.mk
@@ -8,10 +8,7 @@
native = $(LOCAL_PATH)/../../../../native
LOCAL_C_INCLUDES := \
- $(base)/services/camera/libcameraservice \
- $(base)/services/audioflinger \
$(base)/services/sensorservice \
- $(base)/media/libmediaplayerservice \
$(native)/services/surfaceflinger \
$(JNI_H_INCLUDE)
@@ -19,9 +16,6 @@
libandroid_runtime \
libsensorservice \
libsurfaceflinger \
- libaudioflinger \
- libcameraservice \
- libmediaplayerservice \
libinput \
libutils \
libbinder \
diff --git a/cmds/system_server/library/system_init.cpp b/cmds/system_server/library/system_init.cpp
index bfbc138..745c34a 100644
--- a/cmds/system_server/library/system_init.cpp
+++ b/cmds/system_server/library/system_init.cpp
@@ -15,10 +15,6 @@
#include <utils/Log.h>
#include <SurfaceFlinger.h>
-#include <AudioFlinger.h>
-#include <CameraService.h>
-#include <AudioPolicyService.h>
-#include <MediaPlayerService.h>
#include <SensorService.h>
#include <android_runtime/AndroidRuntime.h>
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index f09e29d..dbcea71 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -742,7 +742,8 @@
url = url.replaceFirst(ANDROID_ASSET, "");
try {
AssetManager assets = mContext.getAssets();
- return assets.open(url, AssetManager.ACCESS_STREAMING);
+ Uri uri = Uri.parse(url);
+ return assets.open(uri.getPath(), AssetManager.ACCESS_STREAMING);
} catch (IOException e) {
return null;
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 5774440..9e07151 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -88,6 +88,7 @@
ViewTreeObserver.OnTouchModeChangeListener,
RemoteViewsAdapter.RemoteAdapterConnectionCallback {
+ @SuppressWarnings("UnusedDeclaration")
private static final String TAG = "AbsListView";
/**
@@ -2429,7 +2430,7 @@
final ViewTreeObserver treeObserver = getViewTreeObserver();
treeObserver.removeOnTouchModeChangeListener(this);
if (mTextFilterEnabled && mPopup != null) {
- treeObserver.removeGlobalOnLayoutListener(this);
+ treeObserver.removeOnGlobalLayoutListener(this);
mGlobalLayoutListenerAddedFilter = false;
}
@@ -2943,11 +2944,23 @@
mDirection = 0; // Reset when entering overscroll.
mTouchMode = TOUCH_MODE_OVERSCROLL;
if (rawDeltaY > 0) {
+ if (!mEdgeGlowTop.isIdle()) {
+ invalidate(mEdgeGlowTop.getBounds());
+ } else {
+ invalidate();
+ }
+
mEdgeGlowTop.onPull((float) overscroll / getHeight());
if (!mEdgeGlowBottom.isFinished()) {
mEdgeGlowBottom.onRelease();
}
} else if (rawDeltaY < 0) {
+ if (!mEdgeGlowBottom.isIdle()) {
+ invalidate(mEdgeGlowBottom.getBounds());
+ } else {
+ invalidate();
+ }
+
mEdgeGlowBottom.onPull((float) overscroll / getHeight());
if (!mEdgeGlowTop.isFinished()) {
mEdgeGlowTop.onRelease();
@@ -2956,7 +2969,6 @@
}
}
mMotionY = y;
- invalidate();
}
mLastY = y;
}
@@ -2990,26 +3002,26 @@
if (!mEdgeGlowBottom.isFinished()) {
mEdgeGlowBottom.onRelease();
}
+ invalidate(mEdgeGlowTop.getBounds());
} else if (rawDeltaY < 0) {
mEdgeGlowBottom.onPull((float) overScrollDistance / getHeight());
if (!mEdgeGlowTop.isFinished()) {
mEdgeGlowTop.onRelease();
}
+ invalidate(mEdgeGlowBottom.getBounds());
}
- invalidate();
}
}
if (incrementalDeltaY != 0) {
// Coming back to 'real' list scrolling
- mScrollY = 0;
- invalidateParentIfNeeded();
-
- // No need to do all this work if we're not going to move anyway
- if (incrementalDeltaY != 0) {
- trackMotionScroll(incrementalDeltaY, incrementalDeltaY);
+ if (mScrollY != 0) {
+ mScrollY = 0;
+ invalidateParentIfNeeded();
}
+ trackMotionScroll(incrementalDeltaY, incrementalDeltaY);
+
mTouchMode = TOUCH_MODE_SCROLL;
// We did not scroll the full amount. Treat this essentially like the
@@ -3468,11 +3480,12 @@
final int rightPadding = mListPadding.right + mGlowPaddingRight;
final int width = getWidth() - leftPadding - rightPadding;
- canvas.translate(leftPadding,
- Math.min(0, scrollY + mFirstPositionDistanceGuess));
+ int edgeY = Math.min(0, scrollY + mFirstPositionDistanceGuess);
+ canvas.translate(leftPadding, edgeY);
mEdgeGlowTop.setSize(width, getHeight());
if (mEdgeGlowTop.draw(canvas)) {
- invalidate();
+ mEdgeGlowTop.setPosition(leftPadding, edgeY);
+ invalidate(mEdgeGlowTop.getBounds());
}
canvas.restoreToCount(restoreCount);
}
@@ -3483,12 +3496,15 @@
final int width = getWidth() - leftPadding - rightPadding;
final int height = getHeight();
- canvas.translate(-width + leftPadding,
- Math.max(height, scrollY + mLastPositionDistanceGuess));
+ int edgeX = -width + leftPadding;
+ int edgeY = Math.max(height, scrollY + mLastPositionDistanceGuess);
+ canvas.translate(edgeX, edgeY);
canvas.rotate(180, width, 0);
mEdgeGlowBottom.setSize(width, height);
if (mEdgeGlowBottom.draw(canvas)) {
- invalidate();
+ // Account for the rotation
+ mEdgeGlowBottom.setPosition(edgeX + width, edgeY - mEdgeGlowBottom.getHeight());
+ invalidate(mEdgeGlowBottom.getBounds());
}
canvas.restoreToCount(restoreCount);
}
@@ -3874,7 +3890,8 @@
}
// Don't stop just because delta is zero (it could have been rounded)
- final boolean atEnd = trackMotionScroll(delta, delta) && (delta != 0);
+ final boolean atEdge = trackMotionScroll(delta, delta);
+ final boolean atEnd = atEdge && (delta != 0);
if (atEnd) {
if (motionView != null) {
// Tweak the scroll for how far we overshot
@@ -3889,7 +3906,7 @@
}
if (more && !atEnd) {
- invalidate();
+ if (atEdge) invalidate();
mLastFlingY = y;
post(this);
} else {
@@ -4431,7 +4448,7 @@
}
private void createScrollingCache() {
- if (mScrollingCacheEnabled && !mCachingStarted) {
+ if (mScrollingCacheEnabled && !mCachingStarted && !isHardwareAccelerated()) {
setChildrenDrawnWithCacheEnabled(true);
setChildrenDrawingCacheEnabled(true);
mCachingStarted = mCachingActive = true;
@@ -4439,23 +4456,25 @@
}
private void clearScrollingCache() {
- if (mClearScrollingCache == null) {
- mClearScrollingCache = new Runnable() {
- public void run() {
- if (mCachingStarted) {
- mCachingStarted = mCachingActive = false;
- setChildrenDrawnWithCacheEnabled(false);
- if ((mPersistentDrawingCache & PERSISTENT_SCROLLING_CACHE) == 0) {
- setChildrenDrawingCacheEnabled(false);
- }
- if (!isAlwaysDrawnWithCacheEnabled()) {
- invalidate();
+ if (!isHardwareAccelerated()) {
+ if (mClearScrollingCache == null) {
+ mClearScrollingCache = new Runnable() {
+ public void run() {
+ if (mCachingStarted) {
+ mCachingStarted = mCachingActive = false;
+ setChildrenDrawnWithCacheEnabled(false);
+ if ((mPersistentDrawingCache & PERSISTENT_SCROLLING_CACHE) == 0) {
+ setChildrenDrawingCacheEnabled(false);
+ }
+ if (!isAlwaysDrawnWithCacheEnabled()) {
+ invalidate();
+ }
}
}
- }
- };
+ };
+ }
+ post(mClearScrollingCache);
}
- post(mClearScrollingCache);
}
/**
@@ -4599,14 +4618,18 @@
mRecycler.removeSkippedScrap();
}
+ // invalidate before moving the children to avoid unnecessary invalidate
+ // calls to bubble up from the children all the way to the top
+ if (!awakenScrollBars()) {
+ invalidate();
+ }
+
offsetChildrenTopAndBottom(incrementalDeltaY);
if (down) {
mFirstPosition += count;
}
- invalidate();
-
final int absIncrementalDeltaY = Math.abs(incrementalDeltaY);
if (spaceAbove < absIncrementalDeltaY || spaceBelow < absIncrementalDeltaY) {
fillGap(down);
@@ -4629,7 +4652,6 @@
mBlockLayoutRequests = false;
invokeOnItemScrollListener();
- awakenScrollBars();
return false;
}
diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java
index 83aa8ba..c1f31bb 100644
--- a/core/java/android/widget/EdgeEffect.java
+++ b/core/java/android/widget/EdgeEffect.java
@@ -16,6 +16,7 @@
package android.widget;
+import android.graphics.Rect;
import com.android.internal.R;
import android.content.Context;
@@ -45,6 +46,7 @@
* {@link #draw(Canvas)} method.</p>
*/
public class EdgeEffect {
+ @SuppressWarnings("UnusedDeclaration")
private static final String TAG = "EdgeEffect";
// Time it will take the effect to fully recede in ms
@@ -57,10 +59,7 @@
private static final int PULL_DECAY_TIME = 1000;
private static final float MAX_ALPHA = 1.f;
- private static final float HELD_EDGE_ALPHA = 0.7f;
private static final float HELD_EDGE_SCALE_Y = 0.5f;
- private static final float HELD_GLOW_ALPHA = 0.5f;
- private static final float HELD_GLOW_SCALE_Y = 0.5f;
private static final float MAX_GLOW_HEIGHT = 4.f;
@@ -76,7 +75,9 @@
private final Drawable mGlow;
private int mWidth;
private int mHeight;
- private final int MIN_WIDTH = 300;
+ private int mX;
+ private int mY;
+ private static final int MIN_WIDTH = 300;
private final int mMinWidth;
private float mEdgeAlpha;
@@ -119,6 +120,8 @@
private int mState = STATE_IDLE;
private float mPullDistance;
+
+ private final Rect mBounds = new Rect();
/**
* Construct a new EdgeEffect with a theme appropriate for the provided context.
@@ -145,6 +148,29 @@
}
/**
+ * Set the position of this edge effect in pixels. This position is
+ * only used by {@link #getBounds()}.
+ *
+ * @param x The position of the edge effect on the X axis
+ * @param y The position of the edge effect on the Y axis
+ */
+ void setPosition(int x, int y) {
+ mX = x;
+ mY = y;
+ }
+
+ boolean isIdle() {
+ return mState == STATE_IDLE;
+ }
+
+ /**
+ * Returns the height of the effect itself.
+ */
+ int getHeight() {
+ return Math.max(mGlow.getBounds().height(), mEdge.getBounds().height());
+ }
+
+ /**
* Reports if this EdgeEffect's animation is finished. If this method returns false
* after a call to {@link #draw(Canvas)} the host widget should schedule another
* drawing pass to continue the animation.
@@ -301,7 +327,6 @@
update();
final int edgeHeight = mEdge.getIntrinsicHeight();
- final int edgeWidth = mEdge.getIntrinsicWidth();
final int glowHeight = mGlow.getIntrinsicHeight();
final int glowWidth = mGlow.getIntrinsicWidth();
@@ -334,9 +359,23 @@
}
mEdge.draw(canvas);
+ if (mState == STATE_RECEDE && glowBottom == 0 && edgeBottom == 0) {
+ mState = STATE_IDLE;
+ }
+
return mState != STATE_IDLE;
}
+ /**
+ * Returns the bounds of the edge effect.
+ */
+ public Rect getBounds() {
+ mBounds.set(mGlow.getBounds());
+ mBounds.union(mEdge.getBounds());
+ mBounds.offset(mX, mY);
+ return mBounds;
+ }
+
private void update() {
final long time = AnimationUtils.currentAnimationTimeMillis();
final float t = Math.min((time - mStartTime) / mDuration, 1.f);
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index fc08cc5..60dd55c 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -29,8 +29,8 @@
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
-
import com.android.internal.R;
+import android.widget.RemoteViews.RemoteView;
import java.lang.reflect.Array;
import java.util.ArrayList;
@@ -146,6 +146,7 @@
* @attr ref android.R.styleable#GridLayout_rowOrderPreserved
* @attr ref android.R.styleable#GridLayout_columnOrderPreserved
*/
+@RemoteView
public class GridLayout extends ViewGroup {
// Public constants
@@ -234,7 +235,6 @@
final Axis horizontalAxis = new Axis(true);
final Axis verticalAxis = new Axis(false);
- boolean layoutParamsValid = false;
int orientation = DEFAULT_ORIENTATION;
boolean useDefaultMargins = DEFAULT_USE_DEFAULT_MARGINS;
int alignmentMode = DEFAULT_ALIGNMENT_MODE;
@@ -713,12 +713,10 @@
minor = minor + minorSpan;
}
- lastLayoutParamsHashCode = computeLayoutParamsHashCode();
- invalidateStructure();
}
private void invalidateStructure() {
- layoutParamsValid = false;
+ lastLayoutParamsHashCode = UNINITIALIZED_HASH;
horizontalAxis.invalidateStructure();
verticalAxis.invalidateStructure();
// This can end up being done twice. Better twice than not at all.
@@ -742,10 +740,6 @@
}
final LayoutParams getLayoutParams(View c) {
- if (!layoutParamsValid) {
- validateLayoutParams();
- layoutParamsValid = true;
- }
return (LayoutParams) c.getLayoutParams();
}
@@ -874,20 +868,22 @@
return result;
}
- private void checkForLayoutParamsModification() {
- int layoutParamsHashCode = computeLayoutParamsHashCode();
- if (lastLayoutParamsHashCode != UNINITIALIZED_HASH &&
- lastLayoutParamsHashCode != layoutParamsHashCode) {
- invalidateStructure();
+ private void consistencyCheck() {
+ if (lastLayoutParamsHashCode == UNINITIALIZED_HASH) {
+ validateLayoutParams();
+ lastLayoutParamsHashCode = computeLayoutParamsHashCode();
+ } else if (lastLayoutParamsHashCode != computeLayoutParamsHashCode()) {
Log.w(TAG, "The fields of some layout parameters were modified in between layout " +
"operations. Check the javadoc for GridLayout.LayoutParams#rowSpec.");
+ invalidateStructure();
+ consistencyCheck();
}
}
// Measurement
private void measureChildWithMargins2(View child, int parentWidthSpec, int parentHeightSpec,
- int childWidth, int childHeight) {
+ int childWidth, int childHeight) {
int childWidthSpec = getChildMeasureSpec(parentWidthSpec,
mPaddingLeft + mPaddingRight + getTotalMargin(child, true), childWidth);
int childHeightSpec = getChildMeasureSpec(parentHeightSpec,
@@ -923,7 +919,7 @@
@Override
protected void onMeasure(int widthSpec, int heightSpec) {
- checkForLayoutParamsModification();
+ consistencyCheck();
/** If we have been called by {@link View#measure(int, int)}, one of width or height
* is likely to have changed. We must invalidate if so. */
@@ -993,7 +989,7 @@
*/
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- checkForLayoutParamsModification();
+ consistencyCheck();
int targetWidth = right - left;
int targetHeight = bottom - top;
@@ -1250,7 +1246,7 @@
}
private void include(List<Arc> arcs, Interval key, MutableInt size,
- boolean ignoreIfAlreadyPresent) {
+ boolean ignoreIfAlreadyPresent) {
/*
Remove self referential links.
These appear:
@@ -1429,8 +1425,8 @@
int dst = arc.span.max;
int value = arc.value.value;
result.append((src < dst) ?
- var + dst + " - " + var + src + " > " + value :
- var + src + " - " + var + dst + " < " + -value);
+ var + dst + "-" + var + src + ">=" + value :
+ var + src + "-" + var + dst + "<=" + -value);
}
return result.toString();
diff --git a/media/libstagefright/XINGSeeker.cpp b/media/libstagefright/XINGSeeker.cpp
index 2091381..e36d619 100644
--- a/media/libstagefright/XINGSeeker.cpp
+++ b/media/libstagefright/XINGSeeker.cpp
@@ -24,7 +24,7 @@
static bool parse_xing_header(
const sp<DataSource> &source, off64_t first_frame_pos,
int32_t *frame_number = NULL, int32_t *byte_number = NULL,
- unsigned char *table_of_contents = NULL,
+ unsigned char *table_of_contents = NULL, bool *toc_is_valid = NULL,
int32_t *quality_indicator = NULL, int64_t *duration = NULL);
// static
@@ -36,7 +36,7 @@
if (!parse_xing_header(
source, first_frame_pos,
- NULL, &seeker->mSizeBytes, seeker->mTableOfContents,
+ NULL, &seeker->mSizeBytes, seeker->mTOC, &seeker->mTOCValid,
NULL, &seeker->mDurationUs)) {
return NULL;
}
@@ -60,7 +60,7 @@
}
bool XINGSeeker::getOffsetForTime(int64_t *timeUs, off64_t *pos) {
- if (mSizeBytes == 0 || mTableOfContents[0] <= 0 || mDurationUs < 0) {
+ if (mSizeBytes == 0 || !mTOCValid || mDurationUs < 0) {
return false;
}
@@ -76,10 +76,10 @@
if ( a == 0 ) {
fa = 0.0f;
} else {
- fa = (float)mTableOfContents[a-1];
+ fa = (float)mTOC[a-1];
}
if ( a < 99 ) {
- fb = (float)mTableOfContents[a];
+ fb = (float)mTOC[a];
} else {
fb = 256.0f;
}
@@ -94,7 +94,8 @@
static bool parse_xing_header(
const sp<DataSource> &source, off64_t first_frame_pos,
int32_t *frame_number, int32_t *byte_number,
- unsigned char *table_of_contents, int32_t *quality_indicator,
+ unsigned char *table_of_contents, bool *toc_valid,
+ int32_t *quality_indicator,
int64_t *duration) {
if (frame_number) {
*frame_number = 0;
@@ -102,8 +103,8 @@
if (byte_number) {
*byte_number = 0;
}
- if (table_of_contents) {
- table_of_contents[0] = 0;
+ if (toc_valid) {
+ *toc_valid = false;
}
if (quality_indicator) {
*quality_indicator = 0;
@@ -199,10 +200,13 @@
offset += 4;
}
if (flags & 0x0004) { // TOC field is present
- if (table_of_contents) {
+ if (table_of_contents) {
if (source->readAt(offset + 1, table_of_contents, 99) < 99) {
return false;
}
+ if (toc_valid) {
+ *toc_valid = true;
+ }
}
offset += 100;
}
diff --git a/media/libstagefright/include/XINGSeeker.h b/media/libstagefright/include/XINGSeeker.h
index ec5bd9b..8510979 100644
--- a/media/libstagefright/include/XINGSeeker.h
+++ b/media/libstagefright/include/XINGSeeker.h
@@ -37,7 +37,8 @@
int32_t mSizeBytes;
// TOC entries in XING header. Skip the first one since it's always 0.
- unsigned char mTableOfContents[99];
+ unsigned char mTOC[99];
+ bool mTOCValid;
XINGSeeker();
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index b84fbdb..5ca09e7 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -27,6 +27,7 @@
import android.view.IApplicationToken;
import android.view.View;
import android.view.WindowManager;
+import android.view.WindowManagerPolicy;
import android.view.animation.Animation;
import android.view.animation.Transformation;
@@ -37,7 +38,7 @@
* Version of WindowToken that is specifically for a particular application (or
* really activity) that is displaying windows.
*/
-class AppWindowToken extends WindowToken implements WindowManagerService.StepAnimator {
+class AppWindowToken extends WindowToken {
// Non-null only for application tokens.
final IApplicationToken appToken;
@@ -195,8 +196,8 @@
}
}
- @Override
- public boolean stepAnimation(long currentTime) {
+
+ private boolean stepAnimation(long currentTime) {
if (animation == null) {
return false;
}
@@ -216,7 +217,7 @@
}
// This must be called while inside a transaction.
- boolean startAndFinishAnimationLocked(long currentTime, int dw, int dh) {
+ boolean stepAnimationLocked(long currentTime, int dw, int dh) {
if (!service.mDisplayFrozen && service.mPolicy.isScreenOnFully()) {
// We will run animations as long as the display isn't frozen.
@@ -240,7 +241,7 @@
animating = true;
}
// we're done!
- return true;
+ return stepAnimation(currentTime);
}
} else if (animation != null) {
// If the display is frozen, and there is a pending animation,
@@ -255,6 +256,7 @@
return false;
}
+ service.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
clearAnimation();
animating = false;
if (animLayerAdjustment != 0) {
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 7b5bf08..58187b6 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -29,7 +29,7 @@
import android.view.animation.AnimationUtils;
import android.view.animation.Transformation;
-class ScreenRotationAnimation implements WindowManagerService.StepAnimator {
+class ScreenRotationAnimation {
static final String TAG = "ScreenRotationAnimation";
static final boolean DEBUG_STATE = false;
static final boolean DEBUG_TRANSFORMS = false;
@@ -540,8 +540,7 @@
|| mRotateFrameAnimation != null;
}
- @Override
- public boolean stepAnimation(long now) {
+ private boolean stepAnimation(long now) {
if (mFinishAnimReady && mFinishAnimStartTime < 0) {
if (DEBUG_STATE) Slog.v(TAG, "Step: finish anim now ready");
@@ -725,7 +724,7 @@
setSnapshotTransform(mSnapshotFinalMatrix, mExitTransformation.getAlpha());
}
- public boolean startAndFinishAnimationLocked(long now) {
+ public boolean stepAnimationLocked(long now) {
if (!isAnimating()) {
if (DEBUG_STATE) Slog.v(TAG, "Step: no animations running");
mFinishAnimReady = false;
@@ -763,8 +762,8 @@
}
mAnimRunning = true;
}
-
- return true;
+
+ return stepAnimation(now);
}
public Transformation getEnterTransformation() {
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 22949f3..4f55217 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -461,6 +461,7 @@
= new ArrayList<IRotationWatcher>();
int mDeferredRotationPauseCount;
+ int mPendingLayoutChanges = 0;
boolean mLayoutNeeded = true;
boolean mTraversalScheduled = false;
boolean mDisplayFrozen = false;
@@ -617,18 +618,6 @@
final AnimationRunnable mAnimationRunnable = new AnimationRunnable();
boolean mAnimationScheduled;
- interface StepAnimator {
- /**
- * Continue the stepping of an ongoing animation. When the animation completes this method
- * must disable the animation on the StepAnimator.
- * @param currentTime Animation time in milliseconds. Use SystemClock.uptimeMillis().
- * @return True if the animation is still going on, false if the animation has completed
- * and stepAnimation has cleared the animation locally.
- */
- boolean stepAnimation(long currentTime);
- }
- final ArrayList<StepAnimator> mStepAnimators = new ArrayList<StepAnimator>();
-
final class DragInputEventReceiver extends InputEventReceiver {
public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
@@ -2995,15 +2984,27 @@
}
void applyEnterAnimationLocked(WindowState win) {
- int transit = WindowManagerPolicy.TRANSIT_SHOW;
+ final int transit;
if (win.mEnterAnimationPending) {
win.mEnterAnimationPending = false;
transit = WindowManagerPolicy.TRANSIT_ENTER;
+ } else {
+ transit = WindowManagerPolicy.TRANSIT_SHOW;
}
applyAnimationLocked(win, transit, true);
}
+ /**
+ * Choose the correct animation and set it to the passed WindowState.
+ * @param win The window to add the animation to.
+ * @param transit If WindowManagerPolicy.TRANSIT_PREVIEW_DONE and the app window has been drawn
+ * then the animation will be app_starting_exit. Any other value loads the animation from
+ * the switch statement below.
+ * @param isEntrance The animation type the last time this was called. Used to keep from
+ * loading the same animation twice.
+ * @return true if an animation has been loaded.
+ */
boolean applyAnimationLocked(WindowState win,
int transit, boolean isEntrance) {
if (win.mLocalAnimating && win.mAnimationIsEntrance == isEntrance) {
@@ -7643,20 +7644,6 @@
}
/**
- * Run through each of the animating objects saved in mStepAnimators.
- */
- private void stepAnimations() {
- final long currentTime = SystemClock.uptimeMillis();
- for (final StepAnimator stepAnimator : mStepAnimators) {
- final boolean more = stepAnimator.stepAnimation(currentTime);
- if (DEBUG_ANIM) {
- Slog.v(TAG, "stepAnimations: " + currentTime + ": Stepped " + stepAnimator
- + (more ? " more" : " done"));
- }
- }
- }
-
- /**
* Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
* Update animations of all applications, including those associated with exiting/removed apps.
*
@@ -7670,16 +7657,14 @@
final int NAT = mAppTokens.size();
for (i=0; i<NAT; i++) {
final AppWindowToken appToken = mAppTokens.get(i);
- if (appToken.startAndFinishAnimationLocked(currentTime, innerDw, innerDh)) {
- mStepAnimators.add(appToken);
+ if (appToken.stepAnimationLocked(currentTime, innerDw, innerDh)) {
mInnerFields.mAnimating = true;
}
}
final int NEAT = mExitingAppTokens.size();
for (i=0; i<NEAT; i++) {
final AppWindowToken appToken = mExitingAppTokens.get(i);
- if (appToken.startAndFinishAnimationLocked(currentTime, innerDw, innerDh)) {
- mStepAnimators.add(appToken);
+ if (appToken.stepAnimationLocked(currentTime, innerDw, innerDh)) {
mInnerFields.mAnimating = true;
}
}
@@ -7687,10 +7672,9 @@
if (mScreenRotationAnimation != null) {
if (mScreenRotationAnimation.isAnimating() ||
mScreenRotationAnimation.mFinishAnimReady) {
- if (mScreenRotationAnimation.startAndFinishAnimationLocked(currentTime)) {
+ if (mScreenRotationAnimation.stepAnimationLocked(currentTime)) {
mInnerFields.mUpdateRotation = false;
mInnerFields.mAnimating = true;
- mStepAnimators.add(mScreenRotationAnimation);
} else {
mInnerFields.mUpdateRotation = true;
mScreenRotationAnimation.kill();
@@ -7711,9 +7695,7 @@
*/
private int updateWindowsAndWallpaperLocked(final long currentTime, final int dw, final int dh,
final int innerDw, final int innerDh) {
-
- mPolicy.beginAnimationLw(dw, dh);
-
+ int changes = 0;
for (int i = mWindows.size() - 1; i >= 0; i--) {
WindowState w = mWindows.get(i);
@@ -7727,6 +7709,7 @@
if (DEBUG_WALLPAPER) Slog.v(TAG,
"First draw done in potential wallpaper target " + w);
mInnerFields.mWallpaperMayChange = true;
+ changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
}
}
@@ -7749,13 +7732,7 @@
}
final boolean wasAnimating = w.mWasAnimating;
-
-
- final boolean nowAnimating = w.startAndFinishAnimationLocked(currentTime);
- if (nowAnimating) {
- mStepAnimators.add(w);
- mInnerFields.mAnimating = true;
- }
+ final boolean nowAnimating = w.stepAnimationLocked(currentTime);
if (DEBUG_WALLPAPER) {
Slog.v(TAG, w + ": wasAnimating=" + wasAnimating +
@@ -7806,6 +7783,7 @@
if (wasAnimating && !w.mAnimating && mWallpaperTarget == w) {
mInnerFields.mWallpaperMayChange = true;
+ changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
}
if (mPolicy.doesForceHide(w, attrs)) {
@@ -7814,6 +7792,7 @@
"Animation started that could impact force hide: "
+ w);
mInnerFields.mWallpaperForceHidingChanged = true;
+ changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
mFocusMayChange = true;
} else if (w.isReadyForDisplay() && w.mAnimation == null) {
mInnerFields.mForceHiding = true;
@@ -7852,10 +7831,9 @@
if (changed && (attrs.flags
& WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
mInnerFields.mWallpaperMayChange = true;
+ changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
}
}
-
- mPolicy.animatingWindowLw(w, attrs);
}
final AppWindowToken atoken = w.mAppToken;
@@ -7900,10 +7878,11 @@
}
} else if (w.mReadyToShow) {
w.performShowLocked();
+ changes |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
}
} // end forall windows
- return mPolicy.finishAnimationLw();
+ return changes;
}
/**
@@ -8322,6 +8301,72 @@
return changes;
}
+ private void updateResizingWindows(final WindowState w) {
+ if (!w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) {
+ w.mContentInsetsChanged |=
+ !w.mLastContentInsets.equals(w.mContentInsets);
+ w.mVisibleInsetsChanged |=
+ !w.mLastVisibleInsets.equals(w.mVisibleInsets);
+ boolean configChanged =
+ w.mConfiguration != mCurConfiguration
+ && (w.mConfiguration == null
+ || mCurConfiguration.diff(w.mConfiguration) != 0);
+ if (DEBUG_CONFIGURATION && configChanged) {
+ Slog.v(TAG, "Win " + w + " config changed: "
+ + mCurConfiguration);
+ }
+ if (localLOGV) Slog.v(TAG, "Resizing " + w
+ + ": configChanged=" + configChanged
+ + " last=" + w.mLastFrame + " frame=" + w.mFrame);
+ w.mLastFrame.set(w.mFrame);
+ if (w.mContentInsetsChanged
+ || w.mVisibleInsetsChanged
+ || w.mSurfaceResized
+ || configChanged) {
+ if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
+ Slog.v(TAG, "Resize reasons: "
+ + " contentInsetsChanged=" + w.mContentInsetsChanged
+ + " visibleInsetsChanged=" + w.mVisibleInsetsChanged
+ + " surfaceResized=" + w.mSurfaceResized
+ + " configChanged=" + configChanged);
+ }
+
+ w.mLastContentInsets.set(w.mContentInsets);
+ w.mLastVisibleInsets.set(w.mVisibleInsets);
+ makeWindowFreezingScreenIfNeededLocked(w);
+ // If the orientation is changing, then we need to
+ // hold off on unfreezing the display until this
+ // window has been redrawn; to do that, we need
+ // to go through the process of getting informed
+ // by the application when it has finished drawing.
+ if (w.mOrientationChanging) {
+ if (DEBUG_ORIENTATION) Slog.v(TAG,
+ "Orientation start waiting for draw in "
+ + w + ", surface " + w.mSurface);
+ w.mDrawPending = true;
+ w.mCommitDrawPending = false;
+ w.mReadyToShow = false;
+ if (w.mAppToken != null) {
+ w.mAppToken.allDrawn = false;
+ }
+ }
+ if (!mResizingWindows.contains(w)) {
+ if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
+ "Resizing window " + w + " to " + w.mSurfaceW
+ + "x" + w.mSurfaceH);
+ mResizingWindows.add(w);
+ }
+ } else if (w.mOrientationChanging) {
+ if (!w.mDrawPending && !w.mCommitDrawPending) {
+ if (DEBUG_ORIENTATION) Slog.v(TAG,
+ "Orientation not waiting for draw in "
+ + w + ", surface " + w.mSurface);
+ w.mOrientationChanging = false;
+ }
+ }
+ }
+ }
+
/**
* Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
*
@@ -8407,69 +8452,7 @@
}
}
- if (!w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) {
- w.mContentInsetsChanged |=
- !w.mLastContentInsets.equals(w.mContentInsets);
- w.mVisibleInsetsChanged |=
- !w.mLastVisibleInsets.equals(w.mVisibleInsets);
- boolean configChanged =
- w.mConfiguration != mCurConfiguration
- && (w.mConfiguration == null
- || mCurConfiguration.diff(w.mConfiguration) != 0);
- if (DEBUG_CONFIGURATION && configChanged) {
- Slog.v(TAG, "Win " + w + " config changed: "
- + mCurConfiguration);
- }
- if (localLOGV) Slog.v(TAG, "Resizing " + w
- + ": configChanged=" + configChanged
- + " last=" + w.mLastFrame + " frame=" + w.mFrame);
- w.mLastFrame.set(w.mFrame);
- if (w.mContentInsetsChanged
- || w.mVisibleInsetsChanged
- || w.mSurfaceResized
- || configChanged) {
- if (DEBUG_RESIZE || DEBUG_ORIENTATION) {
- Slog.v(TAG, "Resize reasons: "
- + " contentInsetsChanged=" + w.mContentInsetsChanged
- + " visibleInsetsChanged=" + w.mVisibleInsetsChanged
- + " surfaceResized=" + w.mSurfaceResized
- + " configChanged=" + configChanged);
- }
-
- w.mLastContentInsets.set(w.mContentInsets);
- w.mLastVisibleInsets.set(w.mVisibleInsets);
- makeWindowFreezingScreenIfNeededLocked(w);
- // If the orientation is changing, then we need to
- // hold off on unfreezing the display until this
- // window has been redrawn; to do that, we need
- // to go through the process of getting informed
- // by the application when it has finished drawing.
- if (w.mOrientationChanging) {
- if (DEBUG_ORIENTATION) Slog.v(TAG,
- "Orientation start waiting for draw in "
- + w + ", surface " + w.mSurface);
- w.mDrawPending = true;
- w.mCommitDrawPending = false;
- w.mReadyToShow = false;
- if (w.mAppToken != null) {
- w.mAppToken.allDrawn = false;
- }
- }
- if (!mResizingWindows.contains(w)) {
- if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
- "Resizing window " + w + " to " + w.mSurfaceW
- + "x" + w.mSurfaceH);
- mResizingWindows.add(w);
- }
- } else if (w.mOrientationChanging) {
- if (!w.mDrawPending && !w.mCommitDrawPending) {
- if (DEBUG_ORIENTATION) Slog.v(TAG,
- "Orientation not waiting for draw in "
- + w + ", surface " + w.mSurface);
- w.mOrientationChanging = false;
- }
- }
- }
+ updateResizingWindows(w);
if (w.mAttachedHidden || !w.isReadyForDisplay()) {
if (!w.mLastHidden) {
@@ -8678,6 +8661,67 @@
}
}
+ private final int performAnimationsLocked(long currentTime, int dw, int dh,
+ int innerDw, int innerDh) {
+ ++mTransactionSequence;
+
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: seq="
+ + mTransactionSequence + " mAnimating="
+ + mInnerFields.mAnimating);
+
+ mInnerFields.mTokenMayBeDrawn = false;
+ mInnerFields.mWallpaperMayChange = false;
+ mInnerFields.mForceHiding = false;
+ mInnerFields.mDetachedWallpaper = null;
+ mInnerFields.mWindowAnimationBackground = null;
+ mInnerFields.mWindowAnimationBackgroundColor = 0;
+
+ int changes = updateWindowsAndWallpaperLocked(currentTime, dw, dh, innerDw, innerDh);
+
+ if (mInnerFields.mTokenMayBeDrawn) {
+ changes |= testTokenMayBeDrawnLocked();
+ }
+
+ // If we are ready to perform an app transition, check through
+ // all of the app tokens to be shown and see if they are ready
+ // to go.
+ if (mAppTransitionReady) {
+ changes |= handleAppTransitionReadyLocked();
+ }
+
+ mInnerFields.mAdjResult = 0;
+
+ if (!mInnerFields.mAnimating && mAppTransitionRunning) {
+ // We have finished the animation of an app transition. To do
+ // this, we have delayed a lot of operations like showing and
+ // hiding apps, moving apps in Z-order, etc. The app token list
+ // reflects the correct Z-order, but the window list may now
+ // be out of sync with it. So here we will just rebuild the
+ // entire app window list. Fun!
+ changes |= handleAnimatingStoppedAndTransitionLocked();
+ }
+
+ if (mInnerFields.mWallpaperForceHidingChanged && changes == 0 && !mAppTransitionReady) {
+ // At this point, there was a window with a wallpaper that
+ // was force hiding other windows behind it, but now it
+ // is going away. This may be simple -- just animate
+ // away the wallpaper and its window -- or it may be
+ // hard -- the wallpaper now needs to be shown behind
+ // something that was hidden.
+ changes |= animateAwayWallpaperLocked();
+ }
+
+ changes |= testWallpaperAndBackgroundLocked();
+
+ if (mLayoutNeeded) {
+ changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
+ }
+
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: changes=0x"
+ + Integer.toHexString(changes));
+ return changes;
+ }
+
// "Something has changed! Let's make it correct now."
private final void performLayoutAndPlaceSurfacesLockedInner(
boolean recoveringMemory) {
@@ -8741,7 +8785,6 @@
try {
mInnerFields.mWallpaperForceHidingChanged = false;
int repeats = 0;
- int changes = 0;
do {
repeats++;
@@ -8751,20 +8794,20 @@
break;
}
- if ((changes & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
+ if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
assignLayersLocked();
mLayoutNeeded = true;
}
}
- if ((changes & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
+ if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
if (updateOrientationFromAppTokensLocked(true)) {
mLayoutNeeded = true;
mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
}
}
- if ((changes & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
+ if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
mLayoutNeeded = true;
}
@@ -8775,71 +8818,26 @@
Slog.w(TAG, "Layout repeat skipped after too many iterations");
}
- ++mTransactionSequence;
-
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: seq="
- + mTransactionSequence + " mAnimating="
- + mInnerFields.mAnimating);
-
- mInnerFields.mTokenMayBeDrawn = false;
- mInnerFields.mWallpaperMayChange = false;
- mInnerFields.mForceHiding = false;
- mInnerFields.mDetachedWallpaper = null;
- mInnerFields.mWindowAnimationBackground = null;
- mInnerFields.mWindowAnimationBackgroundColor = 0;
-
- mStepAnimators.clear();
- changes = updateWindowsAndWallpaperLocked(currentTime, dw, dh, innerDw, innerDh);
-
- if (mInnerFields.mTokenMayBeDrawn) {
- changes |= testTokenMayBeDrawnLocked();
+ // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
+ // it is animating.
+ mPendingLayoutChanges = 0;
+ mPolicy.beginAnimationLw(dw, dh);
+ for (i = mWindows.size() - 1; i >= 0; i--) {
+ WindowState w = mWindows.get(i);
+ if (w.mSurface != null) {
+ mPolicy.animatingWindowLw(w, w.mAttrs);
+ }
}
-
- // If we are ready to perform an app transition, check through
- // all of the app tokens to be shown and see if they are ready
- // to go.
- if (mAppTransitionReady) {
- changes |= handleAppTransitionReadyLocked();
- }
-
- mInnerFields.mAdjResult = 0;
-
- if (!mInnerFields.mAnimating && mAppTransitionRunning) {
- // We have finished the animation of an app transition. To do
- // this, we have delayed a lot of operations like showing and
- // hiding apps, moving apps in Z-order, etc. The app token list
- // reflects the correct Z-order, but the window list may now
- // be out of sync with it. So here we will just rebuild the
- // entire app window list. Fun!
- changes |= handleAnimatingStoppedAndTransitionLocked();
- }
-
- if (mInnerFields.mWallpaperForceHidingChanged && changes == 0 && !mAppTransitionReady) {
- // At this point, there was a window with a wallpaper that
- // was force hiding other windows behind it, but now it
- // is going away. This may be simple -- just animate
- // away the wallpaper and its window -- or it may be
- // hard -- the wallpaper now needs to be shown behind
- // something that was hidden.
- changes |= animateAwayWallpaperLocked();
- }
-
- changes |= testWallpaperAndBackgroundLocked();
-
- if (mLayoutNeeded) {
- changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
- }
-
- if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: changes=0x"
- + Integer.toHexString(changes));
- } while (changes != 0);
+ mPendingLayoutChanges |= mPolicy.finishAnimationLw();
+
+ } while (mPendingLayoutChanges != 0);
// Update animations of all applications, including those
// associated with exiting/removed apps
+ mPendingLayoutChanges = performAnimationsLocked(currentTime, dw, dh,
+ innerDw, innerDh);
updateWindowsAppsAndRotationAnimationsLocked(currentTime, innerDw, innerDh);
-
- stepAnimations();
// THIRD LOOP: Update the surfaces of all windows.
@@ -9049,6 +9047,13 @@
if (wallpaperDestroyed) {
needRelayout = adjustWallpaperWindowsLocked() != 0;
}
+ if ((mPendingLayoutChanges & (
+ WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER |
+ ADJUST_WALLPAPER_LAYERS_CHANGED |
+ WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG |
+ WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT)) != 0) {
+ needRelayout = true;
+ }
if (needRelayout) {
requestTraversalLocked();
} else if (mInnerFields.mAnimating) {
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index e11c87a..48788e7 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -54,8 +54,7 @@
/**
* A window in the window manager.
*/
-final class WindowState implements WindowManagerPolicy.WindowState,
- WindowManagerService.StepAnimator {
+final class WindowState implements WindowManagerPolicy.WindowState {
static final boolean DEBUG_VISIBILITY = WindowManagerService.DEBUG_VISIBILITY;
static final boolean SHOW_TRANSACTIONS = WindowManagerService.SHOW_TRANSACTIONS;
static final boolean SHOW_LIGHT_TRANSACTIONS = WindowManagerService.SHOW_LIGHT_TRANSACTIONS;
@@ -995,8 +994,7 @@
return true;
}
- @Override
- public boolean stepAnimation(long currentTime) {
+ private boolean stepAnimation(long currentTime) {
if ((mAnimation == null) || !mLocalAnimating || (mAnimState != ANIM_STATE_RUNNING)) {
return false;
}
@@ -1013,7 +1011,7 @@
// This must be called while inside a transaction. Returns true if
// there is more animation to run.
- boolean startAndFinishAnimationLocked(long currentTime) {
+ boolean stepAnimationLocked(long currentTime) {
// Save the animation state as it was before this step so WindowManagerService can tell if
// we just started or just stopped animating by comparing mWasAnimating with isAnimating().
mWasAnimating = mAnimating;
@@ -1038,7 +1036,7 @@
}
if ((mAnimation != null) && mLocalAnimating &&
(mAnimState != ANIM_STATE_STOPPING)) {
- return true;
+ return stepAnimation(currentTime);
}
if (WindowManagerService.DEBUG_ANIM) Slog.v(
WindowManagerService.TAG, "Finished animation in " + this +
@@ -1133,6 +1131,7 @@
}
finishExit();
+ mService.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
if (mAppToken != null) {
mAppToken.updateReportedVisibilityLocked();
@@ -1608,6 +1607,7 @@
boolean showLw(boolean doAnimation, boolean requestAnim) {
if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
+ // Already showing.
return false;
}
if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Policy visibility true: " + this);
@@ -1647,6 +1647,7 @@
boolean current = doAnimation ? mPolicyVisibilityAfterAnim
: mPolicyVisibility;
if (!current) {
+ // Already hiding.
return false;
}
if (doAnimation) {