summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/16.txt1
-rw-r--r--api/current.txt1
-rw-r--r--core/java/android/app/ActivityOptions.java74
-rw-r--r--core/java/android/app/Notification.java1
-rw-r--r--core/java/android/view/IWindowManager.aidl3
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java32
-rw-r--r--core/jni/android/graphics/TextLayoutCache.cpp4
-rw-r--r--core/res/res/drawable-hdpi/progressbar_indeterminate_holo1.pngbin1240 -> 1084 bytes
-rw-r--r--core/res/res/drawable-hdpi/progressbar_indeterminate_holo2.pngbin1223 -> 1198 bytes
-rw-r--r--core/res/res/drawable-hdpi/progressbar_indeterminate_holo3.pngbin1280 -> 1346 bytes
-rw-r--r--core/res/res/drawable-hdpi/progressbar_indeterminate_holo4.pngbin1401 -> 1377 bytes
-rw-r--r--core/res/res/drawable-hdpi/progressbar_indeterminate_holo5.pngbin1298 -> 1209 bytes
-rw-r--r--core/res/res/drawable-hdpi/progressbar_indeterminate_holo6.pngbin1309 -> 1401 bytes
-rw-r--r--core/res/res/drawable-hdpi/progressbar_indeterminate_holo7.pngbin1089 -> 1162 bytes
-rw-r--r--core/res/res/drawable-hdpi/progressbar_indeterminate_holo8.pngbin1230 -> 1255 bytes
-rw-r--r--core/res/res/drawable-mdpi/progressbar_indeterminate_holo1.pngbin713 -> 672 bytes
-rw-r--r--core/res/res/drawable-mdpi/progressbar_indeterminate_holo2.pngbin691 -> 764 bytes
-rw-r--r--core/res/res/drawable-mdpi/progressbar_indeterminate_holo3.pngbin766 -> 855 bytes
-rw-r--r--core/res/res/drawable-mdpi/progressbar_indeterminate_holo4.pngbin809 -> 839 bytes
-rw-r--r--core/res/res/drawable-mdpi/progressbar_indeterminate_holo5.pngbin730 -> 828 bytes
-rw-r--r--core/res/res/drawable-mdpi/progressbar_indeterminate_holo6.pngbin749 -> 840 bytes
-rw-r--r--core/res/res/drawable-mdpi/progressbar_indeterminate_holo7.pngbin693 -> 794 bytes
-rw-r--r--core/res/res/drawable-mdpi/progressbar_indeterminate_holo8.pngbin688 -> 811 bytes
-rw-r--r--core/res/res/drawable-xhdpi/progressbar_indeterminate_holo1.pngbin1510 -> 1177 bytes
-rw-r--r--core/res/res/drawable-xhdpi/progressbar_indeterminate_holo2.pngbin1449 -> 1398 bytes
-rw-r--r--core/res/res/drawable-xhdpi/progressbar_indeterminate_holo3.pngbin1673 -> 1659 bytes
-rw-r--r--core/res/res/drawable-xhdpi/progressbar_indeterminate_holo4.pngbin1614 -> 1594 bytes
-rw-r--r--core/res/res/drawable-xhdpi/progressbar_indeterminate_holo5.pngbin1520 -> 1536 bytes
-rw-r--r--core/res/res/drawable-xhdpi/progressbar_indeterminate_holo6.pngbin1650 -> 1678 bytes
-rw-r--r--core/res/res/drawable-xhdpi/progressbar_indeterminate_holo7.pngbin1489 -> 1504 bytes
-rw-r--r--core/res/res/drawable-xhdpi/progressbar_indeterminate_holo8.pngbin1459 -> 1498 bytes
-rw-r--r--include/androidfw/VelocityTracker.h75
-rw-r--r--libs/androidfw/VelocityTracker.cpp321
-rw-r--r--packages/SystemUI/res/anim/search_launch_enter.xml4
-rw-r--r--packages/SystemUI/src/com/android/systemui/SearchPanelView.java33
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java2
-rw-r--r--services/java/com/android/server/am/ActivityRecord.java3
-rwxr-xr-xservices/java/com/android/server/am/ActivityStack.java20
-rwxr-xr-xservices/java/com/android/server/wm/WindowManagerService.java119
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java4
40 files changed, 574 insertions, 123 deletions
diff --git a/api/16.txt b/api/16.txt
index ec35e2169003..4cdff10880fd 100644
--- a/api/16.txt
+++ b/api/16.txt
@@ -3704,7 +3704,6 @@ package android.app {
field public static final int FLAG_ONGOING_EVENT = 2; // 0x2
field public static final int FLAG_ONLY_ALERT_ONCE = 8; // 0x8
field public static final int FLAG_SHOW_LIGHTS = 1; // 0x1
- field public static final java.lang.String KIND_PROMO = "android.promo";
field public static final int PRIORITY_DEFAULT = 0; // 0x0
field public static final int PRIORITY_HIGH = 1; // 0x1
field public static final int PRIORITY_LOW = -1; // 0xffffffff
diff --git a/api/current.txt b/api/current.txt
index 43128eefeb64..9540eab67537 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3705,7 +3705,6 @@ package android.app {
field public static final int FLAG_ONGOING_EVENT = 2; // 0x2
field public static final int FLAG_ONLY_ALERT_ONCE = 8; // 0x8
field public static final int FLAG_SHOW_LIGHTS = 1; // 0x1
- field public static final java.lang.String KIND_PROMO = "android.promo";
field public static final int PRIORITY_DEFAULT = 0; // 0x0
field public static final int PRIORITY_HIGH = 1; // 0x1
field public static final int PRIORITY_LOW = -1; // 0xffffffff
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 523a78d8dd6c..4edfdfb32a35 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -127,14 +127,55 @@ public class ActivityOptions {
*/
public static ActivityOptions makeCustomAnimation(Context context,
int enterResId, int exitResId) {
+ return makeCustomAnimation(context, enterResId, exitResId, null, null);
+ }
+
+ /**
+ * Create an ActivityOptions specifying a custom animation to run when
+ * the activity is displayed.
+ *
+ * @param context Who is defining this. This is the application that the
+ * animation resources will be loaded from.
+ * @param enterResId A resource ID of the animation resource to use for
+ * the incoming activity. Use 0 for no animation.
+ * @param exitResId A resource ID of the animation resource to use for
+ * the outgoing activity. Use 0 for no animation.
+ * @param handler If <var>listener</var> is non-null this must be a valid
+ * Handler on which to dispatch the callback; otherwise it should be null.
+ * @param listener Optional OnAnimationStartedListener to find out when the
+ * requested animation has started running. If for some reason the animation
+ * is not executed, the callback will happen immediately.
+ * @return Returns a new ActivityOptions object that you can use to
+ * supply these options as the options Bundle when starting an activity.
+ * @hide
+ */
+ public static ActivityOptions makeCustomAnimation(Context context,
+ int enterResId, int exitResId, Handler handler, OnAnimationStartedListener listener) {
ActivityOptions opts = new ActivityOptions();
opts.mPackageName = context.getPackageName();
opts.mAnimationType = ANIM_CUSTOM;
opts.mCustomEnterResId = enterResId;
opts.mCustomExitResId = exitResId;
+ opts.setListener(handler, listener);
return opts;
}
+ private void setListener(Handler handler, OnAnimationStartedListener listener) {
+ if (listener != null) {
+ final Handler h = handler;
+ final OnAnimationStartedListener finalListener = listener;
+ mAnimationStartedListener = new IRemoteCallback.Stub() {
+ @Override public void sendResult(Bundle data) throws RemoteException {
+ h.post(new Runnable() {
+ @Override public void run() {
+ finalListener.onAnimationStarted();
+ }
+ });
+ }
+ };
+ }
+ }
+
/**
* Callback for use with {@link ActivityOptions#makeThumbnailScaleUpAnimation}
* to find out when the given animation has started running.
@@ -258,19 +299,7 @@ public class ActivityOptions {
source.getLocationOnScreen(pts);
opts.mStartX = pts[0] + startX;
opts.mStartY = pts[1] + startY;
- if (listener != null) {
- final Handler h = source.getHandler();
- final OnAnimationStartedListener finalListener = listener;
- opts.mAnimationStartedListener = new IRemoteCallback.Stub() {
- @Override public void sendResult(Bundle data) throws RemoteException {
- h.post(new Runnable() {
- @Override public void run() {
- finalListener.onAnimationStarted();
- }
- });
- }
- };
- }
+ opts.setListener(source.getHandler(), listener);
return opts;
}
@@ -284,6 +313,8 @@ public class ActivityOptions {
if (mAnimationType == ANIM_CUSTOM) {
mCustomEnterResId = opts.getInt(KEY_ANIM_ENTER_RES_ID, 0);
mCustomExitResId = opts.getInt(KEY_ANIM_EXIT_RES_ID, 0);
+ mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
+ opts.getIBinder(KEY_ANIM_START_LISTENER));
} else if (mAnimationType == ANIM_SCALE_UP) {
mStartX = opts.getInt(KEY_ANIM_START_X, 0);
mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
@@ -381,7 +412,13 @@ public class ActivityOptions {
mCustomEnterResId = otherOptions.mCustomEnterResId;
mCustomExitResId = otherOptions.mCustomExitResId;
mThumbnail = null;
- mAnimationStartedListener = null;
+ if (otherOptions.mAnimationStartedListener != null) {
+ try {
+ otherOptions.mAnimationStartedListener.sendResult(null);
+ } catch (RemoteException e) {
+ }
+ }
+ mAnimationStartedListener = otherOptions.mAnimationStartedListener;
break;
case ANIM_SCALE_UP:
mAnimationType = otherOptions.mAnimationType;
@@ -389,6 +426,13 @@ public class ActivityOptions {
mStartY = otherOptions.mStartY;
mStartWidth = otherOptions.mStartWidth;
mStartHeight = otherOptions.mStartHeight;
+ if (otherOptions.mAnimationStartedListener != null) {
+ try {
+ otherOptions.mAnimationStartedListener.sendResult(null);
+ } catch (RemoteException e) {
+ }
+ }
+ mAnimationStartedListener = null;
break;
case ANIM_THUMBNAIL:
case ANIM_THUMBNAIL_DELAYED:
@@ -425,6 +469,8 @@ public class ActivityOptions {
b.putInt(KEY_ANIM_TYPE, mAnimationType);
b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);
b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId);
+ b.putIBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
+ != null ? mAnimationStartedListener.asBinder() : null);
break;
case ANIM_SCALE_UP:
b.putInt(KEY_ANIM_TYPE, mAnimationType);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 036008bea53d..457238acfdfb 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -417,6 +417,7 @@ public class Notification implements Parcelable
public static final String KIND_EVENT = "android.event";
/**
+ * @hide
* Notification type: promotion or advertisement.
*/
public static final String KIND_PROMO = "android.promo";
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index c5a687acef48..4d4eec7101c9 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -80,7 +80,8 @@ interface IWindowManager
void setFocusedApp(IBinder token, boolean moveFocusNow);
void prepareAppTransition(int transit, boolean alwaysKeepCurrent);
int getPendingAppTransition();
- void overridePendingAppTransition(String packageName, int enterAnim, int exitAnim);
+ void overridePendingAppTransition(String packageName, int enterAnim, int exitAnim,
+ IRemoteCallback startedCallback);
void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
int startHeight);
void overridePendingAppTransitionThumb(in Bitmap srcThumb, int startX, int startY,
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 0517d4b35374..d3c90553fe9c 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -443,6 +443,7 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
public AccessibilityNodeInfo findFocus(int focus) {
enforceSealed();
+ enforceValidFocusType(focus);
if (!canPerformRequestOverConnection(mSourceNodeId)) {
return null;
}
@@ -472,6 +473,7 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
public AccessibilityNodeInfo focusSearch(int direction) {
enforceSealed();
+ enforceValidFocusDirection(direction);
if (!canPerformRequestOverConnection(mSourceNodeId)) {
return null;
}
@@ -1330,6 +1332,36 @@ public class AccessibilityNodeInfo implements Parcelable {
}
}
+ private void enforceValidFocusDirection(int direction) {
+ switch (direction) {
+ case View.FOCUS_DOWN:
+ case View.FOCUS_UP:
+ case View.FOCUS_LEFT:
+ case View.FOCUS_RIGHT:
+ case View.FOCUS_FORWARD:
+ case View.FOCUS_BACKWARD:
+ case View.ACCESSIBILITY_FOCUS_DOWN:
+ case View.ACCESSIBILITY_FOCUS_UP:
+ case View.ACCESSIBILITY_FOCUS_LEFT:
+ case View.ACCESSIBILITY_FOCUS_RIGHT:
+ case View.ACCESSIBILITY_FOCUS_FORWARD:
+ case View.ACCESSIBILITY_FOCUS_BACKWARD:
+ return;
+ default:
+ throw new IllegalArgumentException("Unknown direction: " + direction);
+ }
+ }
+
+ private void enforceValidFocusType(int focusType) {
+ switch (focusType) {
+ case FOCUS_INPUT:
+ case FOCUS_ACCESSIBILITY:
+ return;
+ default:
+ throw new IllegalArgumentException("Unknown focus type: " + focusType);
+ }
+ }
+
/**
* Enforces that this instance is not sealed.
*
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index c85b09c53095..35f82a85b9f0 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -992,6 +992,10 @@ HB_Face TextLayoutShaper::getCachedHBFace(SkTypeface* typeface) {
}
void TextLayoutShaper::purgeCaches() {
+ size_t cacheSize = mCachedHBFaces.size();
+ for (size_t i = 0; i < cacheSize; i++) {
+ HB_FreeFace(mCachedHBFaces.valueAt(i));
+ }
mCachedHBFaces.clear();
unrefTypefaces();
init();
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo1.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo1.png
index 7efb94f6c55c..43f9e0350dfc 100644
--- a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo1.png
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo1.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo2.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo2.png
index 00e687994b92..c6d95f3396ef 100644
--- a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo2.png
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo2.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo3.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo3.png
index 3ffcd6898d18..7829a3cdabb9 100644
--- a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo3.png
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo3.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo4.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo4.png
index a5e94f79fb6d..d0842f8594d4 100644
--- a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo4.png
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo4.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo5.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo5.png
index dfdeba31311c..e78b8f9c2556 100644
--- a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo5.png
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo5.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo6.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo6.png
index 5b02b13c724d..5f9f6c323744 100644
--- a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo6.png
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo6.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo7.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo7.png
index 815f31bc8387..d39c4aeeb9ac 100644
--- a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo7.png
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo7.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo8.png b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo8.png
index 936794c1af13..94a6fae2cac7 100644
--- a/core/res/res/drawable-hdpi/progressbar_indeterminate_holo8.png
+++ b/core/res/res/drawable-hdpi/progressbar_indeterminate_holo8.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo1.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo1.png
index 5a9dec3fceb2..df7d06aa987e 100644
--- a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo1.png
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo1.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo2.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo2.png
index 184b280b0e05..b5b933f7e126 100644
--- a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo2.png
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo2.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo3.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo3.png
index 96f06442fd8a..b4dccc64d53a 100644
--- a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo3.png
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo3.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo4.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo4.png
index 2393a2c39698..e61f3b3566fb 100644
--- a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo4.png
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo4.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo5.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo5.png
index 4c1d60d357e8..969ab74a0b90 100644
--- a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo5.png
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo5.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo6.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo6.png
index cb89d16b59c1..5c1aa61617d4 100644
--- a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo6.png
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo6.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo7.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo7.png
index a4f843abfb82..0946f2d42ec6 100644
--- a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo7.png
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo7.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo8.png b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo8.png
index ea1ee05d8c20..a900c9f8f57f 100644
--- a/core/res/res/drawable-mdpi/progressbar_indeterminate_holo8.png
+++ b/core/res/res/drawable-mdpi/progressbar_indeterminate_holo8.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo1.png b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo1.png
index f541e3243238..ae847c972008 100644
--- a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo1.png
+++ b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo1.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo2.png b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo2.png
index 4c3f686991a2..7bf3ad65fc19 100644
--- a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo2.png
+++ b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo2.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo3.png b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo3.png
index 42ccc4973a6a..6c6341b0d6ff 100644
--- a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo3.png
+++ b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo3.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo4.png b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo4.png
index e5f0cd327b82..d7bb79683eba 100644
--- a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo4.png
+++ b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo4.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo5.png b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo5.png
index 415494b783dd..255fcb80a199 100644
--- a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo5.png
+++ b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo5.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo6.png b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo6.png
index 297d7b759448..6e5207eeab1e 100644
--- a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo6.png
+++ b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo6.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo7.png b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo7.png
index ba152f275a2d..7223bc0ac4e0 100644
--- a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo7.png
+++ b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo7.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo8.png b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo8.png
index b996b94e0e3a..ebcbe51399ec 100644
--- a/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo8.png
+++ b/core/res/res/drawable-xhdpi/progressbar_indeterminate_holo8.png
Binary files differ
diff --git a/include/androidfw/VelocityTracker.h b/include/androidfw/VelocityTracker.h
index e600c5a3ccf5..8c24219c0bfe 100644
--- a/include/androidfw/VelocityTracker.h
+++ b/include/androidfw/VelocityTracker.h
@@ -138,8 +138,23 @@ public:
*/
class LeastSquaresVelocityTrackerStrategy : public VelocityTrackerStrategy {
public:
+ enum Weighting {
+ // No weights applied. All data points are equally reliable.
+ WEIGHTING_NONE,
+
+ // Weight by time delta. Data points clustered together are weighted less.
+ WEIGHTING_DELTA,
+
+ // Weight such that points within a certain horizon are weighed more than those
+ // outside of that horizon.
+ WEIGHTING_CENTRAL,
+
+ // Weight such that points older than a certain amount are weighed less.
+ WEIGHTING_RECENT,
+ };
+
// Degree must be no greater than Estimator::MAX_DEGREE.
- LeastSquaresVelocityTrackerStrategy(uint32_t degree);
+ LeastSquaresVelocityTrackerStrategy(uint32_t degree, Weighting weighting = WEIGHTING_NONE);
virtual ~LeastSquaresVelocityTrackerStrategy();
virtual void clear();
@@ -167,7 +182,10 @@ private:
}
};
+ float chooseWeight(uint32_t index) const;
+
const uint32_t mDegree;
+ const Weighting mWeighting;
uint32_t mIndex;
Movement mMovements[HISTORY_SIZE];
};
@@ -178,7 +196,8 @@ private:
*/
class IntegratingVelocityTrackerStrategy : public VelocityTrackerStrategy {
public:
- IntegratingVelocityTrackerStrategy();
+ // Degree must be 1 or 2.
+ IntegratingVelocityTrackerStrategy(uint32_t degree);
~IntegratingVelocityTrackerStrategy();
virtual void clear();
@@ -191,18 +210,58 @@ private:
// Current state estimate for a particular pointer.
struct State {
nsecs_t updateTime;
- bool first;
+ uint32_t degree;
- float xpos, xvel;
- float ypos, yvel;
+ float xpos, xvel, xaccel;
+ float ypos, yvel, yaccel;
};
+ const uint32_t mDegree;
BitSet32 mPointerIdBits;
State mPointerState[MAX_POINTER_ID + 1];
- static void initState(State& state, nsecs_t eventTime, float xpos, float ypos);
- static void updateState(State& state, nsecs_t eventTime, float xpos, float ypos);
- static void populateEstimator(const State& state, VelocityTracker::Estimator* outEstimator);
+ void initState(State& state, nsecs_t eventTime, float xpos, float ypos) const;
+ void updateState(State& state, nsecs_t eventTime, float xpos, float ypos) const;
+ void populateEstimator(const State& state, VelocityTracker::Estimator* outEstimator) const;
+};
+
+
+/*
+ * Velocity tracker strategy used prior to ICS.
+ */
+class LegacyVelocityTrackerStrategy : public VelocityTrackerStrategy {
+public:
+ LegacyVelocityTrackerStrategy();
+ virtual ~LegacyVelocityTrackerStrategy();
+
+ virtual void clear();
+ virtual void clearPointers(BitSet32 idBits);
+ virtual void addMovement(nsecs_t eventTime, BitSet32 idBits,
+ const VelocityTracker::Position* positions);
+ virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const;
+
+private:
+ // Oldest sample to consider when calculating the velocity.
+ static const nsecs_t HORIZON = 200 * 1000000; // 100 ms
+
+ // Number of samples to keep.
+ static const uint32_t HISTORY_SIZE = 20;
+
+ // The minimum duration between samples when estimating velocity.
+ static const nsecs_t MIN_DURATION = 10 * 1000000; // 10 ms
+
+ struct Movement {
+ nsecs_t eventTime;
+ BitSet32 idBits;
+ VelocityTracker::Position positions[MAX_POINTERS];
+
+ inline const VelocityTracker::Position& getPosition(uint32_t id) const {
+ return positions[idBits.getIndexOfBit(id)];
+ }
+ };
+
+ uint32_t mIndex;
+ Movement mMovements[HISTORY_SIZE];
};
} // namespace android
diff --git a/libs/androidfw/VelocityTracker.cpp b/libs/androidfw/VelocityTracker.cpp
index 7300ea1bd1db..f48ec6226e70 100644
--- a/libs/androidfw/VelocityTracker.cpp
+++ b/libs/androidfw/VelocityTracker.cpp
@@ -161,13 +161,41 @@ VelocityTrackerStrategy* VelocityTracker::createStrategy(const char* strategy) {
// of the velocity when the finger is released.
return new LeastSquaresVelocityTrackerStrategy(3);
}
+ if (!strcmp("wlsq2-delta", strategy)) {
+ // 2nd order weighted least squares, delta weighting. Quality: EXPERIMENTAL
+ return new LeastSquaresVelocityTrackerStrategy(2,
+ LeastSquaresVelocityTrackerStrategy::WEIGHTING_DELTA);
+ }
+ if (!strcmp("wlsq2-central", strategy)) {
+ // 2nd order weighted least squares, central weighting. Quality: EXPERIMENTAL
+ return new LeastSquaresVelocityTrackerStrategy(2,
+ LeastSquaresVelocityTrackerStrategy::WEIGHTING_CENTRAL);
+ }
+ if (!strcmp("wlsq2-recent", strategy)) {
+ // 2nd order weighted least squares, recent weighting. Quality: EXPERIMENTAL
+ return new LeastSquaresVelocityTrackerStrategy(2,
+ LeastSquaresVelocityTrackerStrategy::WEIGHTING_RECENT);
+ }
if (!strcmp("int1", strategy)) {
// 1st order integrating filter. Quality: GOOD.
// Not as good as 'lsq2' because it cannot estimate acceleration but it is
// more tolerant of errors. Like 'lsq1', this strategy tends to underestimate
// the velocity of a fling but this strategy tends to respond to changes in
// direction more quickly and accurately.
- return new IntegratingVelocityTrackerStrategy();
+ return new IntegratingVelocityTrackerStrategy(1);
+ }
+ if (!strcmp("int2", strategy)) {
+ // 2nd order integrating filter. Quality: EXPERIMENTAL.
+ // For comparison purposes only. Unlike 'int1' this strategy can compensate
+ // for acceleration but it typically overestimates the effect.
+ return new IntegratingVelocityTrackerStrategy(2);
+ }
+ if (!strcmp("legacy", strategy)) {
+ // Legacy velocity tracker algorithm. Quality: POOR.
+ // For comparison purposes only. This algorithm is strongly influenced by
+ // old data points, consistently underestimates velocity and takes a very long
+ // time to adjust to changes in direction.
+ return new LegacyVelocityTrackerStrategy();
}
return NULL;
}
@@ -327,8 +355,9 @@ bool VelocityTracker::getEstimator(uint32_t id, Estimator* outEstimator) const {
const nsecs_t LeastSquaresVelocityTrackerStrategy::HORIZON;
const uint32_t LeastSquaresVelocityTrackerStrategy::HISTORY_SIZE;
-LeastSquaresVelocityTrackerStrategy::LeastSquaresVelocityTrackerStrategy(uint32_t degree) :
- mDegree(degree) {
+LeastSquaresVelocityTrackerStrategy::LeastSquaresVelocityTrackerStrategy(
+ uint32_t degree, Weighting weighting) :
+ mDegree(degree), mWeighting(weighting) {
clear();
}
@@ -366,10 +395,23 @@ void LeastSquaresVelocityTrackerStrategy::addMovement(nsecs_t eventTime, BitSet3
*
* Returns true if a solution is found, false otherwise.
*
- * The input consists of two vectors of data points X and Y with indices 0..m-1.
+ * The input consists of two vectors of data points X and Y with indices 0..m-1
+ * along with a weight vector W of the same size.
+ *
* The output is a vector B with indices 0..n that describes a polynomial
- * that fits the data, such the sum of abs(Y[i] - (B[0] + B[1] X[i] + B[2] X[i]^2 ... B[n] X[i]^n))
- * for all i between 0 and m-1 is minimized.
+ * that fits the data, such the sum of W[i] * W[i] * abs(Y[i] - (B[0] + B[1] X[i]
+ * + B[2] X[i]^2 ... B[n] X[i]^n)) for all i between 0 and m-1 is minimized.
+ *
+ * Accordingly, the weight vector W should be initialized by the caller with the
+ * reciprocal square root of the variance of the error in each input data point.
+ * In other words, an ideal choice for W would be W[i] = 1 / var(Y[i]) = 1 / stddev(Y[i]).
+ * The weights express the relative importance of each data point. If the weights are
+ * all 1, then the data points are considered to be of equal importance when fitting
+ * the polynomial. It is a good idea to choose weights that diminish the importance
+ * of data points that may have higher than usual error margins.
+ *
+ * Errors among data points are assumed to be independent. W is represented here
+ * as a vector although in the literature it is typically taken to be a diagonal matrix.
*
* That is to say, the function that generated the input data can be approximated
* by y(x) ~= B[0] + B[1] x + B[2] x^2 + ... + B[n] x^n.
@@ -379,14 +421,15 @@ void LeastSquaresVelocityTrackerStrategy::addMovement(nsecs_t eventTime, BitSet3
* indicates perfect correspondence.
*
* This function first expands the X vector to a m by n matrix A such that
- * A[i][0] = 1, A[i][1] = X[i], A[i][2] = X[i]^2, ..., A[i][n] = X[i]^n.
+ * A[i][0] = 1, A[i][1] = X[i], A[i][2] = X[i]^2, ..., A[i][n] = X[i]^n, then
+ * multiplies it by w[i]./
*
* Then it calculates the QR decomposition of A yielding an m by m orthonormal matrix Q
* and an m by n upper triangular matrix R. Because R is upper triangular (lower
* part is all zeroes), we can simplify the decomposition into an m by n matrix
* Q1 and a n by n matrix R1 such that A = Q1 R1.
*
- * Finally we solve the system of linear equations given by R1 B = (Qtranspose Y)
+ * Finally we solve the system of linear equations given by R1 B = (Qtranspose W Y)
* to find B.
*
* For efficiency, we lay out A and Q column-wise in memory because we frequently
@@ -395,17 +438,18 @@ void LeastSquaresVelocityTrackerStrategy::addMovement(nsecs_t eventTime, BitSet3
* http://en.wikipedia.org/wiki/Numerical_methods_for_linear_least_squares
* http://en.wikipedia.org/wiki/Gram-Schmidt
*/
-static bool solveLeastSquares(const float* x, const float* y, uint32_t m, uint32_t n,
- float* outB, float* outDet) {
+static bool solveLeastSquares(const float* x, const float* y,
+ const float* w, uint32_t m, uint32_t n, float* outB, float* outDet) {
#if DEBUG_STRATEGY
- ALOGD("solveLeastSquares: m=%d, n=%d, x=%s, y=%s", int(m), int(n),
- vectorToString(x, m).string(), vectorToString(y, m).string());
+ ALOGD("solveLeastSquares: m=%d, n=%d, x=%s, y=%s, w=%s", int(m), int(n),
+ vectorToString(x, m).string(), vectorToString(y, m).string(),
+ vectorToString(w, m).string());
#endif
- // Expand the X vector to a matrix A.
+ // Expand the X vector to a matrix A, pre-multiplied by the weights.
float a[n][m]; // column-major order
for (uint32_t h = 0; h < m; h++) {
- a[0][h] = 1;
+ a[0][h] = w[h];
for (uint32_t i = 1; i < n; i++) {
a[i][h] = a[i - 1][h] * x[h];
}
@@ -462,10 +506,14 @@ static bool solveLeastSquares(const float* x, const float* y, uint32_t m, uint32
ALOGD(" - qr=%s", matrixToString(&qr[0][0], m, n, false /*rowMajor*/).string());
#endif
- // Solve R B = Qt Y to find B. This is easy because R is upper triangular.
+ // Solve R B = Qt W Y to find B. This is easy because R is upper triangular.
// We just work from bottom-right to top-left calculating B's coefficients.
+ float wy[m];
+ for (uint32_t h = 0; h < m; h++) {
+ wy[h] = y[h] * w[h];
+ }
for (uint32_t i = n; i-- != 0; ) {
- outB[i] = vectorDot(&q[i][0], y, m);
+ outB[i] = vectorDot(&q[i][0], wy, m);
for (uint32_t j = n - 1; j > i; j--) {
outB[i] -= r[i][j] * outB[j];
}
@@ -476,8 +524,9 @@ static bool solveLeastSquares(const float* x, const float* y, uint32_t m, uint32
#endif
// Calculate the coefficient of determination as 1 - (SSerr / SStot) where
- // SSerr is the residual sum of squares (squared variance of the error),
- // and SStot is the total sum of squares (squared variance of the data).
+ // SSerr is the residual sum of squares (variance of the error),
+ // and SStot is the total sum of squares (variance of the data) where each
+ // has been weighted.
float ymean = 0;
for (uint32_t h = 0; h < m; h++) {
ymean += y[h];
@@ -493,9 +542,9 @@ static bool solveLeastSquares(const float* x, const float* y, uint32_t m, uint32
term *= x[h];
err -= term * outB[i];
}
- sserr += err * err;
+ sserr += w[h] * w[h] * err * err;
float var = y[h] - ymean;
- sstot += var * var;
+ sstot += w[h] * w[h] * var * var;
}
*outDet = sstot > 0.000001f ? 1.0f - (sserr / sstot) : 1;
#if DEBUG_STRATEGY
@@ -513,6 +562,7 @@ bool LeastSquaresVelocityTrackerStrategy::getEstimator(uint32_t id,
// Iterate over movement samples in reverse time order and collect samples.
float x[HISTORY_SIZE];
float y[HISTORY_SIZE];
+ float w[HISTORY_SIZE];
float time[HISTORY_SIZE];
uint32_t m = 0;
uint32_t index = mIndex;
@@ -531,6 +581,7 @@ bool LeastSquaresVelocityTrackerStrategy::getEstimator(uint32_t id,
const VelocityTracker::Position& position = movement.getPosition(id);
x[m] = position.x;
y[m] = position.y;
+ w[m] = chooseWeight(index);
time[m] = -age * 0.000000001f;
index = (index == 0 ? HISTORY_SIZE : index) - 1;
} while (++m < HISTORY_SIZE);
@@ -547,8 +598,8 @@ bool LeastSquaresVelocityTrackerStrategy::getEstimator(uint32_t id,
if (degree >= 1) {
float xdet, ydet;
uint32_t n = degree + 1;
- if (solveLeastSquares(time, x, m, n, outEstimator->xCoeff, &xdet)
- && solveLeastSquares(time, y, m, n, outEstimator->yCoeff, &ydet)) {
+ if (solveLeastSquares(time, x, w, m, n, outEstimator->xCoeff, &xdet)
+ && solveLeastSquares(time, y, w, m, n, outEstimator->yCoeff, &ydet)) {
outEstimator->time = newestMovement.eventTime;
outEstimator->degree = degree;
outEstimator->confidence = xdet * ydet;
@@ -572,10 +623,78 @@ bool LeastSquaresVelocityTrackerStrategy::getEstimator(uint32_t id,
return true;
}
+float LeastSquaresVelocityTrackerStrategy::chooseWeight(uint32_t index) const {
+ switch (mWeighting) {
+ case WEIGHTING_DELTA: {
+ // Weight points based on how much time elapsed between them and the next
+ // point so that points that "cover" a shorter time span are weighed less.
+ // delta 0ms: 0.5
+ // delta 10ms: 1.0
+ if (index == mIndex) {
+ return 1.0f;
+ }
+ uint32_t nextIndex = (index + 1) % HISTORY_SIZE;
+ float deltaMillis = (mMovements[nextIndex].eventTime- mMovements[index].eventTime)
+ * 0.000001f;
+ if (deltaMillis < 0) {
+ return 0.5f;
+ }
+ if (deltaMillis < 10) {
+ return 0.5f + deltaMillis * 0.05;
+ }
+ return 1.0f;
+ }
+
+ case WEIGHTING_CENTRAL: {
+ // Weight points based on their age, weighing very recent and very old points less.
+ // age 0ms: 0.5
+ // age 10ms: 1.0
+ // age 50ms: 1.0
+ // age 60ms: 0.5
+ float ageMillis = (mMovements[mIndex].eventTime - mMovements[index].eventTime)
+ * 0.000001f;
+ if (ageMillis < 0) {
+ return 0.5f;
+ }
+ if (ageMillis < 10) {
+ return 0.5f + ageMillis * 0.05;
+ }
+ if (ageMillis < 50) {
+ return 1.0f;
+ }
+ if (ageMillis < 60) {
+ return 0.5f + (60 - ageMillis) * 0.05;
+ }
+ return 0.5f;
+ }
+
+ case WEIGHTING_RECENT: {
+ // Weight points based on their age, weighing older points less.
+ // age 0ms: 1.0
+ // age 50ms: 1.0
+ // age 100ms: 0.5
+ float ageMillis = (mMovements[mIndex].eventTime - mMovements[index].eventTime)
+ * 0.000001f;
+ if (ageMillis < 50) {
+ return 1.0f;
+ }
+ if (ageMillis < 100) {
+ return 0.5f + (100 - ageMillis) * 0.01f;
+ }
+ return 0.5f;
+ }
+
+ case WEIGHTING_NONE:
+ default:
+ return 1.0f;
+ }
+}
+
// --- IntegratingVelocityTrackerStrategy ---
-IntegratingVelocityTrackerStrategy::IntegratingVelocityTrackerStrategy() {
+IntegratingVelocityTrackerStrategy::IntegratingVelocityTrackerStrategy(uint32_t degree) :
+ mDegree(degree) {
}
IntegratingVelocityTrackerStrategy::~IntegratingVelocityTrackerStrategy() {
@@ -620,18 +739,20 @@ bool IntegratingVelocityTrackerStrategy::getEstimator(uint32_t id,
}
void IntegratingVelocityTrackerStrategy::initState(State& state,
- nsecs_t eventTime, float xpos, float ypos) {
+ nsecs_t eventTime, float xpos, float ypos) const {
state.updateTime = eventTime;
- state.first = true;
+ state.degree = 0;
state.xpos = xpos;
state.xvel = 0;
+ state.xaccel = 0;
state.ypos = ypos;
state.yvel = 0;
+ state.yaccel = 0;
}
void IntegratingVelocityTrackerStrategy::updateState(State& state,
- nsecs_t eventTime, float xpos, float ypos) {
+ nsecs_t eventTime, float xpos, float ypos) const {
const nsecs_t MIN_TIME_DELTA = 2 * NANOS_PER_MS;
const float FILTER_TIME_CONSTANT = 0.010f; // 10 milliseconds
@@ -644,28 +765,164 @@ void IntegratingVelocityTrackerStrategy::updateState(State& state,
float xvel = (xpos - state.xpos) / dt;
float yvel = (ypos - state.ypos) / dt;
- if (state.first) {
+ if (state.degree == 0) {
state.xvel = xvel;
state.yvel = yvel;
- state.first = false;
+ state.degree = 1;
} else {
float alpha = dt / (FILTER_TIME_CONSTANT + dt);
- state.xvel += (xvel - state.xvel) * alpha;
- state.yvel += (yvel - state.yvel) * alpha;
+ if (mDegree == 1) {
+ state.xvel += (xvel - state.xvel) * alpha;
+ state.yvel += (yvel - state.yvel) * alpha;
+ } else {
+ float xaccel = (xvel - state.xvel) / dt;
+ float yaccel = (yvel - state.yvel) / dt;
+ if (state.degree == 1) {
+ state.xaccel = xaccel;
+ state.yaccel = yaccel;
+ state.degree = 2;
+ } else {
+ state.xaccel += (xaccel - state.xaccel) * alpha;
+ state.yaccel += (yaccel - state.yaccel) * alpha;
+ }
+ state.xvel += (state.xaccel * dt) * alpha;
+ state.yvel += (state.yaccel * dt) * alpha;
+ }
}
state.xpos = xpos;
state.ypos = ypos;
}
void IntegratingVelocityTrackerStrategy::populateEstimator(const State& state,
- VelocityTracker::Estimator* outEstimator) {
+ VelocityTracker::Estimator* outEstimator) const {
outEstimator->time = state.updateTime;
- outEstimator->degree = 1;
outEstimator->confidence = 1.0f;
+ outEstimator->degree = state.degree;
outEstimator->xCoeff[0] = state.xpos;
outEstimator->xCoeff[1] = state.xvel;
+ outEstimator->xCoeff[2] = state.xaccel / 2;
outEstimator->yCoeff[0] = state.ypos;
outEstimator->yCoeff[1] = state.yvel;
+ outEstimator->yCoeff[2] = state.yaccel / 2;
+}
+
+
+// --- LegacyVelocityTrackerStrategy ---
+
+const nsecs_t LegacyVelocityTrackerStrategy::HORIZON;
+const uint32_t LegacyVelocityTrackerStrategy::HISTORY_SIZE;
+const nsecs_t LegacyVelocityTrackerStrategy::MIN_DURATION;
+
+LegacyVelocityTrackerStrategy::LegacyVelocityTrackerStrategy() {
+ clear();
+}
+
+LegacyVelocityTrackerStrategy::~LegacyVelocityTrackerStrategy() {
+}
+
+void LegacyVelocityTrackerStrategy::clear() {
+ mIndex = 0;
+ mMovements[0].idBits.clear();
+}
+
+void LegacyVelocityTrackerStrategy::clearPointers(BitSet32 idBits) {
+ BitSet32 remainingIdBits(mMovements[mIndex].idBits.value & ~idBits.value);
+ mMovements[mIndex].idBits = remainingIdBits;
+}
+
+void LegacyVelocityTrackerStrategy::addMovement(nsecs_t eventTime, BitSet32 idBits,
+ const VelocityTracker::Position* positions) {
+ if (++mIndex == HISTORY_SIZE) {
+ mIndex = 0;
+ }
+
+ Movement& movement = mMovements[mIndex];
+ movement.eventTime = eventTime;
+ movement.idBits = idBits;
+ uint32_t count = idBits.count();
+ for (uint32_t i = 0; i < count; i++) {
+ movement.positions[i] = positions[i];
+ }
+}
+
+bool LegacyVelocityTrackerStrategy::getEstimator(uint32_t id,
+ VelocityTracker::Estimator* outEstimator) const {
+ outEstimator->clear();
+
+ const Movement& newestMovement = mMovements[mIndex];
+ if (!newestMovement.idBits.hasBit(id)) {
+ return false; // no data
+ }
+
+ // Find the oldest sample that contains the pointer and that is not older than HORIZON.
+ nsecs_t minTime = newestMovement.eventTime - HORIZON;
+ uint32_t oldestIndex = mIndex;
+ uint32_t numTouches = 1;
+ do {
+ uint32_t nextOldestIndex = (oldestIndex == 0 ? HISTORY_SIZE : oldestIndex) - 1;
+ const Movement& nextOldestMovement = mMovements[nextOldestIndex];
+ if (!nextOldestMovement.idBits.hasBit(id)
+ || nextOldestMovement.eventTime < minTime) {
+ break;
+ }
+ oldestIndex = nextOldestIndex;
+ } while (++numTouches < HISTORY_SIZE);
+
+ // Calculate an exponentially weighted moving average of the velocity estimate
+ // at different points in time measured relative to the oldest sample.
+ // This is essentially an IIR filter. Newer samples are weighted more heavily
+ // than older samples. Samples at equal time points are weighted more or less
+ // equally.
+ //
+ // One tricky problem is that the sample data may be poorly conditioned.
+ // Sometimes samples arrive very close together in time which can cause us to
+ // overestimate the velocity at that time point. Most samples might be measured
+ // 16ms apart but some consecutive samples could be only 0.5sm apart because
+ // the hardware or driver reports them irregularly or in bursts.
+ float accumVx = 0;
+ float accumVy = 0;
+ uint32_t index = oldestIndex;
+ uint32_t samplesUsed = 0;
+ const Movement& oldestMovement = mMovements[oldestIndex];
+ const VelocityTracker::Position& oldestPosition = oldestMovement.getPosition(id);
+ nsecs_t lastDuration = 0;
+
+ while (numTouches-- > 1) {
+ if (++index == HISTORY_SIZE) {
+ index = 0;
+ }
+ const Movement& movement = mMovements[index];
+ nsecs_t duration = movement.eventTime - oldestMovement.eventTime;
+
+ // If the duration between samples is small, we may significantly overestimate
+ // the velocity. Consequently, we impose a minimum duration constraint on the
+ // samples that we include in the calculation.
+ if (duration >= MIN_DURATION) {
+ const VelocityTracker::Position& position = movement.getPosition(id);
+ float scale = 1000000000.0f / duration; // one over time delta in seconds
+ float vx = (position.x - oldestPosition.x) * scale;
+ float vy = (position.y - oldestPosition.y) * scale;
+ accumVx = (accumVx * lastDuration + vx * duration) / (duration + lastDuration);
+ accumVy = (accumVy * lastDuration + vy * duration) / (duration + lastDuration);
+ lastDuration = duration;
+ samplesUsed += 1;
+ }
+ }
+
+ // Report velocity.
+ const VelocityTracker::Position& newestPosition = newestMovement.getPosition(id);
+ outEstimator->time = newestMovement.eventTime;
+ outEstimator->confidence = 1;
+ outEstimator->xCoeff[0] = newestPosition.x;
+ outEstimator->yCoeff[0] = newestPosition.y;
+ if (samplesUsed) {
+ outEstimator->xCoeff[1] = accumVx;
+ outEstimator->yCoeff[1] = accumVy;
+ outEstimator->degree = 1;
+ } else {
+ outEstimator->degree = 0;
+ }
+ return true;
}
} // namespace android
diff --git a/packages/SystemUI/res/anim/search_launch_enter.xml b/packages/SystemUI/res/anim/search_launch_enter.xml
index 055ea5d795fa..f3333b7cd816 100644
--- a/packages/SystemUI/res/anim/search_launch_enter.xml
+++ b/packages/SystemUI/res/anim/search_launch_enter.xml
@@ -22,10 +22,10 @@
<alpha android:fromAlpha="0" android:toAlpha="1.0"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@android:interpolator/decelerate_quad"
+ android:interpolator="@android:interpolator/decelerate_cubic"
android:duration="300"/>
- <translate android:fromYDelta="200" android:toYDelta="0"
+ <translate android:fromYDelta="100%" android:toYDelta="0"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
android:interpolator="@android:interpolator/decelerate_cubic"
android:duration="300" />
diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
index 1cd8d503ca26..8b8a814cd3f6 100644
--- a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
@@ -46,8 +46,8 @@ import com.android.systemui.statusbar.tablet.StatusBarPanel;
import com.android.systemui.statusbar.tablet.TabletStatusBar;
public class SearchPanelView extends FrameLayout implements
- StatusBarPanel {
- private static final int SEARCH_PANEL_HOLD_DURATION = 500;
+ StatusBarPanel, ActivityOptions.OnAnimationStartedListener {
+ private static final int SEARCH_PANEL_HOLD_DURATION = 0;
static final String TAG = "SearchPanelView";
static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false;
private static final String ASSIST_ICON_METADATA_NAME =
@@ -115,18 +115,18 @@ public class SearchPanelView extends FrameLayout implements
if (intent == null) return;
try {
ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
- R.anim.search_launch_enter, R.anim.search_launch_exit);
+ R.anim.search_launch_enter, R.anim.search_launch_exit,
+ getHandler(), this);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent, opts.toBundle());
} catch (ActivityNotFoundException e) {
Slog.w(TAG, "Activity not found for " + intent.getAction());
+ onAnimationStarted();
}
}
- final MultiWaveView.OnTriggerListener mMultiWaveViewListener
- = new MultiWaveView.OnTriggerListener() {
-
- private boolean mWaitingForLaunch;
+ class MultiWaveTriggerListener implements MultiWaveView.OnTriggerListener {
+ boolean mWaitingForLaunch;
public void onGrabbed(View v, int handle) {
}
@@ -147,19 +147,24 @@ public class SearchPanelView extends FrameLayout implements
mWaitingForLaunch = true;
startAssistActivity();
vibrate();
- postDelayed(new Runnable() {
- public void run() {
- mWaitingForLaunch = false;
- mBar.hideSearchPanel();
- }
- }, SEARCH_PANEL_HOLD_DURATION);
break;
}
}
public void onFinishFinalAnimation() {
}
- };
+ }
+ final MultiWaveTriggerListener mMultiWaveViewListener = new MultiWaveTriggerListener();
+
+ @Override
+ public void onAnimationStarted() {
+ postDelayed(new Runnable() {
+ public void run() {
+ mMultiWaveViewListener.mWaitingForLaunch = false;
+ mBar.hideSearchPanel();
+ }
+ }, SEARCH_PANEL_HOLD_DURATION);
+ }
@Override
protected void onFinishInflate() {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index febbd3234d5e..8245d671ba87 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2804,7 +2804,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (self.state == ActivityState.RESUMED
|| self.state == ActivityState.PAUSING) {
mWindowManager.overridePendingAppTransition(packageName,
- enterAnim, exitAnim);
+ enterAnim, exitAnim, null);
}
Binder.restoreCallingIdentity(origId);
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index ad80273bc02b..26c5c3d952fb 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -558,7 +558,8 @@ final class ActivityRecord {
service.mWindowManager.overridePendingAppTransition(
pendingOptions.getPackageName(),
pendingOptions.getCustomEnterResId(),
- pendingOptions.getCustomExitResId());
+ pendingOptions.getCustomExitResId(),
+ pendingOptions.getOnAnimationStartListener());
break;
case ActivityOptions.ANIM_SCALE_UP:
service.mWindowManager.overridePendingAppTransitionScaleUp(
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 5b15e50cc05c..6af7a88aed90 100755
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -1371,6 +1371,10 @@ final class ActivityStack {
* nothing happened.
*/
final boolean resumeTopActivityLocked(ActivityRecord prev) {
+ return resumeTopActivityLocked(prev, null);
+ }
+
+ final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
// Find the first activity that is not finishing.
ActivityRecord next = topRunningActivityLocked(null);
@@ -1383,6 +1387,7 @@ final class ActivityStack {
// There are no more activities! Let's just start up the
// Launcher...
if (mMainStack) {
+ ActivityOptions.abort(options);
return mService.startHomeActivityLocked(0);
}
}
@@ -1395,6 +1400,7 @@ final class ActivityStack {
// should be nothing left to do at this point.
mService.mWindowManager.executeAppTransition();
mNoAnimActivities.clear();
+ ActivityOptions.abort(options);
return false;
}
@@ -1409,6 +1415,7 @@ final class ActivityStack {
// should be nothing left to do at this point.
mService.mWindowManager.executeAppTransition();
mNoAnimActivities.clear();
+ ActivityOptions.abort(options);
return false;
}
@@ -1419,6 +1426,8 @@ final class ActivityStack {
next.sleeping = false;
mWaitingVisibleActivities.remove(next);
+ next.updateOptionsLocked(options);
+
if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
// If we are currently pausing an activity, then don't do anything
@@ -2666,6 +2675,7 @@ final class ActivityStack {
movedHome = true;
moveHomeToFrontFromLaunchLocked(launchFlags);
moveTaskToFrontLocked(taskTop.task, r, options);
+ options = null;
}
}
// If the caller has requested that the target task be
@@ -2679,9 +2689,10 @@ final class ActivityStack {
// is the case, so this is it! And for paranoia, make
// sure we have correctly resumed the top activity.
if (doResume) {
- resumeTopActivityLocked(null);
+ resumeTopActivityLocked(null, options);
+ } else {
+ ActivityOptions.abort(options);
}
- ActivityOptions.abort(options);
return ActivityManager.START_RETURN_INTENT_TO_CALLER;
}
if ((launchFlags &
@@ -2767,9 +2778,10 @@ final class ActivityStack {
// don't use that intent!) And for paranoia, make
// sure we have correctly resumed the top activity.
if (doResume) {
- resumeTopActivityLocked(null);
+ resumeTopActivityLocked(null, options);
+ } else {
+ ActivityOptions.abort(options);
}
- ActivityOptions.abort(options);
return ActivityManager.START_TASK_TO_FRONT;
}
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 20532996f85e..9257028f0f37 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -3258,13 +3258,15 @@ public class WindowManagerService extends IWindowManager.Stub
if (mNextAppTransitionType == ActivityOptions.ANIM_CUSTOM) {
a = loadAnimation(mNextAppTransitionPackage, enter ?
mNextAppTransitionEnter : mNextAppTransitionExit);
- if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: wtoken=" + wtoken
+ if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
+ "applyAnimation: wtoken=" + wtoken
+ " anim=" + a + " nextAppTransition=ANIM_CUSTOM"
+ " transit=" + transit + " Callers " + Debug.getCallers(3));
} else if (mNextAppTransitionType == ActivityOptions.ANIM_SCALE_UP) {
a = createScaleUpAnimationLocked(transit, enter);
initialized = true;
- if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: wtoken=" + wtoken
+ if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
+ "applyAnimation: wtoken=" + wtoken
+ " anim=" + a + " nextAppTransition=ANIM_SCALE_UP"
+ " transit=" + transit + " Callers " + Debug.getCallers(3));
} else if (mNextAppTransitionType == ActivityOptions.ANIM_THUMBNAIL ||
@@ -3273,7 +3275,7 @@ public class WindowManagerService extends IWindowManager.Stub
a = createThumbnailAnimationLocked(transit, enter, false, delayed);
initialized = true;
- if (DEBUG_ANIM) {
+ if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
String animName = delayed ? "ANIM_THUMBNAIL_DELAYED" : "ANIM_THUMBNAIL";
Slog.v(TAG, "applyAnimation: wtoken=" + wtoken
+ " anim=" + a + " nextAppTransition=" + animName
@@ -3334,7 +3336,8 @@ public class WindowManagerService extends IWindowManager.Stub
break;
}
a = animAttr != 0 ? loadAnimation(lp, animAttr) : null;
- if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: wtoken=" + wtoken
+ if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
+ "applyAnimation: wtoken=" + wtoken
+ " anim=" + a
+ " animAttr=0x" + Integer.toHexString(animAttr)
+ " transit=" + transit + " Callers " + Debug.getCallers(3));
@@ -3897,41 +3900,62 @@ public class WindowManagerService extends IWindowManager.Stub
return mNextAppTransition;
}
+ private void scheduleAnimationCallback(IRemoteCallback cb) {
+ if (cb != null) {
+ mH.sendMessage(mH.obtainMessage(H.DO_ANIMATION_CALLBACK, cb));
+ }
+ }
+
public void overridePendingAppTransition(String packageName,
- int enterAnim, int exitAnim) {
- if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
- mNextAppTransitionType = ActivityOptions.ANIM_CUSTOM;
- mNextAppTransitionPackage = packageName;
- mNextAppTransitionThumbnail = null;
- mNextAppTransitionEnter = enterAnim;
- mNextAppTransitionExit = exitAnim;
+ int enterAnim, int exitAnim, IRemoteCallback startedCallback) {
+ synchronized(mWindowMap) {
+ if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
+ mNextAppTransitionType = ActivityOptions.ANIM_CUSTOM;
+ mNextAppTransitionPackage = packageName;
+ mNextAppTransitionThumbnail = null;
+ mNextAppTransitionEnter = enterAnim;
+ mNextAppTransitionExit = exitAnim;
+ scheduleAnimationCallback(mNextAppTransitionCallback);
+ mNextAppTransitionCallback = startedCallback;
+ } else {
+ scheduleAnimationCallback(startedCallback);
+ }
}
}
public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
int startHeight) {
- if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
- mNextAppTransitionType = ActivityOptions.ANIM_SCALE_UP;
- mNextAppTransitionPackage = null;
- mNextAppTransitionThumbnail = null;
- mNextAppTransitionStartX = startX;
- mNextAppTransitionStartY = startY;
- mNextAppTransitionStartWidth = startWidth;
- mNextAppTransitionStartHeight = startHeight;
+ synchronized(mWindowMap) {
+ if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
+ mNextAppTransitionType = ActivityOptions.ANIM_SCALE_UP;
+ mNextAppTransitionPackage = null;
+ mNextAppTransitionThumbnail = null;
+ mNextAppTransitionStartX = startX;
+ mNextAppTransitionStartY = startY;
+ mNextAppTransitionStartWidth = startWidth;
+ mNextAppTransitionStartHeight = startHeight;
+ scheduleAnimationCallback(mNextAppTransitionCallback);
+ mNextAppTransitionCallback = null;
+ }
}
}
public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
int startY, IRemoteCallback startedCallback, boolean delayed) {
- if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
- mNextAppTransitionType =
- delayed ? ActivityOptions.ANIM_THUMBNAIL_DELAYED : ActivityOptions.ANIM_THUMBNAIL;
- mNextAppTransitionPackage = null;
- mNextAppTransitionThumbnail = srcThumb;
- mNextAppTransitionDelayed = delayed;
- mNextAppTransitionStartX = startX;
- mNextAppTransitionStartY = startY;
- mNextAppTransitionCallback = startedCallback;
+ synchronized(mWindowMap) {
+ if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
+ mNextAppTransitionType = delayed
+ ? ActivityOptions.ANIM_THUMBNAIL_DELAYED : ActivityOptions.ANIM_THUMBNAIL;
+ mNextAppTransitionPackage = null;
+ mNextAppTransitionThumbnail = srcThumb;
+ mNextAppTransitionDelayed = delayed;
+ mNextAppTransitionStartX = startX;
+ mNextAppTransitionStartY = startY;
+ scheduleAnimationCallback(mNextAppTransitionCallback);
+ mNextAppTransitionCallback = startedCallback;
+ } else {
+ scheduleAnimationCallback(startedCallback);
+ }
}
}
@@ -6797,6 +6821,7 @@ public class WindowManagerService extends IWindowManager.Stub
public static final int WAITING_FOR_DRAWN_TIMEOUT = 24;
public static final int BULK_UPDATE_PARAMETERS = 25;
public static final int SHOW_STRICT_MODE_VIOLATION = 26;
+ public static final int DO_ANIMATION_CALLBACK = 27;
public static final int ANIMATOR_WHAT_OFFSET = 100000;
public static final int SET_TRANSPARENT_REGION = ANIMATOR_WHAT_OFFSET + 1;
@@ -7297,6 +7322,14 @@ public class WindowManagerService extends IWindowManager.Stub
mAnimator.clearPendingActions();
break;
}
+
+ case DO_ANIMATION_CALLBACK: {
+ try {
+ ((IRemoteCallback)msg.obj).sendResult(null);
+ } catch (RemoteException e) {
+ }
+ break;
+ }
}
if (DEBUG_WINDOW_TRACE) {
Slog.v(TAG, "handleMessage: exit");
@@ -8012,6 +8045,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
"New wallpaper target=" + mWallpaperTarget
+ + ", oldWallpaper=" + oldWallpaper
+ ", lower target=" + mLowerWallpaperTarget
+ ", upper target=" + mUpperWallpaperTarget);
int foundWallpapers = 0;
@@ -8078,7 +8112,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
"New transit: " + transit);
- } else if (oldWallpaper != null) {
+ } else if ((oldWallpaper != null) && !mOpeningApps.contains(oldWallpaper.mAppToken)) {
// We are transitioning from an activity with
// a wallpaper to one without.
transit = WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE;
@@ -8103,7 +8137,6 @@ public class WindowManagerService extends IWindowManager.Stub
AppWindowToken topOpeningApp = null;
int topOpeningLayer = 0;
- // TODO(cmautner): Move to animation side.
NN = mOpeningApps.size();
for (i=0; i<NN; i++) {
AppWindowToken wtoken = mOpeningApps.get(i);
@@ -8185,12 +8218,8 @@ public class WindowManagerService extends IWindowManager.Stub
mNextAppTransitionType = ActivityOptions.ANIM_NONE;
mNextAppTransitionPackage = null;
mNextAppTransitionThumbnail = null;
- if (mNextAppTransitionCallback != null) {
- try {
- mNextAppTransitionCallback.sendResult(null);
- } catch (RemoteException e) {
- }
- }
+ scheduleAnimationCallback(mNextAppTransitionCallback);
+ mNextAppTransitionCallback = null;
mOpeningApps.clear();
mClosingApps.clear();
@@ -9725,11 +9754,11 @@ public class WindowManagerService extends IWindowManager.Stub
switch (mNextAppTransitionType) {
case ActivityOptions.ANIM_CUSTOM:
pw.print(" mNextAppTransitionPackage=");
- pw.print(mNextAppTransitionPackage);
- pw.print(" mNextAppTransitionEnter=0x");
+ pw.println(mNextAppTransitionPackage);
+ pw.print(" mNextAppTransitionEnter=0x");
pw.print(Integer.toHexString(mNextAppTransitionEnter));
pw.print(" mNextAppTransitionExit=0x");
- pw.print(Integer.toHexString(mNextAppTransitionExit));
+ pw.println(Integer.toHexString(mNextAppTransitionExit));
break;
case ActivityOptions.ANIM_SCALE_UP:
pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX);
@@ -9744,11 +9773,17 @@ public class WindowManagerService extends IWindowManager.Stub
case ActivityOptions.ANIM_THUMBNAIL_DELAYED:
pw.print(" mNextAppTransitionThumbnail=");
pw.print(mNextAppTransitionThumbnail);
- pw.print(" mNextAppTransitionStartX="); pw.print(mNextAppTransitionStartX);
- pw.print(" mNextAppTransitionStartY="); pw.println(mNextAppTransitionStartY);
- pw.print(" mNextAppTransitionDelayed="); pw.println(mNextAppTransitionDelayed);
+ pw.print(" mNextAppTransitionStartX=");
+ pw.print(mNextAppTransitionStartX);
+ pw.print(" mNextAppTransitionStartY=");
+ pw.println(mNextAppTransitionStartY);
+ pw.print(" mNextAppTransitionDelayed="); pw.println(mNextAppTransitionDelayed);
break;
}
+ if (mNextAppTransitionCallback != null) {
+ pw.print(" mNextAppTransitionCallback=");
+ pw.println(mNextAppTransitionCallback);
+ }
pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition);
pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
index a4b2125549cf..8ab875fa6df2 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
@@ -226,8 +226,8 @@ public class BridgeWindowManager implements IWindowManager {
}
@Override
- public void overridePendingAppTransition(String arg0, int arg1, int arg2)
- throws RemoteException {
+ public void overridePendingAppTransition(String arg0, int arg1, int arg2,
+ IRemoteCallback startedCallback) throws RemoteException {
// TODO Auto-generated method stub
}