diff options
| -rw-r--r-- | core/java/android/os/FileUtils.java | 86 | ||||
| -rw-r--r-- | core/java/android/os/Process.java | 13 | ||||
| -rw-r--r-- | core/java/com/android/internal/os/ZygoteInit.java | 2 | ||||
| -rw-r--r-- | core/jni/android/graphics/Canvas.cpp | 17 | ||||
| -rw-r--r-- | core/jni/android/graphics/SurfaceTexture.cpp | 3 | ||||
| -rw-r--r-- | core/jni/android_os_FileUtils.cpp | 42 | ||||
| -rw-r--r-- | graphics/java/android/graphics/Canvas.java | 16 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 19 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.h | 1 | ||||
| -rw-r--r-- | media/mca/filterfw/native/core/gl_env.cpp | 2 | ||||
| -rw-r--r-- | media/mca/filterfw/native/core/gl_env.h | 3 | ||||
| -rw-r--r-- | packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java | 2 | ||||
| -rw-r--r-- | services/java/com/android/server/accessibility/TouchExplorer.java | 783 | ||||
| -rw-r--r-- | services/java/com/android/server/pm/Settings.java | 19 | ||||
| -rw-r--r-- | tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java | 8 |
15 files changed, 386 insertions, 630 deletions
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index 97ea99ddb419..4d48fd46dd29 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 @@ public class FileUtils { /** 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); + } + + /** + * 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; + } - public static native int getUid(String file); + 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 ab0543d0b78e..cf9ddb3b258b 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -100,12 +100,6 @@ public class Process { 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 class Process { 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 ccc0089cb0c0..04351da6dff7 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -499,7 +499,7 @@ public class ZygoteInit { 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 330806463ecc..6c4526eccfdf 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 @@ public: 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 @@ static JNINativeMethod gCanvasMethods[] = { (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 2c482ea975d6..bacfdf6ae8d1 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 0aaa2b158da8..d1245da24777 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 @@ jint android_os_FileUtils_getFatVolumeId(JNIEnv* env, jobject clazz, jstring pat } 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 fdec22be9350..0ea4074c7eb0 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -114,9 +114,13 @@ public class Canvas { * 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 class Canvas { */ public void drawPicture(Picture picture) { picture.endRecording(); - native_drawPicture(mNativeCanvas, picture.ni()); + int restoreCount = save(); + picture.draw(this); + restoreToCount(restoreCount); } /** @@ -1831,7 +1837,5 @@ public class Canvas { 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 d1bae1e45838..707f662bec4f 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1112,8 +1112,6 @@ void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) { 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 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) { GL_UNSIGNED_SHORT, NULL)); } - finishDrawTexture(); - #if DEBUG_LAYERS_AS_REGIONS drawRegionRects(layer->region); #endif @@ -2021,9 +2017,6 @@ void OpenGLRenderer::setupDrawIndexedVertices(GLvoid* vertices) { mCaches.bindPositionVertexPointer(force, vertices, gVertexStride); } -void OpenGLRenderer::finishDrawTexture() { -} - /////////////////////////////////////////////////////////////////////////////// // Drawing /////////////////////////////////////////////////////////////////////////////// @@ -2308,8 +2301,6 @@ status_t OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int mes glDrawArrays(GL_TRIANGLES, 0, count); - finishDrawTexture(); - int slot = mCaches.currentProgram->getAttrib("colors"); if (slot >= 0) { glDisableVertexAttribArray(slot); @@ -3134,8 +3125,6 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y) { mesh += (drawCount / 6) * 4; } - finishDrawTexture(); - #if DEBUG_LAYERS_AS_REGIONS drawRegionRects(layer->region); #endif @@ -3270,8 +3259,6 @@ void OpenGLRenderer::drawPathTexture(const PathTexture* texture, setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset); glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); - - finishDrawTexture(); } // Same values used by Skia @@ -3488,8 +3475,6 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b setupDrawMesh(vertices, texCoords, vbo); glDrawArrays(drawMode, 0, elementsCount); - - finishDrawTexture(); } void OpenGLRenderer::drawIndexedTextureMesh(float left, float top, float right, float bottom, @@ -3515,8 +3500,6 @@ void OpenGLRenderer::drawIndexedTextureMesh(float left, float top, float right, 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 @@ void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, f 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 2f8a2f0d28a7..1c3bfdc23b06 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -1003,7 +1003,6 @@ private: 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 fdecda378220..84dad8ca70ee 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 81e1e9dcb7a2..a709638f1c34 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 8e7e087c487d..a536acbc3c8c 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java @@ -72,7 +72,7 @@ public class DocumentsActivity extends Activity { 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 18b46fbec4e6..8fb3998f4859 100644 --- a/services/java/com/android/server/accessibility/TouchExplorer.java +++ b/services/java/com/android/server/accessibility/TouchExplorer.java @@ -41,6 +41,7 @@ import com.android.internal.R; 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 @@ import java.util.Arrays; * <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 @@ class TouchExplorer implements EventStreamTransformation { // 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 @@ class TouchExplorer implements EventStreamTransformation { // 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 @@ class TouchExplorer implements EventStreamTransformation { 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 @@ class TouchExplorer implements EventStreamTransformation { 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 @@ class TouchExplorer implements EventStreamTransformation { } 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 @@ class TouchExplorer implements EventStreamTransformation { // 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 @@ class TouchExplorer implements EventStreamTransformation { // 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 @@ class TouchExplorer implements EventStreamTransformation { 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(); - - // 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; + // 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.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 @@ class TouchExplorer implements EventStreamTransformation { // 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 @@ class TouchExplorer implements EventStreamTransformation { } 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 @@ class TouchExplorer implements EventStreamTransformation { 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 @@ class TouchExplorer implements EventStreamTransformation { 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 @@ class TouchExplorer implements EventStreamTransformation { } 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 @@ class TouchExplorer implements EventStreamTransformation { // 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(); + mPerformLongPressDelayed.cancel(); + mVelocityTracker.clear(); - // 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 (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; + if (!mSendTouchInteractionEndDelayed.isPending()) { + mSendTouchInteractionEndDelayed.post(); } - mVelocityTracker.clear(); + } break; case MotionEvent.ACTION_CANCEL: { clear(event, policyFlags); @@ -676,29 +648,19 @@ class TouchExplorer implements EventStreamTransformation { 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 @@ class TouchExplorer implements EventStreamTransformation { // 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 @@ class TouchExplorer implements EventStreamTransformation { // 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 @@ class TouchExplorer implements EventStreamTransformation { 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 @@ class TouchExplorer implements EventStreamTransformation { } 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 @@ class TouchExplorer implements EventStreamTransformation { } mStrokeBuffer.clear(); - mExitGestureDetectionModeDelayed.remove(); + mExitGestureDetectionModeDelayed.cancel(); mCurrentState = STATE_TOUCH_EXPLORING; } break; case MotionEvent.ACTION_CANCEL: { @@ -889,40 +833,26 @@ class TouchExplorer implements EventStreamTransformation { } /** - * 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 @@ class TouchExplorer implements EventStreamTransformation { } /** - * 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 @@ class TouchExplorer implements EventStreamTransformation { } /** - * 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 @@ class TouchExplorer implements EventStreamTransformation { } // 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 @@ class TouchExplorer implements EventStreamTransformation { */ 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(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 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 @@ class TouchExplorer implements EventStreamTransformation { } /** - * @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 @@ class TouchExplorer implements EventStreamTransformation { mHandler.postDelayed(this, EXIT_GESTURE_DETECTION_TIMEOUT); } - public void remove() { + public void cancel() { mHandler.removeCallbacks(this); } @@ -1396,21 +1266,21 @@ class TouchExplorer implements EventStreamTransformation { 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 @@ class TouchExplorer implements EventStreamTransformation { 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 TouchExplorer implements EventStreamTransformation { } /** - * 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 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, + public void post(MotionEvent event, boolean touchExplorationInProgress, int pointerIdBits, int policyFlags) { - remove(); - mPrototype = MotionEvent.obtain(prototype); + cancel(); + addEvent(event); mPointerIdBits = pointerIdBits; mPolicyFlags = policyFlags; mHandler.postDelayed(this, mDetermineUserIntentTimeout); } - public float getX() { + public void addEvent(MotionEvent event) { + mEvents.add(MotionEvent.obtain(event)); + } + + public void cancel() { if (isPending()) { - return mPrototype.getX(); + 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(); } - return 0; } - public float getY() { + public void forceSendAndRemove() { if (isPending()) { - return mPrototype.getY(); + run(); + cancel(); } - return 0; } - public void remove() { - mHandler.removeCallbacks(this); + 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 void post(MotionEvent prototype, int pointerIdBits, int policyFlags) { + cancel(); + mPrototype = MotionEvent.obtain(prototype); + mPointerIdBits = pointerIdBits; + mPolicyFlags = policyFlags; + mHandler.postDelayed(this, mDetermineUserIntentTimeout); + } + + public void cancel() { + if (isPending()) { + 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 @@ class TouchExplorer implements EventStreamTransformation { 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(); + } + if (mSendTouchInteractionEndDelayed.isPending()) { + mSendTouchInteractionEndDelayed.cancel(); + mSendTouchInteractionEndDelayed.post(); } - sendMotionEvent(mPrototype, mHoverAction, mPointerIdBits, mPolicyFlags); clear(); } } @@ -1574,7 +1492,7 @@ class TouchExplorer implements EventStreamTransformation { mDelay = delay; } - public void remove() { + public void cancel() { mHandler.removeCallbacks(this); } @@ -1589,7 +1507,7 @@ class TouchExplorer implements EventStreamTransformation { public void forceSendAndRemove() { if (isPending()) { run(); - remove(); + cancel(); } } @@ -1736,15 +1654,6 @@ class TouchExplorer implements EventStreamTransformation { 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 @@ class TouchExplorer implements EventStreamTransformation { // 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 @@ class TouchExplorer implements EventStreamTransformation { 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 @@ class TouchExplorer implements EventStreamTransformation { 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 @@ class TouchExplorer implements EventStreamTransformation { } /** - * @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 @@ class TouchExplorer implements EventStreamTransformation { } /** - * 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 @@ class TouchExplorer implements EventStreamTransformation { /** * @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 @@ class TouchExplorer implements EventStreamTransformation { } /** - * @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 @@ class TouchExplorer implements EventStreamTransformation { } /** - * @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 @@ class TouchExplorer implements EventStreamTransformation { mLastReceivedUpPointerId = 0; mLastReceivedUpPointerDownTime = 0; - mLastReceivedUpPointerActive = false; mLastReceivedUpPointerDownX = 0; mLastReceivedUpPointerDownX = 0; @@ -2013,25 +1832,7 @@ class TouchExplorer implements EventStreamTransformation { 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 @@ class TouchExplorer implements EventStreamTransformation { 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; - } - } - - /** - * Detects the active pointers in an event. - * - * @param event The event to examine. - */ - 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; - } + if (mPrimaryPointerId == pointerId) { + mPrimaryPointerId = INVALID_POINTER_ID; } } /** - * @return The primary active pointer. + * @return The primary 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 @@ class TouchExplorer implements EventStreamTransformation { } } 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 163536ab49aa..e78362bae63b 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 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 @@ final class Settings { 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 @@ final class Settings { 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 @@ final class Settings { -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 @@ final class Settings { // 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 @@ final class Settings { 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 4171bb54b31c..361f5d7a8bef 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 @@ public final class Canvas_Delegate { } @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); |