Merge "Fix issue #5461497: Landed on Welcome screen after a tap on 'Next' in Screen 500" into ics-mr0
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 7eae739..081e267 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -108,6 +108,7 @@
private static final boolean DEBUG_TRACKBALL = false || LOCAL_LOGV;
private static final boolean DEBUG_IMF = false || LOCAL_LOGV;
private static final boolean DEBUG_CONFIGURATION = false || LOCAL_LOGV;
+ private static final boolean DEBUG_FPS = false;
private static final boolean WATCH_POINTER = false;
/**
@@ -274,6 +275,11 @@
private Thread mRenderProfiler;
private volatile boolean mRenderProfilingEnabled;
+ // Variables to track frames per second, enabled via DEBUG_FPS flag
+ private long mFpsStartTime = -1;
+ private long mFpsPrevTime = -1;
+ private int mFpsNumFrames;
+
/**
* see {@link #playSoundEffect(int)}
*/
@@ -1766,12 +1772,42 @@
}
}
+ /**
+ * Called from draw() when DEBUG_FPS is enabled
+ */
+ private void trackFPS() {
+ // Tracks frames per second drawn. First value in a series of draws may be bogus
+ // because it down not account for the intervening idle time
+ long nowTime = System.currentTimeMillis();
+ if (mFpsStartTime < 0) {
+ mFpsStartTime = mFpsPrevTime = nowTime;
+ mFpsNumFrames = 0;
+ } else {
+ ++mFpsNumFrames;
+ String thisHash = Integer.toHexString(System.identityHashCode(this));
+ long frameTime = nowTime - mFpsPrevTime;
+ long totalTime = nowTime - mFpsStartTime;
+ Log.v(TAG, "0x" + thisHash + "\tFrame time:\t" + frameTime);
+ mFpsPrevTime = nowTime;
+ if (totalTime > 1000) {
+ float fps = (float) mFpsNumFrames * 1000 / totalTime;
+ Log.v(TAG, "0x" + thisHash + "\tFPS:\t" + fps);
+ mFpsStartTime = nowTime;
+ mFpsNumFrames = 0;
+ }
+ }
+ }
+
private void draw(boolean fullRedrawNeeded) {
Surface surface = mSurface;
if (surface == null || !surface.isValid()) {
return;
}
+ if (DEBUG_FPS) {
+ trackFPS();
+ }
+
if (!sFirstDrawComplete) {
synchronized (sFirstDrawHandlers) {
sFirstDrawComplete = true;
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 07281d4..14ce266 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -17,6 +17,7 @@
package com.android.systemui;
import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.Animator.AnimatorListener;
import android.animation.ValueAnimator;
@@ -40,6 +41,8 @@
public static final int X = 0;
public static final int Y = 1;
+ private static LinearInterpolator sLinearInterpolator = new LinearInterpolator();
+
private float SWIPE_ESCAPE_VELOCITY = 100f; // dp/sec
private int DEFAULT_ESCAPE_ANIMATION_DURATION = 200; // ms
private int MAX_ESCAPE_ANIMATION_DURATION = 400; // ms
@@ -199,6 +202,10 @@
return mDragging;
}
+ /**
+ * @param view The view to be dismissed
+ * @param velocity The desired pixels/second speed at which the view should move
+ */
public void dismissChild(final View view, float velocity) {
final View animView = mCallback.getChildContentView(view);
final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view);
@@ -221,22 +228,14 @@
duration = DEFAULT_ESCAPE_ANIMATION_DURATION;
}
+ animView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
ObjectAnimator anim = createTranslationAnimation(animView, newPos);
- anim.setInterpolator(new LinearInterpolator());
+ anim.setInterpolator(sLinearInterpolator);
anim.setDuration(duration);
- anim.addListener(new AnimatorListener() {
- public void onAnimationStart(Animator animation) {
- }
-
- public void onAnimationRepeat(Animator animation) {
- }
-
+ anim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
mCallback.onChildDismissed(view);
- }
-
- public void onAnimationCancel(Animator animation) {
- mCallback.onChildDismissed(view);
+ animView.setLayerType(View.LAYER_TYPE_NONE, null);
}
});
anim.addUpdateListener(new AnimatorUpdateListener() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 4e9b411..b724552 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -50,7 +50,6 @@
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
-import android.view.Surface;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
@@ -213,6 +212,8 @@
boolean mAnimatingReveal = false;
int mViewDelta;
int[] mAbsPos = new int[2];
+ Runnable mPostCollapseCleanup = null;
+
// for disabling the status bar
int mDisabled = 0;
@@ -1238,6 +1239,10 @@
return;
}
mExpanded = false;
+ if (mPostCollapseCleanup != null) {
+ mPostCollapseCleanup.run();
+ mPostCollapseCleanup = null;
+ }
}
void doAnimation() {
@@ -2066,49 +2071,67 @@
}
public void onClick(View v) {
synchronized (mNotificationData) {
- // let's also queue up 400ms worth of animated dismissals
- final int N = mini(5, mPile.getChildCount());
+ // animate-swipe all dismissable notifications, then animate the shade closed
+ int numChildren = mPile.getChildCount();
- final ArrayList<View> snapshot = new ArrayList<View>(N);
- for (int i=0; i<N; i++) {
+ int scrollTop = mScrollView.getScrollY();
+ int scrollBottom = scrollTop + mScrollView.getHeight();
+ final ArrayList<View> snapshot = new ArrayList<View>(numChildren);
+ for (int i=0; i<numChildren; i++) {
final View child = mPile.getChildAt(i);
- if (mPile.canChildBeDismissed(child)) snapshot.add(child);
+ if (mPile.canChildBeDismissed(child) && child.getBottom() > scrollTop &&
+ child.getTop() < scrollBottom) {
+ snapshot.add(child);
+ }
}
+ final int N = snapshot.size();
new Thread(new Runnable() {
@Override
public void run() {
- final int ROW_DELAY = 100;
+ // Decrease the delay for every row we animate to give the sense of
+ // accelerating the swipes
+ final int ROW_DELAY_DECREMENT = 10;
+ int currentDelay = 140;
+ int totalDelay = 0;
- mHandler.postDelayed(new Runnable() {
- public void run() {
- animateCollapse(false, 0f);
- }
- }, (N-1) * ROW_DELAY);
+ // Set the shade-animating state to avoid doing other work during
+ // all of these animations. In particular, avoid layout and
+ // redrawing when collapsing the shade.
+ mPile.setViewRemoval(false);
- mHandler.postDelayed(new Runnable() {
+ mPostCollapseCleanup = new Runnable() {
public void run() {
try {
+ mPile.setViewRemoval(true);
mBarService.onClearAllNotifications();
- } catch (RemoteException ex) { }
+ } catch (Exception ex) { }
}
- }, N * ROW_DELAY + 500);
+ };
- mPile.setAnimateBounds(false); // temporarily disable some re-layouts
-
+ View sampleView = snapshot.get(0);
+ int width = sampleView.getWidth();
+ final int velocity = (int)(width * 8); // 1000/8 = 125 ms duration
for (View v : snapshot) {
final View _v = v;
- mHandler.post(new Runnable() {
+ mHandler.postDelayed(new Runnable() {
@Override
public void run() {
- mPile.dismissRowAnimated(_v, (int)(ROW_DELAY*0.25f));
+ mPile.dismissRowAnimated(_v, velocity);
}
- });
- try {
- Thread.sleep(ROW_DELAY);
- } catch (InterruptedException ex) { }
+ }, totalDelay);
+ currentDelay = Math.max(50, currentDelay - ROW_DELAY_DECREMENT);
+ totalDelay += currentDelay;
}
-
- mPile.setAnimateBounds(true); // reenable layout animation
+ // Delay the collapse animation until after all swipe animations have
+ // finished. Provide some buffer because there may be some extra delay
+ // before actually starting each swipe animation. Ideally, we'd
+ // synchronize the end of those animations with the start of the collaps
+ // exactly.
+ mHandler.postDelayed(new Runnable() {
+ public void run() {
+ animateCollapse(false);
+ }
+ }, totalDelay + 225);
}
}).start();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
index a7342dc..3649f75e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
@@ -18,7 +18,6 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
@@ -29,7 +28,6 @@
import android.util.Log;
import android.util.Slog;
import android.view.MotionEvent;
-import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
@@ -59,6 +57,10 @@
private SwipeHelper mSwipeHelper;
+ // Flag set during notification removal animation to avoid causing too much work until
+ // animation is done
+ boolean mRemoveViews = true;
+
public NotificationRowLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@@ -117,7 +119,7 @@
public void onChildDismissed(View v) {
final View veto = v.findViewById(R.id.veto);
- if (veto != null && veto.getVisibility() != View.GONE) {
+ if (veto != null && veto.getVisibility() != View.GONE && mRemoveViews) {
veto.performClick();
}
}
@@ -170,7 +172,6 @@
final View childF = child;
if (mAnimateBounds) {
- child.setPivotY(0);
final ObjectAnimator alphaFade = ObjectAnimator.ofFloat(child, "alpha", 0f, 1f);
alphaFade.setDuration(APPEAR_ANIM_LEN);
alphaFade.addListener(new AnimatorListenerAdapter() {
@@ -189,6 +190,16 @@
}
}
+ /**
+ * Sets a flag to tell us whether to actually remove views. Removal is delayed by setting this
+ * to false during some animations to smooth out performance. Callers should restore the
+ * flag to true after the animation is done, and then they should make sure that the views
+ * get removed properly.
+ */
+ public void setViewRemoval(boolean removeViews) {
+ mRemoveViews = removeViews;
+ }
+
public void dismissRowAnimated(View child) {
dismissRowAnimated(child, 0);
}
@@ -199,16 +210,34 @@
@Override
public void removeView(View child) {
- final View childF = child;
+ if (!mRemoveViews) {
+ // This flag is cleared during an animation that removes all notifications. There
+ // should be a call to remove all notifications when the animation is done, at which
+ // time the view will be removed.
+ return;
+ }
if (mAnimateBounds) {
if (mAppearingViews.containsKey(child)) {
mAppearingViews.remove(child);
}
- child.setPivotY(0);
- final ObjectAnimator alphaFade = ObjectAnimator.ofFloat(child, "alpha", 0f);
- alphaFade.setDuration(DISAPPEAR_ANIM_LEN);
- alphaFade.addListener(new AnimatorListenerAdapter() {
+ // Don't fade it out if it already has a low alpha value, but run a non-visual
+ // animation which is used by onLayout() to animate shrinking the gap that it left
+ // in the list
+ ValueAnimator anim;
+ float currentAlpha = child.getAlpha();
+ if (currentAlpha > .1) {
+ anim = ObjectAnimator.ofFloat(child, "alpha", currentAlpha, 0);
+ } else {
+ if (currentAlpha > 0) {
+ // Just make it go away - no need to render it anymore
+ child.setAlpha(0);
+ }
+ anim = ValueAnimator.ofFloat(0, 1);
+ }
+ anim.setDuration(DISAPPEAR_ANIM_LEN);
+ final View childF = child;
+ anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (DEBUG) Slog.d(TAG, "actually removing child: " + childF);
@@ -218,9 +247,8 @@
}
});
- alphaFade.start();
-
- mDisappearingViews.put(child, alphaFade);
+ anim.start();
+ mDisappearingViews.put(child, anim);
requestLayout(); // start the container animation
} else {
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index ac3cdb8..e166401 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -273,7 +273,14 @@
break;
case ConnectivityManager.TYPE_MOBILE_HIPRI:
apnContext = addApnContext(Phone.APN_TYPE_HIPRI);
- break;
+ ApnContext defaultContext = mApnContexts.get(Phone.APN_TYPE_DEFAULT);
+ if (defaultContext != null) {
+ applyNewState(apnContext, apnContext.isEnabled(),
+ defaultContext.getDependencyMet());
+ } else {
+ // the default will set the hipri dep-met when it is created
+ }
+ continue;
case ConnectivityManager.TYPE_MOBILE_FOTA:
apnContext = addApnContext(Phone.APN_TYPE_FOTA);
break;