Merge "Fix bug #10205316 CTS (KLP): android.graphics tests are failing" into klp-dev
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 97ea99d..4d48fd4 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -17,10 +17,17 @@
package android.os;
import android.util.Log;
+import android.util.Slog;
+
+import libcore.io.ErrnoException;
+import libcore.io.IoUtils;
+import libcore.io.Libcore;
+import libcore.io.OsConstants;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -58,9 +65,84 @@
/** Regular expression for safe filenames: no spaces or metacharacters */
private static final Pattern SAFE_FILENAME_PATTERN = Pattern.compile("[\\w%+,./=_-]+");
- public static native int setPermissions(String file, int mode, int uid, int gid);
+ /**
+ * Set owner and mode of of given {@link File}.
+ *
+ * @param mode to apply through {@code chmod}
+ * @param uid to apply through {@code chown}, or -1 to leave unchanged
+ * @param gid to apply through {@code chown}, or -1 to leave unchanged
+ * @return 0 on success, otherwise errno.
+ */
+ public static int setPermissions(File path, int mode, int uid, int gid) {
+ return setPermissions(path.getAbsolutePath(), mode, uid, gid);
+ }
- public static native int getUid(String file);
+ /**
+ * Set owner and mode of of given path.
+ *
+ * @param mode to apply through {@code chmod}
+ * @param uid to apply through {@code chown}, or -1 to leave unchanged
+ * @param gid to apply through {@code chown}, or -1 to leave unchanged
+ * @return 0 on success, otherwise errno.
+ */
+ public static int setPermissions(String path, int mode, int uid, int gid) {
+ try {
+ Libcore.os.chmod(path, mode);
+ } catch (ErrnoException e) {
+ Slog.w(TAG, "Failed to chmod(" + path + "): " + e);
+ return e.errno;
+ }
+
+ if (uid >= 0 || gid >= 0) {
+ try {
+ Libcore.os.chown(path, uid, gid);
+ } catch (ErrnoException e) {
+ Slog.w(TAG, "Failed to chown(" + path + "): " + e);
+ return e.errno;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Set owner and mode of of given {@link FileDescriptor}.
+ *
+ * @param mode to apply through {@code chmod}
+ * @param uid to apply through {@code chown}, or -1 to leave unchanged
+ * @param gid to apply through {@code chown}, or -1 to leave unchanged
+ * @return 0 on success, otherwise errno.
+ */
+ public static int setPermissions(FileDescriptor fd, int mode, int uid, int gid) {
+ try {
+ Libcore.os.fchmod(fd, mode);
+ } catch (ErrnoException e) {
+ Slog.w(TAG, "Failed to fchmod(): " + e);
+ return e.errno;
+ }
+
+ if (uid >= 0 || gid >= 0) {
+ try {
+ Libcore.os.fchown(fd, uid, gid);
+ } catch (ErrnoException e) {
+ Slog.w(TAG, "Failed to fchown(): " + e);
+ return e.errno;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Return owning UID of given path, otherwise -1.
+ */
+ public static int getUid(String path) {
+ try {
+ return Libcore.os.stat(path).st_uid;
+ } catch (ErrnoException e) {
+ return -1;
+ }
+ }
/** returns the FAT file system volume ID for the volume mounted
* at the given mount point, or -1 for failure
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index ab0543d..cf9ddb3 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -100,12 +100,6 @@
public static final int DRM_UID = 1019;
/**
- * Defines the GID for the group that allows write access to the SD card.
- * @hide
- */
- public static final int SDCARD_RW_GID = 1015;
-
- /**
* Defines the UID/GID for the group that controls VPN services.
* @hide
*/
@@ -130,11 +124,18 @@
public static final int MEDIA_RW_GID = 1023;
/**
+ * Access to installed package details
+ * @hide
+ */
+ public static final int PACKAGE_INFO_GID = 1032;
+
+ /**
* Defines the start of a range of UIDs (and GIDs), going from this
* number to {@link #LAST_APPLICATION_UID} that are reserved for assigning
* to applications.
*/
public static final int FIRST_APPLICATION_UID = 10000;
+
/**
* Last of application-specific UIDs starting at
* {@link #FIRST_APPLICATION_UID}.
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index ccc0089..04351da 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -499,7 +499,7 @@
String args[] = {
"--setuid=1000",
"--setgid=1000",
- "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003,3006,3007",
+ "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--runtime-init",
"--nice-name=system_server",
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 3308064..6c4526e 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -35,8 +35,6 @@
#include <utils/Log.h>
-#define TIME_DRAWx
-
static uint32_t get_thread_msec() {
#if defined(HAVE_POSIX_CLOCKS)
struct timespec tm;
@@ -463,20 +461,6 @@
canvas->drawPath(*path, *paint);
}
- static void drawPicture(JNIEnv* env, jobject, SkCanvas* canvas,
- SkPicture* picture) {
- SkASSERT(canvas);
- SkASSERT(picture);
-
-#ifdef TIME_DRAW
- SkMSec now = get_thread_msec(); //SkTime::GetMSecs();
-#endif
- canvas->drawPicture(*picture);
-#ifdef TIME_DRAW
- ALOGD("---- picture playback %d ms\n", get_thread_msec() - now);
-#endif
- }
-
static void drawBitmap__BitmapFFPaint(JNIEnv* env, jobject jcanvas,
SkCanvas* canvas, SkBitmap* bitmap,
jfloat left, jfloat top,
@@ -1103,7 +1087,6 @@
(void*) SkCanvasGlue::drawTextOnPath___CIIPathFFPaint},
{"native_drawTextOnPath","(ILjava/lang/String;IFFII)V",
(void*) SkCanvasGlue::drawTextOnPath__StringPathFFPaint},
- {"native_drawPicture", "(II)V", (void*) SkCanvasGlue::drawPicture},
{"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches},
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index 2c482ea..bacfdf6 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -18,6 +18,9 @@
#include <stdio.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
#include <gui/GLConsumer.h>
#include <gui/Surface.h>
diff --git a/core/jni/android_os_FileUtils.cpp b/core/jni/android_os_FileUtils.cpp
index 0aaa2b1..d1245da 100644
--- a/core/jni/android_os_FileUtils.cpp
+++ b/core/jni/android_os_FileUtils.cpp
@@ -33,46 +33,6 @@
namespace android {
-jint android_os_FileUtils_setPermissions(JNIEnv* env, jobject clazz,
- jstring file, jint mode,
- jint uid, jint gid)
-{
- const jchar* str = env->GetStringCritical(file, 0);
- String8 file8;
- if (str) {
- file8 = String8(str, env->GetStringLength(file));
- env->ReleaseStringCritical(file, str);
- }
- if (file8.size() <= 0) {
- return ENOENT;
- }
- if (uid >= 0 || gid >= 0) {
- int res = chown(file8.string(), uid, gid);
- if (res != 0) {
- return errno;
- }
- }
- return chmod(file8.string(), mode) == 0 ? 0 : errno;
-}
-
-jint android_os_FileUtils_getUid(JNIEnv* env, jobject clazz, jstring file)
-{
- struct stat stats;
- const jchar* str = env->GetStringCritical(file, 0);
- String8 file8;
- if (str) {
- file8 = String8(str, env->GetStringLength(file));
- env->ReleaseStringCritical(file, str);
- }
- if (file8.size() <= 0) {
- return ENOENT;
- }
- if (stat(file8.string(), &stats) < 0) {
- return -1;
- }
- return stats.st_uid;
-}
-
jint android_os_FileUtils_getFatVolumeId(JNIEnv* env, jobject clazz, jstring path)
{
if (path == NULL) {
@@ -95,8 +55,6 @@
}
static const JNINativeMethod methods[] = {
- {"setPermissions", "(Ljava/lang/String;III)I", (void*)android_os_FileUtils_setPermissions},
- {"getUid", "(Ljava/lang/String;)I", (void*)android_os_FileUtils_getUid},
{"getFatVolumeId", "(Ljava/lang/String;)I", (void*)android_os_FileUtils_getFatVolumeId},
};
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index fdec22b..0ea4074 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -114,9 +114,13 @@
* canvas.
*/
public Canvas() {
- // 0 means no native bitmap
- mNativeCanvas = initRaster(0);
- mFinalizer = new CanvasFinalizer(mNativeCanvas);
+ if (!isHardwareAccelerated()) {
+ // 0 means no native bitmap
+ mNativeCanvas = initRaster(0);
+ mFinalizer = new CanvasFinalizer(mNativeCanvas);
+ } else {
+ mFinalizer = null;
+ }
}
/**
@@ -1646,7 +1650,9 @@
*/
public void drawPicture(Picture picture) {
picture.endRecording();
- native_drawPicture(mNativeCanvas, picture.ni());
+ int restoreCount = save();
+ picture.draw(this);
+ restoreToCount(restoreCount);
}
/**
@@ -1831,7 +1837,5 @@
float hOffset,
float vOffset,
int flags, int paint);
- private static native void native_drawPicture(int nativeCanvas,
- int nativePicture);
private static native void finalizer(int nativeCanvas);
}
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index d1bae1e..707f662 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1112,8 +1112,6 @@
setupDrawMesh(&mMeshVertices[0].position[0], &mMeshVertices[0].texture[0]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
-
- finishDrawTexture();
}
void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) {
@@ -1256,8 +1254,6 @@
GL_UNSIGNED_SHORT, NULL));
}
- finishDrawTexture();
-
#if DEBUG_LAYERS_AS_REGIONS
drawRegionRects(layer->region);
#endif
@@ -2021,9 +2017,6 @@
mCaches.bindPositionVertexPointer(force, vertices, gVertexStride);
}
-void OpenGLRenderer::finishDrawTexture() {
-}
-
///////////////////////////////////////////////////////////////////////////////
// Drawing
///////////////////////////////////////////////////////////////////////////////
@@ -2308,8 +2301,6 @@
glDrawArrays(GL_TRIANGLES, 0, count);
- finishDrawTexture();
-
int slot = mCaches.currentProgram->getAttrib("colors");
if (slot >= 0) {
glDisableVertexAttribArray(slot);
@@ -3134,8 +3125,6 @@
mesh += (drawCount / 6) * 4;
}
- finishDrawTexture();
-
#if DEBUG_LAYERS_AS_REGIONS
drawRegionRects(layer->region);
#endif
@@ -3270,8 +3259,6 @@
setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
-
- finishDrawTexture();
}
// Same values used by Skia
@@ -3488,8 +3475,6 @@
setupDrawMesh(vertices, texCoords, vbo);
glDrawArrays(drawMode, 0, elementsCount);
-
- finishDrawTexture();
}
void OpenGLRenderer::drawIndexedTextureMesh(float left, float top, float right, float bottom,
@@ -3515,8 +3500,6 @@
setupDrawMeshIndices(vertices, texCoords, vbo);
glDrawElements(drawMode, elementsCount, GL_UNSIGNED_SHORT, NULL);
-
- finishDrawTexture();
}
void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, float bottom,
@@ -3546,8 +3529,6 @@
setupDrawMesh(vertices, texCoords);
glDrawArrays(drawMode, 0, elementsCount);
-
- finishDrawTexture();
}
void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode,
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 2f8a2f0..1c3bfdc 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -1003,7 +1003,6 @@
void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLvoid* colors);
void setupDrawMeshIndices(GLvoid* vertices, GLvoid* texCoords, GLuint vbo = 0);
void setupDrawIndexedVertices(GLvoid* vertices);
- void finishDrawTexture();
void accountForClear(SkXfermode::Mode mode);
bool updateLayer(Layer* layer, bool inFrame);
diff --git a/media/mca/filterfw/native/core/gl_env.cpp b/media/mca/filterfw/native/core/gl_env.cpp
index fdecda3..84dad8c 100644
--- a/media/mca/filterfw/native/core/gl_env.cpp
+++ b/media/mca/filterfw/native/core/gl_env.cpp
@@ -26,6 +26,8 @@
#include <string>
#include <EGL/eglext.h>
+#include <gui/GLConsumer.h>
+
namespace android {
namespace filterfw {
diff --git a/media/mca/filterfw/native/core/gl_env.h b/media/mca/filterfw/native/core/gl_env.h
index 81e1e9d..a709638 100644
--- a/media/mca/filterfw/native/core/gl_env.h
+++ b/media/mca/filterfw/native/core/gl_env.h
@@ -31,6 +31,9 @@
#include <gui/Surface.h>
namespace android {
+
+class GLConsumer;
+
namespace filterfw {
class ShaderProgram;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 8e7e087..a536acb 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -72,7 +72,7 @@
private final DisplayState mDisplayState = new DisplayState();
/** Current user navigation stack; empty implies recents. */
- private DocumentStack mStack;
+ private DocumentStack mStack = new DocumentStack();
/** Currently active search, overriding any stack. */
private String mCurrentSearch;
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index 18b46fb..8fb3998 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -41,6 +41,7 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
/**
* This class is a strategy for performing touch exploration. It
@@ -52,10 +53,8 @@
* <li>2. One finger moving fast around performs gestures.</li>
* <li>3. Two close fingers moving in the same direction perform a drag.</li>
* <li>4. Multi-finger gestures are delivered to view hierarchy.</li>
- * <li>5. Pointers that have not moved more than a specified distance after they
- * went down are considered inactive.</li>
- * <li>6. Two fingers moving in different directions are considered a multi-finger gesture.</li>
- * <li>7. Double tapping clicks on the on the last touch explored location of it was in
+ * <li>5. Two fingers moving in different directions are considered a multi-finger gesture.</li>
+ * <li>7. Double tapping clicks on the on the last touch explored location if it was in
* a window that does not take focus, otherwise the click is within the accessibility
* focused rectangle.</li>
* <li>7. Tapping and holding for a while performs a long press in a similar fashion
@@ -102,9 +101,6 @@
// The timeout after which we are no longer trying to detect a gesture.
private static final int EXIT_GESTURE_DETECTION_TIMEOUT = 2000;
- // Temporary array for storing pointer IDs.
- private final int[] mTempPointerIds = new int[MAX_POINTER_COUNT];
-
// Timeout before trying to decide what the user is trying to do.
private final int mDetermineUserIntentTimeout;
@@ -129,11 +125,11 @@
// Handler for performing asynchronous operations.
private final Handler mHandler;
- // Command for delayed sending of a hover enter event.
- private final SendHoverDelayed mSendHoverEnterDelayed;
+ // Command for delayed sending of a hover enter and move event.
+ private final SendHoverEnterAndMoveDelayed mSendHoverEnterAndMoveDelayed;
// Command for delayed sending of a hover exit event.
- private final SendHoverDelayed mSendHoverExitDelayed;
+ private final SendHoverExitDelayed mSendHoverExitDelayed;
// Command for delayed sending of touch exploration end events.
private final SendAccessibilityEventDelayed mSendTouchExplorationEndDelayed;
@@ -220,7 +216,7 @@
public TouchExplorer(Context context, AccessibilityManagerService service) {
mContext = context;
mAms = service;
- mReceivedPointerTracker = new ReceivedPointerTracker(context);
+ mReceivedPointerTracker = new ReceivedPointerTracker();
mInjectedPointerTracker = new InjectedPointerTracker();
mTapTimeout = ViewConfiguration.getTapTimeout();
mDetermineUserIntentTimeout = ViewConfiguration.getDoubleTapTimeout();
@@ -234,8 +230,8 @@
mGestureLibrary.setOrientationStyle(8);
mGestureLibrary.setSequenceType(GestureStore.SEQUENCE_SENSITIVE);
mGestureLibrary.load();
- mSendHoverEnterDelayed = new SendHoverDelayed(MotionEvent.ACTION_HOVER_ENTER, true);
- mSendHoverExitDelayed = new SendHoverDelayed(MotionEvent.ACTION_HOVER_EXIT, false);
+ mSendHoverEnterAndMoveDelayed = new SendHoverEnterAndMoveDelayed();
+ mSendHoverExitDelayed = new SendHoverExitDelayed();
mSendTouchExplorationEndDelayed = new SendAccessibilityEventDelayed(
AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END,
mDetermineUserIntentTimeout);
@@ -283,12 +279,12 @@
} break;
}
// Remove all pending callbacks.
- mSendHoverEnterDelayed.remove();
- mSendHoverExitDelayed.remove();
- mPerformLongPressDelayed.remove();
- mExitGestureDetectionModeDelayed.remove();
- mSendTouchExplorationEndDelayed.remove();
- mSendTouchInteractionEndDelayed.remove();
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ mPerformLongPressDelayed.cancel();
+ mExitGestureDetectionModeDelayed.cancel();
+ mSendTouchExplorationEndDelayed.cancel();
+ mSendTouchInteractionEndDelayed.cancel();
// Reset the pointer trackers.
mReceivedPointerTracker.clear();
mInjectedPointerTracker.clear();
@@ -347,7 +343,7 @@
// last hover exit event.
if (mSendTouchExplorationEndDelayed.isPending()
&& eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
- mSendTouchExplorationEndDelayed.remove();
+ mSendTouchExplorationEndDelayed.cancel();
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END);
}
@@ -355,7 +351,7 @@
// last hover exit and the touch exploration gesture end events.
if (mSendTouchInteractionEndDelayed.isPending()
&& eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
- mSendTouchInteractionEndDelayed.remove();
+ mSendTouchInteractionEndDelayed.cancel();
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
}
@@ -390,95 +386,80 @@
private void handleMotionEventStateTouchExploring(MotionEvent event, MotionEvent rawEvent,
int policyFlags) {
ReceivedPointerTracker receivedTracker = mReceivedPointerTracker;
- final int activePointerCount = receivedTracker.getActivePointerCount();
mVelocityTracker.addMovement(rawEvent);
mDoubleTapDetector.onMotionEvent(event, policyFlags);
switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
+ case MotionEvent.ACTION_DOWN: {
mAms.onTouchInteractionStart();
+
// Pre-feed the motion events to the gesture detector since we
// have a distance slop before getting into gesture detection
// mode and not using the points within this slop significantly
// decreases the quality of gesture recognition.
handleMotionEventGestureDetecting(rawEvent, policyFlags);
- //$FALL-THROUGH$
- case MotionEvent.ACTION_POINTER_DOWN: {
- switch (activePointerCount) {
- case 0: {
- throw new IllegalStateException("The must always be one active pointer in"
- + "touch exploring state!");
- }
- case 1: {
- // If we still have not notified the user for the last
- // touch, we figure out what to do. If were waiting
- // we resent the delayed callback and wait again.
- if (mSendHoverEnterDelayed.isPending()) {
- mSendHoverEnterDelayed.remove();
- mSendHoverExitDelayed.remove();
- }
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_START);
- if (mSendTouchExplorationEndDelayed.isPending()) {
- mSendTouchExplorationEndDelayed.forceSendAndRemove();
- }
+ // If we still have not notified the user for the last
+ // touch, we figure out what to do. If were waiting
+ // we resent the delayed callback and wait again.
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ mPerformLongPressDelayed.cancel();
- if (mSendTouchInteractionEndDelayed.isPending()) {
- mSendTouchInteractionEndDelayed.forceSendAndRemove();
- }
+ if (mSendTouchExplorationEndDelayed.isPending()) {
+ mSendTouchExplorationEndDelayed.forceSendAndRemove();
+ }
- // Every pointer that goes down is active until it moves or
- // another one goes down. Hence, having more than one pointer
- // down we have already send the interaction start event.
- if (event.getPointerCount() == 1) {
- sendAccessibilityEvent(
- AccessibilityEvent.TYPE_TOUCH_INTERACTION_START);
- }
+ if (mSendTouchInteractionEndDelayed.isPending()) {
+ mSendTouchInteractionEndDelayed.forceSendAndRemove();
+ }
- mPerformLongPressDelayed.remove();
+ // Cache the event until we discern exploration from gesturing.
+ mSendHoverEnterAndMoveDelayed.addEvent(event);
- // If we have the first tap schedule a long press and break
- // since we do not want to schedule hover enter because
- // the delayed callback will kick in before the long click.
- // This would lead to a state transition resulting in long
- // pressing the item below the double taped area which is
- // not necessary where accessibility focus is.
- if (mDoubleTapDetector.firstTapDetected()) {
- // We got a tap now post a long press action.
- mPerformLongPressDelayed.post(event, policyFlags);
- break;
- }
- if (!mTouchExplorationInProgress) {
- // Deliver hover enter with a delay to have a chance
- // to detect what the user is trying to do.
- final int pointerId = receivedTracker.getPrimaryActivePointerId();
- final int pointerIdBits = (1 << pointerId);
- mSendHoverEnterDelayed.post(event, true, pointerIdBits, policyFlags);
- }
- } break;
- default: {
- /* do nothing - let the code for ACTION_MOVE decide what to do */
- } break;
+ // If we have the first tap, schedule a long press and break
+ // since we do not want to schedule hover enter because
+ // the delayed callback will kick in before the long click.
+ // This would lead to a state transition resulting in long
+ // pressing the item below the double taped area which is
+ // not necessary where accessibility focus is.
+ if (mDoubleTapDetector.firstTapDetected()) {
+ // We got a tap now post a long press action.
+ mPerformLongPressDelayed.post(event, policyFlags);
+ break;
+ }
+ if (!mTouchExplorationInProgress) {
+ // Deliver hover enter with a delay to have a chance
+ // to detect what the user is trying to do.
+ final int pointerId = receivedTracker.getPrimaryPointerId();
+ final int pointerIdBits = (1 << pointerId);
+ mSendHoverEnterAndMoveDelayed.post(event, true, pointerIdBits, policyFlags);
}
} break;
+ case MotionEvent.ACTION_POINTER_DOWN: {
+ /* do nothing - let the code for ACTION_MOVE decide what to do */
+ } break;
case MotionEvent.ACTION_MOVE: {
- final int pointerId = receivedTracker.getPrimaryActivePointerId();
+ final int pointerId = receivedTracker.getPrimaryPointerId();
final int pointerIndex = event.findPointerIndex(pointerId);
final int pointerIdBits = (1 << pointerId);
- switch (activePointerCount) {
- case 0: {
- /* do nothing - no active pointers so we swallow the event */
- } break;
+ switch (event.getPointerCount()) {
case 1: {
// We have not started sending events since we try to
// figure out what the user is doing.
- if (mSendHoverEnterDelayed.isPending()) {
+ if (mSendHoverEnterAndMoveDelayed.isPending()) {
// Pre-feed the motion events to the gesture detector since we
// have a distance slop before getting into gesture detection
// mode and not using the points within this slop significantly
// decreases the quality of gesture recognition.
handleMotionEventGestureDetecting(rawEvent, policyFlags);
+
+ // Cache the event until we discern exploration from gesturing.
+ mSendHoverEnterAndMoveDelayed.addEvent(event);
+
// It is *important* to use the distance traveled by the pointers
// on the screen which may or may not be magnified.
final float deltaX = receivedTracker.getReceivedPointerDownX(pointerId)
@@ -500,9 +481,9 @@
// clear the current state and try to detect.
mCurrentState = STATE_GESTURE_DETECTING;
mVelocityTracker.clear();
- mSendHoverEnterDelayed.remove();
- mSendHoverExitDelayed.remove();
- mPerformLongPressDelayed.remove();
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ mPerformLongPressDelayed.cancel();
mExitGestureDetectionModeDelayed.post();
// Send accessibility event to announce the start
// of gesture recognition.
@@ -511,9 +492,9 @@
} else {
// We have just decided that the user is touch,
// exploring so start sending events.
- mSendHoverEnterDelayed.forceSendAndRemove();
- mSendHoverExitDelayed.remove();
- mPerformLongPressDelayed.remove();
+ mSendHoverEnterAndMoveDelayed.forceSendAndRemove();
+ mSendHoverExitDelayed.cancel();
+ mPerformLongPressDelayed.cancel();
sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE,
pointerIdBits, policyFlags);
}
@@ -532,11 +513,11 @@
final double moveDelta = Math.hypot(deltaX, deltaY);
// The user has moved enough for us to decide.
if (moveDelta > mTouchSlop) {
- mPerformLongPressDelayed.remove();
+ mPerformLongPressDelayed.cancel();
}
}
- // The user is wither double tapping or performing long
- // press so do not send move events yet.
+ // The user is either double tapping or performing a long
+ // press, so do not send move events yet.
if (mDoubleTapDetector.firstTapDetected()) {
break;
}
@@ -548,14 +529,14 @@
case 2: {
// More than one pointer so the user is not touch exploring
// and now we have to decide whether to delegate or drag.
- if (mSendHoverEnterDelayed.isPending()) {
+ if (mSendHoverEnterAndMoveDelayed.isPending()) {
// We have not started sending events so cancel
// scheduled sending events.
- mSendHoverEnterDelayed.remove();
- mSendHoverExitDelayed.remove();
- mPerformLongPressDelayed.remove();
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ mPerformLongPressDelayed.cancel();
} else {
- mPerformLongPressDelayed.remove();
+ mPerformLongPressDelayed.cancel();
// If the user is touch exploring the second pointer may be
// performing a double tap to activate an item without need
// for the user to lift his exploring finger.
@@ -590,21 +571,21 @@
} else {
// Two pointers moving arbitrary are delegated to the view hierarchy.
mCurrentState = STATE_DELEGATING;
- sendDownForAllActiveNotInjectedPointers(event, policyFlags);
+ sendDownForAllNotInjectedPointers(event, policyFlags);
}
mVelocityTracker.clear();
} break;
default: {
// More than one pointer so the user is not touch exploring
// and now we have to decide whether to delegate or drag.
- if (mSendHoverEnterDelayed.isPending()) {
+ if (mSendHoverEnterAndMoveDelayed.isPending()) {
// We have not started sending events so cancel
// scheduled sending events.
- mSendHoverEnterDelayed.remove();
- mSendHoverExitDelayed.remove();
- mPerformLongPressDelayed.remove();
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ mPerformLongPressDelayed.cancel();
} else {
- mPerformLongPressDelayed.remove();
+ mPerformLongPressDelayed.cancel();
// We are sending events so send exit and gesture
// end since we transition to another state.
sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
@@ -612,43 +593,34 @@
// More than two pointers are delegated to the view hierarchy.
mCurrentState = STATE_DELEGATING;
- sendDownForAllActiveNotInjectedPointers(event, policyFlags);
+ sendDownForAllNotInjectedPointers(event, policyFlags);
mVelocityTracker.clear();
}
}
} break;
- case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_UP: {
mAms.onTouchInteractionEnd();
// We know that we do not need the pre-fed gesture points are not
// needed anymore since the last pointer just went up.
mStrokeBuffer.clear();
- //$FALL-THROUGH$
- case MotionEvent.ACTION_POINTER_UP: {
- final int pointerId = receivedTracker.getLastReceivedUpPointerId();
+ final int pointerId = event.getPointerId(event.getActionIndex());
final int pointerIdBits = (1 << pointerId);
- switch (activePointerCount) {
- case 0: {
- // If the pointer that went up was not active we have nothing to do.
- if (!receivedTracker.wasLastReceivedUpPointerActive()) {
- break;
- }
- mPerformLongPressDelayed.remove();
-
- // If we have not delivered the enter schedule exit.
- if (mSendHoverEnterDelayed.isPending()) {
- mSendHoverExitDelayed.post(event, false, pointerIdBits, policyFlags);
- } else {
- // The user is touch exploring so we send events for end.
- sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
- }
-
- if (!mSendTouchInteractionEndDelayed.isPending()) {
- mSendTouchInteractionEndDelayed.post();
- }
- } break;
- }
+ mPerformLongPressDelayed.cancel();
mVelocityTracker.clear();
+
+ if (mSendHoverEnterAndMoveDelayed.isPending()) {
+ // If we have not delivered the enter schedule an exit.
+ mSendHoverExitDelayed.post(event, pointerIdBits, policyFlags);
+ } else {
+ // The user is touch exploring so we send events for end.
+ sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
+ }
+
+ if (!mSendTouchInteractionEndDelayed.isPending()) {
+ mSendTouchInteractionEndDelayed.post();
+ }
+
} break;
case MotionEvent.ACTION_CANCEL: {
clear(event, policyFlags);
@@ -676,29 +648,19 @@
if (mDraggingPointerId != INVALID_POINTER_ID) {
sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits, policyFlags);
}
- sendDownForAllActiveNotInjectedPointers(event, policyFlags);
+ sendDownForAllNotInjectedPointers(event, policyFlags);
} break;
case MotionEvent.ACTION_MOVE: {
- final int activePointerCount = mReceivedPointerTracker.getActivePointerCount();
- switch (activePointerCount) {
+ switch (event.getPointerCount()) {
case 1: {
// do nothing
} break;
case 2: {
if (isDraggingGesture(event)) {
- // If the dragging pointer are closer that a given distance we
- // use the location of the primary one. Otherwise, we take the
- // middle between the pointers.
- int[] pointerIds = mTempPointerIds;
- mReceivedPointerTracker.populateActivePointerIds(pointerIds);
-
- final int firstPtrIndex = event.findPointerIndex(pointerIds[0]);
- final int secondPtrIndex = event.findPointerIndex(pointerIds[1]);
-
- final float firstPtrX = event.getX(firstPtrIndex);
- final float firstPtrY = event.getY(firstPtrIndex);
- final float secondPtrX = event.getX(secondPtrIndex);
- final float secondPtrY = event.getY(secondPtrIndex);
+ final float firstPtrX = event.getX(0);
+ final float firstPtrY = event.getY(0);
+ final float secondPtrX = event.getX(1);
+ final float secondPtrY = event.getY(1);
final float deltaX = firstPtrX - secondPtrX;
final float deltaY = firstPtrY - secondPtrY;
@@ -718,8 +680,8 @@
// Send an event to the end of the drag gesture.
sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits,
policyFlags);
- // Deliver all active pointers to the view hierarchy.
- sendDownForAllActiveNotInjectedPointers(event, policyFlags);
+ // Deliver all pointers to the view hierarchy.
+ sendDownForAllNotInjectedPointers(event, policyFlags);
}
} break;
default: {
@@ -727,8 +689,8 @@
// Send an event to the end of the drag gesture.
sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits,
policyFlags);
- // Deliver all active pointers to the view hierarchy.
- sendDownForAllActiveNotInjectedPointers(event, policyFlags);
+ // Deliver all pointers to the view hierarchy.
+ sendDownForAllNotInjectedPointers(event, policyFlags);
}
}
} break;
@@ -771,37 +733,21 @@
throw new IllegalStateException("Delegating state can only be reached if "
+ "there is at least one pointer down!");
}
- case MotionEvent.ACTION_MOVE: {
- // Check whether some other pointer became active because they have moved
- // a given distance and if such exist send them to the view hierarchy
- final int notInjectedCount = getNotInjectedActivePointerCount(
- mReceivedPointerTracker, mInjectedPointerTracker);
- if (notInjectedCount > 0) {
- MotionEvent prototype = MotionEvent.obtain(event);
- sendDownForAllActiveNotInjectedPointers(prototype, policyFlags);
- }
- } break;
- case MotionEvent.ACTION_UP:
- // Announce the end of a new touch interaction.
- sendAccessibilityEvent(
- AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
- //$FALL-THROUGH$
- case MotionEvent.ACTION_POINTER_UP: {
+ case MotionEvent.ACTION_UP: {
+ // Announce the end of a the touch interaction.
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
mAms.onTouchInteractionEnd();
mLongPressingPointerId = -1;
mLongPressingPointerDeltaX = 0;
mLongPressingPointerDeltaY = 0;
- // No active pointers => go to initial state.
- if (mReceivedPointerTracker.getActivePointerCount() == 0) {
- mCurrentState = STATE_TOUCH_EXPLORING;
- }
+ mCurrentState = STATE_TOUCH_EXPLORING;
} break;
case MotionEvent.ACTION_CANCEL: {
clear(event, policyFlags);
} break;
}
- // Deliver the event striping out inactive pointers.
- sendMotionEventStripInactivePointers(event, policyFlags);
+ // Deliver the event.
+ sendMotionEvent(event, event.getAction(), ALL_POINTER_ID_BITS, policyFlags);
}
private void handleMotionEventGestureDetecting(MotionEvent event, int policyFlags) {
@@ -826,12 +772,10 @@
} break;
case MotionEvent.ACTION_UP: {
mAms.onTouchInteractionEnd();
- // Announce the end of gesture recognition.
- sendAccessibilityEvent(
- AccessibilityEvent.TYPE_GESTURE_DETECTION_END);
- // Announce the end of a new touch interaction.
- sendAccessibilityEvent(
- AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
+ // Announce the end of the gesture recognition.
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_END);
+ // Announce the end of a the touch interaction.
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
float x = event.getX();
float y = event.getY();
@@ -858,7 +802,7 @@
}
mStrokeBuffer.clear();
- mExitGestureDetectionModeDelayed.remove();
+ mExitGestureDetectionModeDelayed.cancel();
mCurrentState = STATE_TOUCH_EXPLORING;
} break;
case MotionEvent.ACTION_CANCEL: {
@@ -889,40 +833,26 @@
}
/**
- * Sends down events to the view hierarchy for all active pointers which are
+ * Sends down events to the view hierarchy for all pointers which are
* not already being delivered i.e. pointers that are not yet injected.
*
* @param prototype The prototype from which to create the injected events.
* @param policyFlags The policy flags associated with the event.
*/
- private void sendDownForAllActiveNotInjectedPointers(MotionEvent prototype, int policyFlags) {
- ReceivedPointerTracker receivedPointers = mReceivedPointerTracker;
+ private void sendDownForAllNotInjectedPointers(MotionEvent prototype, int policyFlags) {
InjectedPointerTracker injectedPointers = mInjectedPointerTracker;
+
+ // Inject the injected pointers.
int pointerIdBits = 0;
final int pointerCount = prototype.getPointerCount();
-
- // Find which pointers are already injected.
for (int i = 0; i < pointerCount; i++) {
final int pointerId = prototype.getPointerId(i);
- if (injectedPointers.isInjectedPointerDown(pointerId)) {
- pointerIdBits |= (1 << pointerId);
- }
- }
-
- // Inject the active and not injected pointers.
- for (int i = 0; i < pointerCount; i++) {
- final int pointerId = prototype.getPointerId(i);
- // Skip inactive pointers.
- if (!receivedPointers.isActivePointer(pointerId)) {
- continue;
- }
// Do not send event for already delivered pointers.
- if (injectedPointers.isInjectedPointerDown(pointerId)) {
- continue;
+ if (!injectedPointers.isInjectedPointerDown(pointerId)) {
+ pointerIdBits |= (1 << pointerId);
+ final int action = computeInjectionAction(MotionEvent.ACTION_DOWN, i);
+ sendMotionEvent(prototype, action, pointerIdBits, policyFlags);
}
- pointerIdBits |= (1 << pointerId);
- final int action = computeInjectionAction(MotionEvent.ACTION_DOWN, i);
- sendMotionEvent(prototype, action, pointerIdBits, policyFlags);
}
}
@@ -959,7 +889,7 @@
}
/**
- * Sends up events to the view hierarchy for all active pointers which are
+ * Sends up events to the view hierarchy for all pointers which are
* already being delivered i.e. pointers that are injected.
*
* @param prototype The prototype from which to create the injected events.
@@ -982,58 +912,13 @@
}
/**
- * Sends a motion event by first stripping the inactive pointers.
- *
- * @param prototype The prototype from which to create the injected event.
- * @param policyFlags The policy flags associated with the event.
- */
- private void sendMotionEventStripInactivePointers(MotionEvent prototype, int policyFlags) {
- ReceivedPointerTracker receivedTracker = mReceivedPointerTracker;
-
- // All pointers active therefore we just inject the event as is.
- if (prototype.getPointerCount() == receivedTracker.getActivePointerCount()) {
- sendMotionEvent(prototype, prototype.getAction(), ALL_POINTER_ID_BITS, policyFlags);
- return;
- }
-
- // No active pointers and the one that just went up was not
- // active, therefore we have nothing to do.
- if (receivedTracker.getActivePointerCount() == 0
- && !receivedTracker.wasLastReceivedUpPointerActive()) {
- return;
- }
-
- // If the action pointer going up/down is not active we have nothing to do.
- // However, for moves we keep going to report moves of active pointers.
- final int actionMasked = prototype.getActionMasked();
- final int actionPointerId = prototype.getPointerId(prototype.getActionIndex());
- if (actionMasked != MotionEvent.ACTION_MOVE) {
- if (!receivedTracker.isActiveOrWasLastActiveUpPointer(actionPointerId)) {
- return;
- }
- }
-
- // If the pointer is active or the pointer that just went up
- // was active we keep the pointer data in the event.
- int pointerIdBits = 0;
- final int pointerCount = prototype.getPointerCount();
- for (int pointerIndex = 0; pointerIndex < pointerCount; pointerIndex++) {
- final int pointerId = prototype.getPointerId(pointerIndex);
- if (receivedTracker.isActiveOrWasLastActiveUpPointer(pointerId)) {
- pointerIdBits |= (1 << pointerId);
- }
- }
- sendMotionEvent(prototype, prototype.getAction(), pointerIdBits, policyFlags);
- }
-
- /**
* Sends an up and down events.
*
* @param prototype The prototype from which to create the injected events.
* @param policyFlags The policy flags associated with the event.
*/
private void sendActionDownAndUp(MotionEvent prototype, int policyFlags) {
- // Tap with the pointer that last explored - we may have inactive pointers.
+ // Tap with the pointer that last explored.
final int pointerId = prototype.getPointerId(prototype.getActionIndex());
final int pointerIdBits = (1 << pointerId);
sendMotionEvent(prototype, MotionEvent.ACTION_DOWN, pointerIdBits, policyFlags);
@@ -1215,9 +1100,9 @@
}
// Remove pending event deliveries.
- mSendHoverEnterDelayed.remove();
- mSendHoverExitDelayed.remove();
- mPerformLongPressDelayed.remove();
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ mPerformLongPressDelayed.cancel();
if (mSendTouchExplorationEndDelayed.isPending()) {
mSendTouchExplorationEndDelayed.forceSendAndRemove();
@@ -1307,21 +1192,16 @@
*/
private boolean isDraggingGesture(MotionEvent event) {
ReceivedPointerTracker receivedTracker = mReceivedPointerTracker;
- int[] pointerIds = mTempPointerIds;
- receivedTracker.populateActivePointerIds(pointerIds);
- final int firstPtrIndex = event.findPointerIndex(pointerIds[0]);
- final int secondPtrIndex = event.findPointerIndex(pointerIds[1]);
+ final float firstPtrX = event.getX(0);
+ final float firstPtrY = event.getY(0);
+ final float secondPtrX = event.getX(1);
+ final float secondPtrY = event.getY(1);
- final float firstPtrX = event.getX(firstPtrIndex);
- final float firstPtrY = event.getY(firstPtrIndex);
- final float secondPtrX = event.getX(secondPtrIndex);
- final float secondPtrY = event.getY(secondPtrIndex);
-
- final float firstPtrDownX = receivedTracker.getReceivedPointerDownX(firstPtrIndex);
- final float firstPtrDownY = receivedTracker.getReceivedPointerDownY(firstPtrIndex);
- final float secondPtrDownX = receivedTracker.getReceivedPointerDownX(secondPtrIndex);
- final float secondPtrDownY = receivedTracker.getReceivedPointerDownY(secondPtrIndex);
+ final float firstPtrDownX = receivedTracker.getReceivedPointerDownX(0);
+ final float firstPtrDownY = receivedTracker.getReceivedPointerDownY(0);
+ final float secondPtrDownX = receivedTracker.getReceivedPointerDownX(1);
+ final float secondPtrDownY = receivedTracker.getReceivedPointerDownY(1);
return GestureUtils.isDraggingGesture(firstPtrDownX, firstPtrDownY, secondPtrDownX,
secondPtrDownY, firstPtrX, firstPtrY, secondPtrX, secondPtrY,
@@ -1350,16 +1230,6 @@
}
/**
- * @return The number of non injected active pointers.
- */
- private int getNotInjectedActivePointerCount(ReceivedPointerTracker receivedTracker,
- InjectedPointerTracker injectedTracker) {
- final int pointerState = receivedTracker.getActivePointers()
- & ~injectedTracker.getInjectedPointersDown();
- return Integer.bitCount(pointerState);
- }
-
- /**
* Class for delayed exiting from gesture detecting mode.
*/
private final class ExitGestureDetectionModeDelayed implements Runnable {
@@ -1368,7 +1238,7 @@
mHandler.postDelayed(this, EXIT_GESTURE_DETECTION_TIMEOUT);
}
- public void remove() {
+ public void cancel() {
mHandler.removeCallbacks(this);
}
@@ -1396,21 +1266,21 @@
mHandler.postDelayed(this, ViewConfiguration.getLongPressTimeout());
}
- public void remove() {
- if (isPending()) {
+ public void cancel() {
+ if (mEvent != null) {
mHandler.removeCallbacks(this);
clear();
}
}
- public boolean isPending() {
- return (mEvent != null);
+ private boolean isPending() {
+ return mHandler.hasCallbacks(this);
}
@Override
public void run() {
- // Active pointers should not be zero when running this command.
- if (mReceivedPointerTracker.getActivePointerCount() == 0) {
+ // Pointers should not be zero when running this command.
+ if (mReceivedPointerTracker.getLastReceivedEvent().getPointerCount() == 0) {
return;
}
@@ -1461,14 +1331,11 @@
sendHoverExitAndTouchExplorationGestureEndIfNeeded(mPolicyFlags);
mCurrentState = STATE_DELEGATING;
- sendDownForAllActiveNotInjectedPointers(mEvent, mPolicyFlags);
+ sendDownForAllNotInjectedPointers(mEvent, mPolicyFlags);
clear();
}
private void clear() {
- if (!isPending()) {
- return;
- }
mEvent.recycle();
mEvent = null;
mPolicyFlags = 0;
@@ -1476,59 +1343,114 @@
}
/**
- * Class for delayed sending of hover events.
+ * Class for delayed sending of hover enter and move events.
*/
- class SendHoverDelayed implements Runnable {
- private final String LOG_TAG_SEND_HOVER_DELAYED = SendHoverDelayed.class.getName();
+ class SendHoverEnterAndMoveDelayed implements Runnable {
+ private final String LOG_TAG_SEND_HOVER_DELAYED = "SendHoverEnterAndMoveDelayed";
- private final int mHoverAction;
- private final boolean mGestureStarted;
+ private final List<MotionEvent> mEvents = new ArrayList<MotionEvent>();
+
+ private int mPointerIdBits;
+ private int mPolicyFlags;
+
+ public void post(MotionEvent event, boolean touchExplorationInProgress,
+ int pointerIdBits, int policyFlags) {
+ cancel();
+ addEvent(event);
+ mPointerIdBits = pointerIdBits;
+ mPolicyFlags = policyFlags;
+ mHandler.postDelayed(this, mDetermineUserIntentTimeout);
+ }
+
+ public void addEvent(MotionEvent event) {
+ mEvents.add(MotionEvent.obtain(event));
+ }
+
+ public void cancel() {
+ if (isPending()) {
+ mHandler.removeCallbacks(this);
+ clear();
+ }
+ }
+
+ private boolean isPending() {
+ return mHandler.hasCallbacks(this);
+ }
+
+ private void clear() {
+ mPointerIdBits = -1;
+ mPolicyFlags = 0;
+ final int eventCount = mEvents.size();
+ for (int i = eventCount - 1; i >= 0; i--) {
+ mEvents.remove(i).recycle();
+ }
+ }
+
+ public void forceSendAndRemove() {
+ if (isPending()) {
+ run();
+ cancel();
+ }
+ }
+
+ public void run() {
+ // Send an accessibility event to announce the touch exploration start.
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
+
+ if (!mEvents.isEmpty()) {
+ // Deliver a down event.
+ sendMotionEvent(mEvents.get(0), MotionEvent.ACTION_HOVER_ENTER,
+ mPointerIdBits, mPolicyFlags);
+ if (DEBUG) {
+ Slog.d(LOG_TAG_SEND_HOVER_DELAYED,
+ "Injecting motion event: ACTION_HOVER_ENTER");
+ }
+
+ // Deliver move events.
+ final int eventCount = mEvents.size();
+ for (int i = 1; i < eventCount; i++) {
+ sendMotionEvent(mEvents.get(i), MotionEvent.ACTION_HOVER_MOVE,
+ mPointerIdBits, mPolicyFlags);
+ if (DEBUG) {
+ Slog.d(LOG_TAG_SEND_HOVER_DELAYED,
+ "Injecting motion event: ACTION_HOVER_MOVE");
+ }
+ }
+ }
+ clear();
+ }
+ }
+
+ /**
+ * Class for delayed sending of hover exit events.
+ */
+ class SendHoverExitDelayed implements Runnable {
+ private final String LOG_TAG_SEND_HOVER_DELAYED = "SendHoverExitDelayed";
private MotionEvent mPrototype;
private int mPointerIdBits;
private int mPolicyFlags;
- public SendHoverDelayed(int hoverAction, boolean gestureStarted) {
- mHoverAction = hoverAction;
- mGestureStarted = gestureStarted;
- }
-
- public void post(MotionEvent prototype, boolean touchExplorationInProgress,
- int pointerIdBits, int policyFlags) {
- remove();
+ public void post(MotionEvent prototype, int pointerIdBits, int policyFlags) {
+ cancel();
mPrototype = MotionEvent.obtain(prototype);
mPointerIdBits = pointerIdBits;
mPolicyFlags = policyFlags;
mHandler.postDelayed(this, mDetermineUserIntentTimeout);
}
- public float getX() {
+ public void cancel() {
if (isPending()) {
- return mPrototype.getX();
+ mHandler.removeCallbacks(this);
+ clear();
}
- return 0;
- }
-
- public float getY() {
- if (isPending()) {
- return mPrototype.getY();
- }
- return 0;
- }
-
- public void remove() {
- mHandler.removeCallbacks(this);
- clear();
}
private boolean isPending() {
- return (mPrototype != null);
+ return mHandler.hasCallbacks(this);
}
private void clear() {
- if (!isPending()) {
- return;
- }
mPrototype.recycle();
mPrototype = null;
mPointerIdBits = -1;
@@ -1538,29 +1460,25 @@
public void forceSendAndRemove() {
if (isPending()) {
run();
- remove();
+ cancel();
}
}
public void run() {
if (DEBUG) {
- Slog.d(LOG_TAG_SEND_HOVER_DELAYED, "Injecting motion event: "
- + MotionEvent.actionToString(mHoverAction));
- Slog.d(LOG_TAG_SEND_HOVER_DELAYED, mGestureStarted ?
- "touchExplorationGestureStarted" : "touchExplorationGestureEnded");
+ Slog.d(LOG_TAG_SEND_HOVER_DELAYED, "Injecting motion event:"
+ + " ACTION_HOVER_EXIT");
}
- if (mGestureStarted) {
- sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
- } else {
- if (!mSendTouchExplorationEndDelayed.isPending()) {
- mSendTouchExplorationEndDelayed.post();
- }
- if (mSendTouchInteractionEndDelayed.isPending()) {
- mSendTouchInteractionEndDelayed.remove();
- mSendTouchInteractionEndDelayed.post();
- }
+ sendMotionEvent(mPrototype, MotionEvent.ACTION_HOVER_EXIT,
+ mPointerIdBits, mPolicyFlags);
+ if (!mSendTouchExplorationEndDelayed.isPending()) {
+ mSendTouchExplorationEndDelayed.cancel();
+ mSendTouchExplorationEndDelayed.post();
}
- sendMotionEvent(mPrototype, mHoverAction, mPointerIdBits, mPolicyFlags);
+ if (mSendTouchInteractionEndDelayed.isPending()) {
+ mSendTouchInteractionEndDelayed.cancel();
+ mSendTouchInteractionEndDelayed.post();
+ }
clear();
}
}
@@ -1574,7 +1492,7 @@
mDelay = delay;
}
- public void remove() {
+ public void cancel() {
mHandler.removeCallbacks(this);
}
@@ -1589,7 +1507,7 @@
public void forceSendAndRemove() {
if (isPending()) {
run();
- remove();
+ cancel();
}
}
@@ -1736,15 +1654,6 @@
class ReceivedPointerTracker {
private static final String LOG_TAG_RECEIVED_POINTER_TRACKER = "ReceivedPointerTracker";
- // The coefficient by which to multiply
- // ViewConfiguration.#getScaledTouchSlop()
- // to compute #mThresholdActivePointer.
- private static final int COEFFICIENT_ACTIVE_POINTER = 2;
-
- // Pointers that moved less than mThresholdActivePointer
- // are considered active i.e. are ignored.
- private final double mThresholdActivePointer;
-
// Keep track of where and when a pointer went down.
private final float[] mReceivedPointerDownX = new float[MAX_POINTER_COUNT];
private final float[] mReceivedPointerDownY = new float[MAX_POINTER_COUNT];
@@ -1756,36 +1665,19 @@
// The edge flags of the last received down event.
private int mLastReceivedDownEdgeFlags;
- // Which down pointers are active.
- private int mActivePointers;
-
- // Primary active pointer which is either the first that went down
- // or if it goes up the next active that most recently went down.
- private int mPrimaryActivePointerId;
-
- // Flag indicating that there is at least one active pointer moving.
- private boolean mHasMovingActivePointer;
+ // Primary pointer which is either the first that went down
+ // or if it goes up the next one that most recently went down.
+ private int mPrimaryPointerId;
// Keep track of the last up pointer data.
private long mLastReceivedUpPointerDownTime;
private int mLastReceivedUpPointerId;
- private boolean mLastReceivedUpPointerActive;
private float mLastReceivedUpPointerDownX;
private float mLastReceivedUpPointerDownY;
private MotionEvent mLastReceivedEvent;
/**
- * Creates a new instance.
- *
- * @param context Context for looking up resources.
- */
- public ReceivedPointerTracker(Context context) {
- mThresholdActivePointer =
- ViewConfiguration.get(context).getScaledTouchSlop() * COEFFICIENT_ACTIVE_POINTER;
- }
-
- /**
* Clears the internals state.
*/
public void clear() {
@@ -1793,12 +1685,9 @@
Arrays.fill(mReceivedPointerDownY, 0);
Arrays.fill(mReceivedPointerDownTime, 0);
mReceivedPointersDown = 0;
- mActivePointers = 0;
- mPrimaryActivePointerId = 0;
- mHasMovingActivePointer = false;
+ mPrimaryPointerId = 0;
mLastReceivedUpPointerDownTime = 0;
mLastReceivedUpPointerId = 0;
- mLastReceivedUpPointerActive = false;
mLastReceivedUpPointerDownX = 0;
mLastReceivedUpPointerDownY = 0;
}
@@ -1822,9 +1711,6 @@
case MotionEvent.ACTION_POINTER_DOWN: {
handleReceivedPointerDown(event.getActionIndex(), event);
} break;
- case MotionEvent.ACTION_MOVE: {
- handleReceivedPointerMove(event);
- } break;
case MotionEvent.ACTION_UP: {
handleReceivedPointerUp(event.getActionIndex(), event);
} break;
@@ -1852,20 +1738,6 @@
}
/**
- * @return The bits of the pointers that are active.
- */
- public int getActivePointers() {
- return mActivePointers;
- }
-
- /**
- * @return The number of down input pointers that are active.
- */
- public int getActivePointerCount() {
- return Integer.bitCount(mActivePointers);
- }
-
- /**
* Whether an received pointer is down.
*
* @param pointerId The unique pointer id.
@@ -1877,17 +1749,6 @@
}
/**
- * Whether an input pointer is active.
- *
- * @param pointerId The unique pointer id.
- * @return True if the pointer is active.
- */
- public boolean isActivePointer(int pointerId) {
- final int pointerFlag = (1 << pointerId);
- return (mActivePointers & pointerFlag) != 0;
- }
-
- /**
* @param pointerId The unique pointer id.
* @return The X coordinate where the pointer went down.
*/
@@ -1914,11 +1775,11 @@
/**
* @return The id of the primary pointer.
*/
- public int getPrimaryActivePointerId() {
- if (mPrimaryActivePointerId == INVALID_POINTER_ID) {
- mPrimaryActivePointerId = findPrimaryActivePointer();
+ public int getPrimaryPointerId() {
+ if (mPrimaryPointerId == INVALID_POINTER_ID) {
+ mPrimaryPointerId = findPrimaryPointer();
}
- return mPrimaryActivePointerId;
+ return mPrimaryPointerId;
}
/**
@@ -1929,14 +1790,6 @@
}
/**
- * @return The id of the last received pointer that went up.
- */
- public int getLastReceivedUpPointerId() {
- return mLastReceivedUpPointerId;
- }
-
-
- /**
* @return The down X of the last received pointer that went up.
*/
public float getLastReceivedUpPointerDownX() {
@@ -1958,39 +1811,6 @@
}
/**
- * @return Whether the last received pointer that went up was active.
- */
- public boolean wasLastReceivedUpPointerActive() {
- return mLastReceivedUpPointerActive;
- }
- /**
- * Populates the active pointer IDs to the given array.
- * <p>
- * Note: The client is responsible for providing large enough array.
- *
- * @param outPointerIds The array to which to write the active pointers.
- */
- public void populateActivePointerIds(int[] outPointerIds) {
- int index = 0;
- for (int idBits = mActivePointers; idBits != 0; ) {
- final int id = Integer.numberOfTrailingZeros(idBits);
- idBits &= ~(1 << id);
- outPointerIds[index] = id;
- index++;
- }
- }
-
- /**
- * @param pointerId The unique pointer id.
- * @return Whether the pointer is active or was the last active than went up.
- */
- public boolean isActiveOrWasLastActiveUpPointer(int pointerId) {
- return (isActivePointer(pointerId)
- || (mLastReceivedUpPointerId == pointerId
- && mLastReceivedUpPointerActive));
- }
-
- /**
* Handles a received pointer down event.
*
* @param pointerIndex The index of the pointer that has changed.
@@ -2002,7 +1822,6 @@
mLastReceivedUpPointerId = 0;
mLastReceivedUpPointerDownTime = 0;
- mLastReceivedUpPointerActive = false;
mLastReceivedUpPointerDownX = 0;
mLastReceivedUpPointerDownX = 0;
@@ -2013,25 +1832,7 @@
mReceivedPointerDownY[pointerId] = event.getY(pointerIndex);
mReceivedPointerDownTime[pointerId] = event.getEventTime();
- if (!mHasMovingActivePointer) {
- // If still no moving active pointers every
- // down pointer is the only active one.
- mActivePointers = pointerFlag;
- mPrimaryActivePointerId = pointerId;
- } else {
- // If at least one moving active pointer every
- // subsequent down pointer is active.
- mActivePointers |= pointerFlag;
- }
- }
-
- /**
- * Handles a received pointer move event.
- *
- * @param event The event to be handled.
- */
- private void handleReceivedPointerMove(MotionEvent event) {
- detectActivePointers(event);
+ mPrimaryPointerId = pointerId;
}
/**
@@ -2046,80 +1847,34 @@
mLastReceivedUpPointerId = pointerId;
mLastReceivedUpPointerDownTime = getReceivedPointerDownTime(pointerId);
- mLastReceivedUpPointerActive = isActivePointer(pointerId);
mLastReceivedUpPointerDownX = mReceivedPointerDownX[pointerId];
mLastReceivedUpPointerDownY = mReceivedPointerDownY[pointerId];
mReceivedPointersDown &= ~pointerFlag;
- mActivePointers &= ~pointerFlag;
mReceivedPointerDownX[pointerId] = 0;
mReceivedPointerDownY[pointerId] = 0;
mReceivedPointerDownTime[pointerId] = 0;
- if (mActivePointers == 0) {
- mHasMovingActivePointer = false;
- }
- if (mPrimaryActivePointerId == pointerId) {
- mPrimaryActivePointerId = INVALID_POINTER_ID;
+ if (mPrimaryPointerId == pointerId) {
+ mPrimaryPointerId = INVALID_POINTER_ID;
}
}
/**
- * Detects the active pointers in an event.
- *
- * @param event The event to examine.
+ * @return The primary pointer.
*/
- private void detectActivePointers(MotionEvent event) {
- for (int i = 0, count = event.getPointerCount(); i < count; i++) {
- final int pointerId = event.getPointerId(i);
- if (mHasMovingActivePointer) {
- // If already active => nothing to do.
- if (isActivePointer(pointerId)) {
- continue;
- }
- }
- // Active pointers are ones that moved more than a given threshold.
- final float pointerDeltaMove = computePointerDeltaMove(i, event);
- if (pointerDeltaMove > mThresholdActivePointer) {
- final int pointerFlag = (1 << pointerId);
- mActivePointers |= pointerFlag;
- mHasMovingActivePointer = true;
- }
- }
- }
-
- /**
- * @return The primary active pointer.
- */
- private int findPrimaryActivePointer() {
- int primaryActivePointerId = INVALID_POINTER_ID;
+ private int findPrimaryPointer() {
+ int primaryPointerId = INVALID_POINTER_ID;
long minDownTime = Long.MAX_VALUE;
- // Find the active pointer that went down first.
+ // Find the pointer that went down first.
for (int i = 0, count = mReceivedPointerDownTime.length; i < count; i++) {
- if (isActivePointer(i)) {
- final long downPointerTime = mReceivedPointerDownTime[i];
- if (downPointerTime < minDownTime) {
- minDownTime = downPointerTime;
- primaryActivePointerId = i;
- }
+ final long downPointerTime = mReceivedPointerDownTime[i];
+ if (downPointerTime < minDownTime) {
+ minDownTime = downPointerTime;
+ primaryPointerId = i;
}
}
- return primaryActivePointerId;
- }
-
- /**
- * Computes the move for a given action pointer index since the
- * corresponding pointer went down.
- *
- * @param pointerIndex The action pointer index.
- * @param event The event to examine.
- * @return The distance the pointer has moved.
- */
- private float computePointerDeltaMove(int pointerIndex, MotionEvent event) {
- final int pointerId = event.getPointerId(pointerIndex);
- final float deltaX = event.getX(pointerIndex) - mReceivedPointerDownX[pointerId];
- final float deltaY = event.getY(pointerIndex) - mReceivedPointerDownY[pointerId];
- return (float) Math.hypot(deltaX, deltaY);
+ return primaryPointerId;
}
@Override
@@ -2136,18 +1891,8 @@
}
}
builder.append("]");
- builder.append("\nActive pointers #");
- builder.append(getActivePointerCount());
- builder.append(" [ ");
- for (int i = 0; i < MAX_POINTER_COUNT; i++) {
- if (isActivePointer(i)) {
- builder.append(i);
- builder.append(" ");
- }
- }
- builder.append("]");
- builder.append("\nPrimary active pointer id [ ");
- builder.append(getPrimaryActivePointerId());
+ builder.append("\nPrimary pointer id [ ");
+ builder.append(getPrimaryPointerId());
builder.append(" ]");
builder.append("\n=========================");
return builder.toString();
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 163536a..e78362b 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -22,6 +22,8 @@
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
+import static android.os.Process.SYSTEM_UID;
+import static android.os.Process.PACKAGE_INFO_GID;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
@@ -117,6 +119,7 @@
private final File mPackageListFilename;
private final File mStoppedPackagesFilename;
private final File mBackupStoppedPackagesFilename;
+
final HashMap<String, PackageSetting> mPackages =
new HashMap<String, PackageSetting>();
// List of replaced system applications
@@ -201,6 +204,8 @@
mSettingsFilename = new File(mSystemDir, "packages.xml");
mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
mPackageListFilename = new File(mSystemDir, "packages.list");
+ FileUtils.setPermissions(mPackageListFilename, 0660, SYSTEM_UID, PACKAGE_INFO_GID);
+
// Deprecated: Needed for migration
mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
@@ -1369,13 +1374,15 @@
-1, -1);
// Write package list file now, use a JournaledFile.
- //
- File tempFile = new File(mPackageListFilename.toString() + ".tmp");
+ File tempFile = new File(mPackageListFilename.getAbsolutePath() + ".tmp");
JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile);
- fstr = new FileOutputStream(journal.chooseForWrite());
+ final File writeTarget = journal.chooseForWrite();
+ fstr = new FileOutputStream(writeTarget);
str = new BufferedOutputStream(fstr);
try {
+ FileUtils.setPermissions(fstr.getFD(), 0660, SYSTEM_UID, PACKAGE_INFO_GID);
+
StringBuilder sb = new StringBuilder();
for (final PackageSetting pkg : mPackages.values()) {
ApplicationInfo ai = pkg.pkg.applicationInfo;
@@ -1400,6 +1407,7 @@
// DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
// FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
// system/core/run-as/run-as.c
+ // system/core/sdcard/sdcard.c
//
sb.setLength(0);
sb.append(ai.packageName);
@@ -1421,11 +1429,6 @@
journal.rollback();
}
- FileUtils.setPermissions(mPackageListFilename.toString(),
- FileUtils.S_IRUSR|FileUtils.S_IWUSR
- |FileUtils.S_IRGRP|FileUtils.S_IWGRP,
- -1, -1);
-
writeAllUsersPackageRestrictionsLPr();
return;
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index 4171bb5..361f5d7 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -1148,14 +1148,6 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawPicture(int nativeCanvas,
- int nativePicture) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Canvas.drawPicture is not supported.", null, null /*data*/);
- }
-
- @LayoutlibDelegate
/*package*/ static void finalizer(int nativeCanvas) {
// get the delegate from the native int so that it can be disposed.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);