Merge "Add concepts of related users and managed profiles to user manager."
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index ad38489..8acd19b 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -77,7 +77,7 @@
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
- mTextureView.layout(l, t, r, b);
+ mTextureView.layout(0, 0, r - l, b - t);
}
@Override
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index aa96f0e..de00f71 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1625,10 +1625,7 @@
String locale = null;
if (mConfiguration.locale != null) {
- locale = mConfiguration.locale.getLanguage();
- if (mConfiguration.locale.getCountry() != null) {
- locale += "-" + mConfiguration.locale.getCountry();
- }
+ locale = mConfiguration.locale.toLanguageTag();
}
int width, height;
if (mMetrics.widthPixels >= mMetrics.heightPixels) {
diff --git a/core/java/android/emoji/EmojiFactory.java b/core/java/android/emoji/EmojiFactory.java
index 8fd8695..aba990d 100644
--- a/core/java/android/emoji/EmojiFactory.java
+++ b/core/java/android/emoji/EmojiFactory.java
@@ -54,7 +54,7 @@
}
// A pointer to native EmojiFactory object.
- private int mNativeEmojiFactory;
+ private long mNativeEmojiFactory;
private String mName;
// Cache.
private Map<Integer, WeakReference<Bitmap>> mCache;
@@ -68,7 +68,7 @@
*
* This can be called from JNI code.
*/
- private EmojiFactory(int nativeEmojiFactory, String name) {
+ private EmojiFactory(long nativeEmojiFactory, String name) {
mNativeEmojiFactory = nativeEmojiFactory;
mName = name;
mCache = new CustomLinkedHashMap<Integer, WeakReference<Bitmap>>();
@@ -272,18 +272,18 @@
// native methods
- private native void nativeDestructor(int factory);
- private native Bitmap nativeGetBitmapFromAndroidPua(int nativeEmojiFactory, int AndroidPua);
- private native int nativeGetAndroidPuaFromVendorSpecificSjis(int nativeEmojiFactory,
+ private native void nativeDestructor(long nativeEmojiFactory);
+ private native Bitmap nativeGetBitmapFromAndroidPua(long nativeEmojiFactory, int AndroidPua);
+ private native int nativeGetAndroidPuaFromVendorSpecificSjis(long nativeEmojiFactory,
char sjis);
- private native int nativeGetVendorSpecificSjisFromAndroidPua(int nativeEmojiFactory,
+ private native int nativeGetVendorSpecificSjisFromAndroidPua(long nativeEmojiFactory,
int pua);
- private native int nativeGetAndroidPuaFromVendorSpecificPua(int nativeEmojiFactory,
+ private native int nativeGetAndroidPuaFromVendorSpecificPua(long nativeEmojiFactory,
int vsp);
- private native int nativeGetVendorSpecificPuaFromAndroidPua(int nativeEmojiFactory,
+ private native int nativeGetVendorSpecificPuaFromAndroidPua(long nativeEmojiFactory,
int pua);
- private native int nativeGetMaximumVendorSpecificPua(int nativeEmojiFactory);
- private native int nativeGetMinimumVendorSpecificPua(int nativeEmojiFactory);
- private native int nativeGetMaximumAndroidPua(int nativeEmojiFactory);
- private native int nativeGetMinimumAndroidPua(int nativeEmojiFactory);
+ private native int nativeGetMaximumVendorSpecificPua(long nativeEmojiFactory);
+ private native int nativeGetMinimumVendorSpecificPua(long nativeEmojiFactory);
+ private native int nativeGetMaximumAndroidPua(long nativeEmojiFactory);
+ private native int nativeGetMinimumAndroidPua(long nativeEmojiFactory);
}
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 3672de4..f06ffaa 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -167,7 +167,9 @@
/**
* <p>Maximum and minimum exposure compensation
* setting, in counts of
- * android.control.aeCompensationStepSize</p>
+ * {@link CameraCharacteristics#CONTROL_AE_COMPENSATION_STEP android.control.aeCompensationStep}.</p>
+ *
+ * @see CameraCharacteristics#CONTROL_AE_COMPENSATION_STEP
*/
public static final Key<int[]> CONTROL_AE_COMPENSATION_RANGE =
new Key<int[]>("android.control.aeCompensationRange", int[].class);
@@ -446,12 +448,16 @@
* <p>The maximum numbers of any type of input streams
* that can be configured and used simultaneously by a camera device.</p>
* <p>When set to 0, it means no input stream is supported.</p>
- * <p>The image format for a input stream can be any supported format provided
- * by android.scaler.availableInputFormats. When using an input stream, there must be
- * at least one output stream configured to to receive the reprocessed images.</p>
+ * <p>The image format for a input stream can be any supported
+ * format provided by
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP android.scaler.availableInputOutputFormatsMap}. When using an
+ * input stream, there must be at least one output stream
+ * configured to to receive the reprocessed images.</p>
* <p>For example, for Zero Shutter Lag (ZSL) still capture use case, the input
* stream image format will be RAW_OPAQUE, the associated output stream image format
* should be JPEG.</p>
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP
*/
public static final Key<Integer> REQUEST_MAX_NUM_INPUT_STREAMS =
new Key<Integer>("android.request.maxNumInputStreams", int.class);
@@ -505,7 +511,7 @@
* to do this query each of android.request.availableRequestKeys,
* android.request.availableResultKeys,
* android.request.availableCharacteristicsKeys.</p>
- * <p>XX: Maybe these should go into android.info.supportedHardwareLevel
+ * <p>XX: Maybe these should go into {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel}
* as a table instead?</p>
* <p>The following capabilities are guaranteed to be available on
* {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} <code>==</code> FULL devices:</p>
@@ -665,7 +671,7 @@
* <p>The mapping of image formats that are supported by this
* camera device for input streams, to their corresponding output formats.</p>
* <p>All camera devices with at least 1
- * android.request.request.maxNumInputStreams will have at least one
+ * {@link CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS android.request.maxNumInputStreams} will have at least one
* available input format.</p>
* <p>The camera device will support the following map of formats,
* if its dependent capability is supported:</p>
@@ -712,6 +718,7 @@
* listed as available in this map is not valid.</p>
* <p>TODO: Add java type mapping for this property.</p>
*
+ * @see CameraCharacteristics#REQUEST_MAX_NUM_INPUT_STREAMS
* @see CameraCharacteristics#SCALER_AVAILABLE_STALL_DURATIONS
*/
public static final Key<int[]> SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP =
@@ -885,11 +892,12 @@
* <li>IMPLEMENTATION_DEFINED</li>
* </ul>
* <p>All other formats may or may not have an allowed stall duration on
- * a per-capability basis; refer to android.request.availableCapabilities
+ * a per-capability basis; refer to {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
* for more details.</p>
* <p>See {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration} for more information about
* calculating the max frame rate (absent stalls).</p>
*
+ * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
* @see CaptureRequest#SENSOR_FRAME_DURATION
*/
public static final Key<long[]> SCALER_AVAILABLE_STALL_DURATIONS =
@@ -922,7 +930,7 @@
/**
* <p>Maximum possible frame duration (minimum frame
* rate).</p>
- * <p>The largest possible android.sensor.frameDuration
+ * <p>The largest possible {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration}
* that will be accepted by the camera device. Attempting to use
* frame durations beyond the maximum will result in the frame duration
* being clipped to the maximum. See that control
@@ -935,6 +943,7 @@
*
* @see CameraCharacteristics#SCALER_AVAILABLE_JPEG_MIN_DURATIONS
* @see CameraCharacteristics#SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS
+ * @see CaptureRequest#SENSOR_FRAME_DURATION
*/
public static final Key<Long> SENSOR_INFO_MAX_FRAME_DURATION =
new Key<Long>("android.sensor.info.maxFrameDuration", long.class);
@@ -952,7 +961,9 @@
* including black calibration pixels.</p>
* <p>Maximum output resolution for raw format must
* match this in
- * android.scaler.info.availableSizesPerFormat.</p>
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS android.scaler.availableStreamConfigurations}.</p>
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS
*/
public static final Key<android.hardware.camera2.Size> SENSOR_INFO_PIXEL_ARRAY_SIZE =
new Key<android.hardware.camera2.Size>("android.sensor.info.pixelArraySize", android.hardware.camera2.Size.class);
@@ -1026,8 +1037,10 @@
/**
* <p>Optional. Defaults to [OFF]. Lists the supported test
- * pattern modes for android.test.patternMode.</p>
+ * pattern modes for {@link CaptureRequest#SENSOR_TEST_PATTERN_MODE android.sensor.testPatternMode}.</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ *
+ * @see CaptureRequest#SENSOR_TEST_PATTERN_MODE
*/
public static final Key<Byte> SENSOR_AVAILABLE_TEST_PATTERN_MODES =
new Key<Byte>("android.sensor.availableTestPatternModes", byte.class);
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 1ce91f6..a581982 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -400,10 +400,12 @@
* formats.</li>
* <li>The maximum available resolution for RAW16 streams (both
* input/output) will match the value in
- * android.sensor.info.pixelArraySize.</li>
+ * {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}.</li>
* <li>All DNG-related optional metadata entries are provided
* by the camera device.</li>
* </ul>
+ *
+ * @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE
* @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
*/
public static final int REQUEST_AVAILABLE_CAPABILITIES_DNG = 5;
@@ -783,10 +785,11 @@
/**
* <p>The camera device's auto white balance routine is active;
- * the application's values for android.colorCorrection.transform
+ * the application's values for {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}
* and {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} are ignored.</p>
*
* @see CaptureRequest#COLOR_CORRECTION_GAINS
+ * @see CaptureRequest#COLOR_CORRECTION_TRANSFORM
* @see CaptureRequest#CONTROL_AWB_MODE
*/
public static final int CONTROL_AWB_MODE_AUTO = 1;
@@ -1031,10 +1034,11 @@
* this should still operate correctly (but will not return
* face detection statistics to the framework).</p>
* <p>Unlike the other scene modes, {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode},
- * {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, and android.control.afMode
+ * {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, and {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode}
* remain active when FACE_PRIORITY is set.</p>
*
* @see CaptureRequest#CONTROL_AE_MODE
+ * @see CaptureRequest#CONTROL_AF_MODE
* @see CaptureRequest#CONTROL_AWB_MODE
* @see CaptureRequest#STATISTICS_FACE_DETECT_MODE
* @see CaptureRequest#CONTROL_SCENE_MODE
@@ -1429,7 +1433,7 @@
/**
* <p>Use the tone mapping curve specified in
- * android.tonemap.curve.</p>
+ * the android.tonemap.curve* entries.</p>
* <p>All color enhancement and tonemapping must be disabled, except
* for applying the tonemapping curve specified by
* {@link CaptureRequest#TONEMAP_CURVE_RED android.tonemap.curveRed}, {@link CaptureRequest#TONEMAP_CURVE_BLUE android.tonemap.curveBlue}, or
@@ -1642,21 +1646,25 @@
//
/**
- * <p>The lens parameters ({@link CaptureRequest#LENS_FOCAL_LENGTH android.lens.focalLength}, android.lens.focusDistance
- * android.lens.filterDensity and {@link CaptureRequest#LENS_APERTURE android.lens.aperture}) are not changing.</p>
+ * <p>The lens parameters ({@link CaptureRequest#LENS_FOCAL_LENGTH android.lens.focalLength}, {@link CaptureRequest#LENS_FOCUS_DISTANCE android.lens.focusDistance},
+ * {@link CaptureRequest#LENS_FILTER_DENSITY android.lens.filterDensity} and {@link CaptureRequest#LENS_APERTURE android.lens.aperture}) are not changing.</p>
*
* @see CaptureRequest#LENS_APERTURE
+ * @see CaptureRequest#LENS_FILTER_DENSITY
* @see CaptureRequest#LENS_FOCAL_LENGTH
+ * @see CaptureRequest#LENS_FOCUS_DISTANCE
* @see CaptureResult#LENS_STATE
*/
public static final int LENS_STATE_STATIONARY = 0;
/**
- * <p>Any of the lens parameters ({@link CaptureRequest#LENS_FOCAL_LENGTH android.lens.focalLength}, android.lens.focusDistance
- * android.lens.filterDensity or {@link CaptureRequest#LENS_APERTURE android.lens.aperture}) is changing.</p>
+ * <p>Any of the lens parameters ({@link CaptureRequest#LENS_FOCAL_LENGTH android.lens.focalLength}, {@link CaptureRequest#LENS_FOCUS_DISTANCE android.lens.focusDistance},
+ * {@link CaptureRequest#LENS_FILTER_DENSITY android.lens.filterDensity} or {@link CaptureRequest#LENS_APERTURE android.lens.aperture}) is changing.</p>
*
* @see CaptureRequest#LENS_APERTURE
+ * @see CaptureRequest#LENS_FILTER_DENSITY
* @see CaptureRequest#LENS_FOCAL_LENGTH
+ * @see CaptureRequest#LENS_FOCUS_DISTANCE
* @see CaptureResult#LENS_STATE
*/
public static final int LENS_STATE_MOVING = 1;
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 326205e..408e532 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -472,7 +472,7 @@
* <p>If AE precapture is triggered (see {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger})
* when AE is already locked, the camera device will not change the exposure time
* ({@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}) and sensitivity ({@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity})
- * parameters. The flash may be fired if the android.control.aeMode
+ * parameters. The flash may be fired if the {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode}
* is ON_AUTO_FLASH/ON_AUTO_FLASH_REDEYE and the scene is too dark. If the
* {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is ON_ALWAYS_FLASH, the scene may become overexposed.</p>
* <p>See {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} for AE lock related state transition details.</p>
@@ -581,9 +581,10 @@
* mode it is set to</p>
* <p>Only effective if {@link CaptureRequest#CONTROL_MODE android.control.mode} = AUTO.</p>
* <p>If the lens is controlled by the camera device auto-focus algorithm,
- * the camera device will report the current AF status in android.control.afState
+ * the camera device will report the current AF status in {@link CaptureResult#CONTROL_AF_STATE android.control.afState}
* in result metadata.</p>
*
+ * @see CaptureResult#CONTROL_AF_STATE
* @see CaptureRequest#CONTROL_MODE
* @see #CONTROL_AF_MODE_OFF
* @see #CONTROL_AF_MODE_AUTO
@@ -658,7 +659,7 @@
* {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode}.</p>
* <p>When set to the OFF mode, the camera device's auto white balance
* routine is disabled. The applicantion manually controls the white
- * balance by {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}, android.colorCorrection.gains
+ * balance by {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}, {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains}
* and {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode}.</p>
* <p>When set to any other modes, the camera device's auto white balance
* routine is disabled. The camera device uses each particular illumination
@@ -944,7 +945,7 @@
* one of the values listed in {@link CameraCharacteristics#LENS_INFO_AVAILABLE_APERTURES android.lens.info.availableApertures}.</p>
* <p>When this is supported and {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is OFF,
* this can be set along with {@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime},
- * {@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity}, and android.sensor.frameDuration
+ * {@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity}, and {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration}
* to achieve manual exposure control.</p>
* <p>The requested aperture value may take several frames to reach the
* requested value; the camera device will report the current (intermediate)
@@ -959,6 +960,7 @@
* @see CameraCharacteristics#LENS_INFO_AVAILABLE_APERTURES
* @see CaptureResult#LENS_STATE
* @see CaptureRequest#SENSOR_EXPOSURE_TIME
+ * @see CaptureRequest#SENSOR_FRAME_DURATION
* @see CaptureRequest#SENSOR_SENSITIVITY
*/
public static final Key<Float> LENS_APERTURE =
@@ -1091,9 +1093,11 @@
* for raw output, where only a few fixed scales may be
* possible. The width and height of the crop region cannot
* be set to be smaller than floor( activeArraySize.width /
- * android.scaler.maxDigitalZoom ) and floor(
- * activeArraySize.height / android.scaler.maxDigitalZoom),
- * respectively.</p>
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} ) and floor(
+ * activeArraySize.height /
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom}), respectively.</p>
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM
*/
public static final Key<android.graphics.Rect> SCALER_CROP_REGION =
new Key<android.graphics.Rect>("android.scaler.cropRegion", android.graphics.Rect.class);
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index f556d71..345b52c 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -391,9 +391,10 @@
* mode it is set to</p>
* <p>Only effective if {@link CaptureRequest#CONTROL_MODE android.control.mode} = AUTO.</p>
* <p>If the lens is controlled by the camera device auto-focus algorithm,
- * the camera device will report the current AF status in android.control.afState
+ * the camera device will report the current AF status in {@link CaptureResult#CONTROL_AF_STATE android.control.afState}
* in result metadata.</p>
*
+ * @see CaptureResult#CONTROL_AF_STATE
* @see CaptureRequest#CONTROL_MODE
* @see #CONTROL_AF_MODE_OFF
* @see #CONTROL_AF_MODE_AUTO
@@ -771,7 +772,7 @@
* {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode}.</p>
* <p>When set to the OFF mode, the camera device's auto white balance
* routine is disabled. The applicantion manually controls the white
- * balance by {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}, android.colorCorrection.gains
+ * balance by {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}, {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains}
* and {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode}.</p>
* <p>When set to any other modes, the camera device's auto white balance
* routine is disabled. The camera device uses each particular illumination
@@ -1019,8 +1020,9 @@
* of the pixel array, and the width,height of the pixel array given in
* {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}. This may include hot pixels
* that lie outside of the active array bounds given by
- * android.sensor.activeArraySize.</p>
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p>
*
+ * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
* @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE
*/
public static final Key<int[]> HOT_PIXEL_MAP =
@@ -1099,7 +1101,7 @@
* one of the values listed in {@link CameraCharacteristics#LENS_INFO_AVAILABLE_APERTURES android.lens.info.availableApertures}.</p>
* <p>When this is supported and {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is OFF,
* this can be set along with {@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime},
- * {@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity}, and android.sensor.frameDuration
+ * {@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity}, and {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration}
* to achieve manual exposure control.</p>
* <p>The requested aperture value may take several frames to reach the
* requested value; the camera device will report the current (intermediate)
@@ -1114,6 +1116,7 @@
* @see CameraCharacteristics#LENS_INFO_AVAILABLE_APERTURES
* @see CaptureResult#LENS_STATE
* @see CaptureRequest#SENSOR_EXPOSURE_TIME
+ * @see CaptureRequest#SENSOR_FRAME_DURATION
* @see CaptureRequest#SENSOR_SENSITIVITY
*/
public static final Key<Float> LENS_APERTURE =
@@ -1325,9 +1328,11 @@
* for raw output, where only a few fixed scales may be
* possible. The width and height of the crop region cannot
* be set to be smaller than floor( activeArraySize.width /
- * android.scaler.maxDigitalZoom ) and floor(
- * activeArraySize.height / android.scaler.maxDigitalZoom),
- * respectively.</p>
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom} ) and floor(
+ * activeArraySize.height /
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM android.scaler.availableMaxDigitalZoom}), respectively.</p>
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_MAX_DIGITAL_ZOOM
*/
public static final Key<android.graphics.Rect> SCALER_CROP_REGION =
new Key<android.graphics.Rect>("android.scaler.cropRegion", android.graphics.Rect.class);
@@ -1738,7 +1743,7 @@
* (<code>{@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} == OFF</code> or <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} == OFF</code>),
* the {@link CaptureRequest#CONTROL_AE_ANTIBANDING_MODE android.control.aeAntibandingMode} doesn't do the antibanding, and the
* application can ensure it selects exposure times that do not cause banding
- * issues by looking into this metadata field. See android.control.aeAntibandingMode
+ * issues by looking into this metadata field. See {@link CaptureRequest#CONTROL_AE_ANTIBANDING_MODE android.control.aeAntibandingMode}
* for more details.</p>
* <p>Report NONE if there doesn't appear to be flickering illumination.</p>
*
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index a96d46c..9aecbea 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -468,6 +468,29 @@
}
/**
+ * Set whether the DisplayList should cast a shadow.
+ *
+ * The shape of the shadow casting area is defined by the outline of the display list, if set
+ * and non-empty, otherwise it will be the bounds rect.
+ */
+ public void setCastsShadow(boolean castsShadow) {
+ if (hasNativeDisplayList()) {
+ nSetCastsShadow(mFinalizer.mNativeDisplayList, castsShadow);
+ }
+ }
+
+ /**
+ * Sets whether the DisplayList should be drawn with perspective applied from the global camera.
+ *
+ * If set to true, camera distance will be ignored. Defaults to false.
+ */
+ public void setSharesGlobalCamera(boolean sharesGlobalCamera) {
+ if (hasNativeDisplayList()) {
+ nSetSharesGlobalCamera(mFinalizer.mNativeDisplayList, sharesGlobalCamera);
+ }
+ }
+
+ /**
* Set the static matrix on the display list. The specified matrix is combined with other
* transforms (such as {@link #setScaleX(float)}, {@link #setRotation(float)}, etc.)
*
@@ -1092,6 +1115,8 @@
private static native void nSetIsolatedZVolume(long displayList, boolean isolateZVolume);
private static native void nSetOutline(long displayList, long nativePath);
private static native void nSetClipToOutline(long displayList, boolean clipToOutline);
+ private static native void nSetCastsShadow(long displayList, boolean castsShadow);
+ private static native void nSetSharesGlobalCamera(long displayList, boolean sharesGlobalCamera);
private static native void nSetAlpha(long displayList, float alpha);
private static native void nSetHasOverlappingRendering(long displayList,
boolean hasOverlappingRendering);
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index dc68e51..2ed0cba 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -31,7 +31,6 @@
import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.Shader;
-import android.graphics.SurfaceTexture;
import android.graphics.TemporaryBuffer;
import android.text.GraphicsOperations;
import android.text.SpannableString;
@@ -46,7 +45,6 @@
private static final int MODIFIER_NONE = 0;
private static final int MODIFIER_SHADOW = 1;
private static final int MODIFIER_SHADER = 2;
- private static final int MODIFIER_COLOR_FILTER = 4;
private final boolean mOpaque;
private long mRenderer;
@@ -88,15 +86,6 @@
GLES20Canvas(boolean translucent) {
this(false, translucent);
}
-
- /**
- * Creates a canvas to render into an FBO.
- */
- GLES20Canvas(long layer, boolean translucent) {
- mOpaque = !translucent;
- mRenderer = nCreateLayerRenderer(layer);
- setupFinalizer();
- }
protected GLES20Canvas(boolean record, boolean translucent) {
mOpaque = !translucent;
@@ -123,7 +112,6 @@
}
private static native long nCreateRenderer();
- private static native long nCreateLayerRenderer(long layer);
private static native long nCreateDisplayListRenderer();
private static native void nResetDisplayListRenderer(long renderer);
private static native void nDestroyRenderer(long renderer);
@@ -157,12 +145,12 @@
@Override
void pushLayerUpdate(HardwareLayer layer) {
- nPushLayerUpdate(mRenderer, ((GLES20RenderLayer) layer).mLayer);
+ nPushLayerUpdate(mRenderer, layer.getLayer());
}
@Override
void cancelLayerUpdate(HardwareLayer layer) {
- nCancelLayerUpdate(mRenderer, ((GLES20RenderLayer) layer).mLayer);
+ nCancelLayerUpdate(mRenderer, layer.getLayer());
}
@Override
@@ -175,22 +163,7 @@
nClearLayerUpdates(mRenderer);
}
- static native long nCreateTextureLayer(boolean opaque, int[] layerInfo);
- static native long nCreateLayer(int width, int height, boolean isOpaque, int[] layerInfo);
- static native boolean nResizeLayer(long layerId, int width, int height, int[] layerInfo);
- static native void nSetOpaqueLayer(long layerId, boolean isOpaque);
- static native void nSetLayerPaint(long layerId, long nativePaint);
- static native void nSetLayerColorFilter(long layerId, long nativeColorFilter);
- static native void nUpdateTextureLayer(long layerId, int width, int height, boolean opaque,
- SurfaceTexture surface);
- static native void nClearLayerTexture(long layerId);
- static native void nSetTextureLayerTransform(long layerId, long matrix);
- static native void nDestroyLayer(long layerId);
- static native void nDestroyLayerDeferred(long layerId);
- static native void nUpdateRenderLayer(long layerId, long renderer, long displayList,
- int left, int top, int right, int bottom);
static native boolean nCopyLayer(long layerId, long bitmap);
-
private static native void nClearLayerUpdates(long renderer);
private static native void nFlushLayerUpdates(long renderer);
private static native void nPushLayerUpdate(long renderer, long layer);
@@ -409,9 +382,7 @@
void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) {
layer.setLayerPaint(paint);
-
- final GLES20Layer glLayer = (GLES20Layer) layer;
- nDrawLayer(mRenderer, glLayer.getLayer(), x, y);
+ nDrawLayer(mRenderer, layer.getLayer(), x, y);
}
private static native void nDrawLayer(long renderer, long layer, float x, float y);
@@ -627,15 +598,8 @@
return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
}
- int count;
- int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
- try {
- final long nativePaint = paint == null ? 0 : paint.mNativePaint;
- count = nSaveLayer(mRenderer, nativePaint, saveFlags);
- } finally {
- if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
- }
- return count;
+ final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+ return nSaveLayer(mRenderer, nativePaint, saveFlags);
}
private static native int nSaveLayer(long renderer, long paint, int saveFlags);
@@ -644,15 +608,8 @@
public int saveLayer(float left, float top, float right, float bottom, Paint paint,
int saveFlags) {
if (left < right && top < bottom) {
- int count;
- int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
- try {
- final long nativePaint = paint == null ? 0 : paint.mNativePaint;
- count = nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
- } finally {
- if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
- }
- return count;
+ final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+ return nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
}
return save(saveFlags);
}
@@ -734,7 +691,7 @@
@Override
public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,
Paint paint) {
- int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
+ int modifiers = setupModifiers(paint, MODIFIER_SHADER);
try {
nDrawArc(mRenderer, oval.left, oval.top, oval.right, oval.bottom,
startAngle, sweepAngle, useCenter, paint.mNativePaint);
@@ -757,14 +714,9 @@
Bitmap bitmap = patch.getBitmap();
throwIfCannotDraw(bitmap);
// Shaders are ignored when drawing patches
- int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
- try {
- final long nativePaint = paint == null ? 0 : paint.mNativePaint;
- nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk,
- dst.left, dst.top, dst.right, dst.bottom, nativePaint);
- } finally {
- if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
- }
+ final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+ nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint);
}
@Override
@@ -772,14 +724,9 @@
Bitmap bitmap = patch.getBitmap();
throwIfCannotDraw(bitmap);
// Shaders are ignored when drawing patches
- int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
- try {
- final long nativePaint = paint == null ? 0 : paint.mNativePaint;
- nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk,
- dst.left, dst.top, dst.right, dst.bottom, nativePaint);
- } finally {
- if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
- }
+ final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+ nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint);
}
private static native void nDrawPatch(long renderer, long bitmap, byte[] buffer, long chunk,
@@ -900,14 +847,9 @@
}
// Shaders are ignored when drawing bitmaps
- int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
- try {
- final long nativePaint = paint == null ? 0 : paint.mNativePaint;
- nDrawBitmap(mRenderer, colors, offset, stride, x, y,
- width, height, hasAlpha, nativePaint);
- } finally {
- if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
- }
+ final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+ nDrawBitmap(mRenderer, colors, offset, stride, x, y,
+ width, height, hasAlpha, nativePaint);
}
private static native void nDrawBitmap(long renderer, int[] colors, int offset, int stride,
@@ -955,7 +897,7 @@
@Override
public void drawCircle(float cx, float cy, float radius, Paint paint) {
- int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
+ int modifiers = setupModifiers(paint, MODIFIER_SHADER);
try {
nDrawCircle(mRenderer, cx, cy, radius, paint.mNativePaint);
} finally {
@@ -995,7 +937,7 @@
if ((offset | count) < 0 || offset + count > pts.length) {
throw new IllegalArgumentException("The lines array must contain 4 elements per line.");
}
- int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
+ int modifiers = setupModifiers(paint, MODIFIER_SHADER);
try {
nDrawLines(mRenderer, pts, offset, count, paint.mNativePaint);
} finally {
@@ -1013,7 +955,7 @@
@Override
public void drawOval(RectF oval, Paint paint) {
- int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
+ int modifiers = setupModifiers(paint, MODIFIER_SHADER);
try {
nDrawOval(mRenderer, oval.left, oval.top, oval.right, oval.bottom, paint.mNativePaint);
} finally {
@@ -1033,7 +975,7 @@
@Override
public void drawPath(Path path, Paint paint) {
- int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
+ int modifiers = setupModifiers(paint, MODIFIER_SHADER);
try {
if (path.isSimplePath) {
if (path.rects != null) {
@@ -1051,7 +993,7 @@
private static native void nDrawRects(long renderer, long region, long paint);
void drawRects(float[] rects, int count, Paint paint) {
- int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
+ int modifiers = setupModifiers(paint, MODIFIER_SHADER);
try {
nDrawRects(mRenderer, rects, count, paint.mNativePaint);
} finally {
@@ -1118,7 +1060,7 @@
public void drawPoints(float[] pts, int offset, int count, Paint paint) {
if (count < 2) return;
- int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
+ int modifiers = setupModifiers(paint, MODIFIER_SHADER);
try {
nDrawPoints(mRenderer, pts, offset, count, paint.mNativePaint);
} finally {
@@ -1168,7 +1110,7 @@
@Override
public void drawRect(float left, float top, float right, float bottom, Paint paint) {
if (left == right || top == bottom) return;
- int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
+ int modifiers = setupModifiers(paint, MODIFIER_SHADER);
try {
nDrawRect(mRenderer, left, top, right, bottom, paint.mNativePaint);
} finally {
@@ -1196,7 +1138,7 @@
@Override
public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) {
- int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
+ int modifiers = setupModifiers(paint, MODIFIER_SHADER);
try {
nDrawRoundRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
rx, ry, paint.mNativePaint);
@@ -1376,12 +1318,6 @@
private int setupModifiers(Bitmap b, Paint paint) {
if (b.getConfig() != Bitmap.Config.ALPHA_8) {
- final ColorFilter filter = paint.getColorFilter();
- if (filter != null) {
- nSetupColorFilter(mRenderer, filter.nativeColorFilter);
- return MODIFIER_COLOR_FILTER;
- }
-
return MODIFIER_NONE;
} else {
return setupModifiers(paint);
@@ -1403,12 +1339,6 @@
modifiers |= MODIFIER_SHADER;
}
- final ColorFilter filter = paint.getColorFilter();
- if (filter != null) {
- nSetupColorFilter(mRenderer, filter.nativeColorFilter);
- modifiers |= MODIFIER_COLOR_FILTER;
- }
-
return modifiers;
}
@@ -1427,26 +1357,10 @@
modifiers |= MODIFIER_SHADER;
}
- final ColorFilter filter = paint.getColorFilter();
- if (filter != null && (flags & MODIFIER_COLOR_FILTER) != 0) {
- nSetupColorFilter(mRenderer, filter.nativeColorFilter);
- modifiers |= MODIFIER_COLOR_FILTER;
- }
-
return modifiers;
}
- private int setupColorFilter(Paint paint) {
- final ColorFilter filter = paint.getColorFilter();
- if (filter != null) {
- nSetupColorFilter(mRenderer, filter.nativeColorFilter);
- return MODIFIER_COLOR_FILTER;
- }
- return MODIFIER_NONE;
- }
-
private static native void nSetupShader(long renderer, long shader);
- private static native void nSetupColorFilter(long renderer, long colorFilter);
private static native void nSetupShadow(long renderer, float radius,
float dx, float dy, int color);
diff --git a/core/java/android/view/GLES20Layer.java b/core/java/android/view/GLES20Layer.java
deleted file mode 100644
index 37154eb..0000000
--- a/core/java/android/view/GLES20Layer.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package android.view;
-
-import android.graphics.Bitmap;
-import android.graphics.Paint;
-
-/**
- * An OpenGL ES 2.0 implementation of {@link HardwareLayer}.
- */
-abstract class GLES20Layer extends HardwareLayer {
- long mLayer;
- Finalizer mFinalizer;
-
- GLES20Layer() {
- }
-
- GLES20Layer(int width, int height, boolean opaque) {
- super(width, height, opaque);
- }
-
- /**
- * Returns the native layer object used to render this layer.
- *
- * @return A pointer to the native layer object, or 0 if the object is NULL
- */
- public long getLayer() {
- return mLayer;
- }
-
- @Override
- void setLayerPaint(Paint paint) {
- if (paint != null) {
- GLES20Canvas.nSetLayerPaint(mLayer, paint.mNativePaint);
- GLES20Canvas.nSetLayerColorFilter(mLayer, paint.getColorFilter() != null ?
- paint.getColorFilter().nativeColorFilter : 0);
- }
- }
-
- @Override
- public boolean copyInto(Bitmap bitmap) {
- return GLES20Canvas.nCopyLayer(mLayer, bitmap.mNativeBitmap);
- }
-
- @Override
- public void destroy() {
- if (mDisplayList != null) {
- mDisplayList.reset();
- }
- if (mFinalizer != null) {
- mFinalizer.destroy();
- mFinalizer = null;
- }
- mLayer = 0;
- }
-
- @Override
- void clearStorage() {
- if (mLayer != 0) GLES20Canvas.nClearLayerTexture(mLayer);
- }
-
- static class Finalizer {
- private long mLayerId;
-
- public Finalizer(long layerId) {
- mLayerId = layerId;
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- if (mLayerId != 0) {
- GLES20Canvas.nDestroyLayerDeferred(mLayerId);
- }
- } finally {
- super.finalize();
- }
- }
-
- void destroy() {
- GLES20Canvas.nDestroyLayer(mLayerId);
- mLayerId = 0;
- }
- }
-}
diff --git a/core/java/android/view/GLES20RenderLayer.java b/core/java/android/view/GLES20RenderLayer.java
deleted file mode 100644
index 8c97867..0000000
--- a/core/java/android/view/GLES20RenderLayer.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Rect;
-
-/**
- * An OpenGL ES 2.0 implementation of {@link HardwareLayer}. This
- * implementation can be used a rendering target. It generates a
- * {@link Canvas} that can be used to render into an FBO using OpenGL.
- */
-class GLES20RenderLayer extends GLES20Layer {
- private int mLayerWidth;
- private int mLayerHeight;
-
- private final GLES20Canvas mCanvas;
-
- GLES20RenderLayer(int width, int height, boolean isOpaque) {
- super(width, height, isOpaque);
-
- int[] layerInfo = new int[2];
- mLayer = GLES20Canvas.nCreateLayer(width, height, isOpaque, layerInfo);
- if (mLayer != 0) {
- mLayerWidth = layerInfo[0];
- mLayerHeight = layerInfo[1];
-
- mCanvas = new GLES20Canvas(mLayer, !isOpaque);
- mFinalizer = new Finalizer(mLayer);
- } else {
- mCanvas = null;
- mFinalizer = null;
- }
- }
-
- @Override
- boolean isValid() {
- return mLayer != 0 && mLayerWidth > 0 && mLayerHeight > 0;
- }
-
- @Override
- boolean resize(int width, int height) {
- if (!isValid() || width <= 0 || height <= 0) return false;
-
- mWidth = width;
- mHeight = height;
-
- if (width != mLayerWidth || height != mLayerHeight) {
- int[] layerInfo = new int[2];
-
- if (GLES20Canvas.nResizeLayer(mLayer, width, height, layerInfo)) {
- mLayerWidth = layerInfo[0];
- mLayerHeight = layerInfo[1];
- } else {
- // Failure: not enough GPU resources for requested size
- mLayer = 0;
- mLayerWidth = 0;
- mLayerHeight = 0;
- }
- }
- return isValid();
- }
-
- @Override
- void setOpaque(boolean isOpaque) {
- mOpaque = isOpaque;
- GLES20Canvas.nSetOpaqueLayer(mLayer, isOpaque);
- }
-
- @Override
- HardwareCanvas getCanvas() {
- return mCanvas;
- }
-
- @Override
- void end(Canvas currentCanvas) {
- HardwareCanvas canvas = getCanvas();
- if (canvas != null) {
- canvas.onPostDraw();
- }
- if (currentCanvas instanceof GLES20Canvas) {
- ((GLES20Canvas) currentCanvas).resume();
- }
- }
-
- @Override
- HardwareCanvas start(Canvas currentCanvas) {
- return start(currentCanvas, null);
- }
-
- @Override
- HardwareCanvas start(Canvas currentCanvas, Rect dirty) {
- if (currentCanvas instanceof GLES20Canvas) {
- ((GLES20Canvas) currentCanvas).interrupt();
- }
- HardwareCanvas canvas = getCanvas();
- canvas.setViewport(mWidth, mHeight);
- canvas.onPreDraw(dirty);
- return canvas;
- }
-
- /**
- * Ignored
- */
- @Override
- void setTransform(Matrix matrix) {
- }
-
- @Override
- void redrawLater(DisplayList displayList, Rect dirtyRect) {
- GLES20Canvas.nUpdateRenderLayer(mLayer, mCanvas.getRenderer(),
- displayList.getNativeDisplayList(),
- dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom);
- }
-}
diff --git a/core/java/android/view/GLES20TextureLayer.java b/core/java/android/view/GLES20TextureLayer.java
deleted file mode 100644
index bb5a6eb..0000000
--- a/core/java/android/view/GLES20TextureLayer.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Rect;
-import android.graphics.SurfaceTexture;
-
-/**
- * An OpenGL ES 2.0 implementation of {@link HardwareLayer}. This
- * implementation can be used as a texture. Rendering into this
- * layer is not controlled by a {@link HardwareCanvas}.
- */
-class GLES20TextureLayer extends GLES20Layer {
- private int mTexture;
- private SurfaceTexture mSurface;
-
- GLES20TextureLayer(boolean isOpaque) {
- int[] layerInfo = new int[2];
- mLayer = GLES20Canvas.nCreateTextureLayer(isOpaque, layerInfo);
-
- if (mLayer != 0) {
- mTexture = layerInfo[0];
- mFinalizer = new Finalizer(mLayer);
- } else {
- mFinalizer = null;
- }
- }
-
- @Override
- boolean isValid() {
- return mLayer != 0 && mTexture != 0;
- }
-
- @Override
- boolean resize(int width, int height) {
- return isValid();
- }
-
- @Override
- HardwareCanvas getCanvas() {
- return null;
- }
-
- @Override
- HardwareCanvas start(Canvas currentCanvas) {
- return null;
- }
-
- @Override
- HardwareCanvas start(Canvas currentCanvas, Rect dirty) {
- return null;
- }
-
- @Override
- void end(Canvas currentCanvas) {
- }
-
- SurfaceTexture getSurfaceTexture() {
- if (mSurface == null) {
- mSurface = new SurfaceTexture(mTexture);
- }
- return mSurface;
- }
-
- void setSurfaceTexture(SurfaceTexture surfaceTexture) {
- if (mSurface != null) {
- mSurface.release();
- }
- mSurface = surfaceTexture;
- mSurface.attachToGLContext(mTexture);
- }
-
- @Override
- void update(int width, int height, boolean isOpaque) {
- super.update(width, height, isOpaque);
- GLES20Canvas.nUpdateTextureLayer(mLayer, width, height, isOpaque, mSurface);
- }
-
- @Override
- void setOpaque(boolean isOpaque) {
- throw new UnsupportedOperationException("Use update(int, int, boolean) instead");
- }
-
- @Override
- void setTransform(Matrix matrix) {
- GLES20Canvas.nSetTextureLayerTransform(mLayer, matrix.native_instance);
- }
-
- @Override
- void redrawLater(DisplayList displayList, Rect dirtyRect) {
- }
-}
diff --git a/core/java/android/view/GLRenderer.java b/core/java/android/view/GLRenderer.java
index 5002fe5..40ad72c 100644
--- a/core/java/android/view/GLRenderer.java
+++ b/core/java/android/view/GLRenderer.java
@@ -40,7 +40,7 @@
import static javax.microedition.khronos.egl.EGL10.EGL_WINDOW_BIT;
import android.content.ComponentCallbacks2;
-import android.graphics.Color;
+import android.graphics.Bitmap;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
@@ -62,6 +62,8 @@
import com.google.android.gles_jni.EGLImpl;
import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import javax.microedition.khronos.egl.EGL10;
@@ -177,6 +179,8 @@
private static EGLSurface sPbuffer;
private static final Object[] sPbufferLock = new Object[0];
+ private List<HardwareLayer> mAttachedLayers = new ArrayList<HardwareLayer>();
+
private static class GLRendererEglContext extends ManagedEGLContext {
final Handler mHandler = new Handler();
@@ -472,33 +476,40 @@
}
@Override
- void cancelLayerUpdate(HardwareLayer layer) {
- mGlCanvas.cancelLayerUpdate(layer);
- }
-
- @Override
void flushLayerUpdates() {
mGlCanvas.flushLayerUpdates();
}
@Override
- HardwareLayer createHardwareLayer(boolean isOpaque) {
- return new GLES20TextureLayer(isOpaque);
+ HardwareLayer createTextureLayer() {
+ return HardwareLayer.createTextureLayer(this);
}
@Override
- public HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque) {
- return new GLES20RenderLayer(width, height, isOpaque);
+ public HardwareLayer createDisplayListLayer(int width, int height) {
+ return HardwareLayer.createRenderLayer(this, width, height);
+ }
+
+ @Override
+ void onLayerCreated(HardwareLayer hardwareLayer) {
+ mAttachedLayers.add(hardwareLayer);
+ }
+
+ @Override
+ void onLayerDestroyed(HardwareLayer layer) {
+ mGlCanvas.cancelLayerUpdate(layer);
+ mAttachedLayers.remove(layer);
}
@Override
public SurfaceTexture createSurfaceTexture(HardwareLayer layer) {
- return ((GLES20TextureLayer) layer).getSurfaceTexture();
+ return layer.createSurfaceTexture();
}
@Override
- void setSurfaceTexture(HardwareLayer layer, SurfaceTexture surfaceTexture) {
- ((GLES20TextureLayer) layer).setSurfaceTexture(surfaceTexture);
+ boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap) {
+ layer.flushChanges();
+ return GLES20Canvas.nCopyLayer(layer.getLayer(), bitmap.mNativeBitmap);
}
@Override
@@ -1127,6 +1138,8 @@
DisplayList displayList = buildDisplayList(view, canvas);
+ flushLayerChanges();
+
// buildDisplayList() calls into user code which can cause
// an eglMakeCurrent to happen with a different surface/context.
// We must therefore check again here.
@@ -1180,6 +1193,20 @@
}
}
+ private void flushLayerChanges() {
+ // Loop through and apply any pending layer changes
+ for (int i = 0; i < mAttachedLayers.size(); i++) {
+ HardwareLayer layer = mAttachedLayers.get(i);
+ layer.flushChanges();
+ if (!layer.isValid()) {
+ // The layer was removed from mAttachedLayers, rewind i by 1
+ // Note that this shouldn't actually happen as View.getHardwareLayer()
+ // is already flushing for error checking reasons
+ i--;
+ }
+ }
+ }
+
private DisplayList buildDisplayList(View view, HardwareCanvas canvas) {
if (mDrawDelta <= 0) {
return view.mDisplayList;
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index 23383d9..9bbcf7c 100644
--- a/core/java/android/view/HardwareLayer.java
+++ b/core/java/android/view/HardwareLayer.java
@@ -17,10 +17,10 @@
package android.view;
import android.graphics.Bitmap;
-import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
+import android.graphics.SurfaceTexture;
/**
* A hardware layer can be used to render graphics operations into a hardware
@@ -28,38 +28,35 @@
* would use a Frame Buffer Object (FBO.) The hardware layer can be used as
* a drawing cache when a complex set of graphics operations needs to be
* drawn several times.
+ *
+ * @hide
*/
-abstract class HardwareLayer {
- /**
- * Indicates an unknown dimension (width or height.)
- */
- static final int DIMENSION_UNDEFINED = -1;
-
- int mWidth;
- int mHeight;
- DisplayList mDisplayList;
+final class HardwareLayer {
+ private static final int LAYER_TYPE_TEXTURE = 1;
+ private static final int LAYER_TYPE_RENDER = 2;
- boolean mOpaque;
+ private HardwareRenderer mRenderer;
+ private Finalizer mFinalizer;
+ private DisplayList mDisplayList;
+ private final int mLayerType;
- /**
- * Creates a new hardware layer with undefined dimensions.
- */
- HardwareLayer() {
- this(DIMENSION_UNDEFINED, DIMENSION_UNDEFINED, false);
+ private HardwareLayer(HardwareRenderer renderer, long deferredUpdater, int type) {
+ if (renderer == null || deferredUpdater == 0) {
+ throw new IllegalArgumentException("Either hardware renderer: " + renderer
+ + " or deferredUpdater: " + deferredUpdater + " is invalid");
+ }
+ mRenderer = renderer;
+ mLayerType = type;
+ mFinalizer = new Finalizer(deferredUpdater);
+
+ // Layer is considered initialized at this point, notify the HardwareRenderer
+ mRenderer.onLayerCreated(this);
}
- /**
- * Creates a new hardware layer at least as large as the supplied
- * dimensions.
- *
- * @param width The minimum width of the layer
- * @param height The minimum height of the layer
- * @param isOpaque Whether the layer should be opaque or not
- */
- HardwareLayer(int width, int height, boolean isOpaque) {
- mWidth = width;
- mHeight = height;
- mOpaque = isOpaque;
+ private void assertType(int type) {
+ if (mLayerType != type) {
+ throw new IllegalAccessError("Method not appropriate for this layer type! " + mLayerType);
+ }
}
/**
@@ -68,158 +65,225 @@
* @param paint The paint used when the layer is drawn into the destination canvas.
* @see View#setLayerPaint(android.graphics.Paint)
*/
- void setLayerPaint(Paint paint) { }
-
- /**
- * Returns the minimum width of the layer.
- *
- * @return The minimum desired width of the hardware layer
- */
- int getWidth() {
- return mWidth;
+ public void setLayerPaint(Paint paint) {
+ nSetLayerPaint(mFinalizer.mDeferredUpdater, paint.mNativePaint,
+ paint.getColorFilter() != null ? paint.getColorFilter().native_instance : 0);
}
/**
- * Returns the minimum height of the layer.
- *
- * @return The minimum desired height of the hardware layer
- */
- int getHeight() {
- return mHeight;
- }
-
- /**
- * Returns the DisplayList for the layer.
- *
- * @return The DisplayList of the hardware layer
- */
- DisplayList getDisplayList() {
- return mDisplayList;
- }
-
- /**
- * Sets the DisplayList for the layer.
- *
- * @param displayList The new DisplayList for this layer
- */
- void setDisplayList(DisplayList displayList) {
- mDisplayList = displayList;
- }
-
- /**
- * Returns whether or not this layer is opaque.
- *
- * @return True if the layer is opaque, false otherwise
- */
- boolean isOpaque() {
- return mOpaque;
- }
-
- /**
- * Sets whether or not this layer should be considered opaque.
- *
- * @param isOpaque True if the layer is opaque, false otherwise
- */
- abstract void setOpaque(boolean isOpaque);
-
- /**
* Indicates whether this layer can be rendered.
- *
+ *
* @return True if the layer can be rendered into, false otherwise
*/
- abstract boolean isValid();
+ public boolean isValid() {
+ return mFinalizer != null && mFinalizer.mDeferredUpdater != 0;
+ }
/**
- * Resize the layer, if necessary, to be at least as large
- * as the supplied dimensions.
- *
- * @param width The new desired minimum width for this layer
- * @param height The new desired minimum height for this layer
- * @return True if the resulting layer is valid, false otherwise
+ * Destroys resources without waiting for a GC.
*/
- abstract boolean resize(int width, int height);
+ public void destroy() {
+ if (!isValid()) {
+ // Already destroyed
+ return;
+ }
+
+ if (mDisplayList != null) {
+ mDisplayList.reset();
+ mDisplayList = null;
+ }
+ if (mRenderer != null) {
+ mRenderer.onLayerDestroyed(this);
+ mRenderer = null;
+ }
+ doDestroyLayerUpdater();
+ }
/**
- * Returns a hardware canvas that can be used to render onto
- * this layer.
- *
- * @return A hardware canvas, or null if a canvas cannot be created
+ * Destroys the deferred layer updater but not the backing layer. The
+ * backing layer is instead returned and is the caller's responsibility
+ * to destroy/recycle as appropriate.
*
- * @see #start(android.graphics.Canvas)
- * @see #end(android.graphics.Canvas)
+ * It is safe to call this in onLayerDestroyed only
*/
- abstract HardwareCanvas getCanvas();
+ public long detachBackingLayer() {
+ long backingLayer = nDetachBackingLayer(mFinalizer.mDeferredUpdater);
+ doDestroyLayerUpdater();
+ return backingLayer;
+ }
- /**
- * Destroys resources without waiting for a GC.
- */
- abstract void destroy();
+ private void doDestroyLayerUpdater() {
+ if (mFinalizer != null) {
+ mFinalizer.destroy();
+ mFinalizer = null;
+ }
+ }
- /**
- * This must be invoked before drawing onto this layer.
- *
- * @param currentCanvas The canvas whose rendering needs to be interrupted
- */
- abstract HardwareCanvas start(Canvas currentCanvas);
+ public DisplayList startRecording() {
+ assertType(LAYER_TYPE_RENDER);
- /**
- * This must be invoked before drawing onto this layer.
- *
- * @param dirty The dirty area to repaint
- * @param currentCanvas The canvas whose rendering needs to be interrupted
- */
- abstract HardwareCanvas start(Canvas currentCanvas, Rect dirty);
+ if (mDisplayList == null) {
+ mDisplayList = DisplayList.create("HardwareLayer");
+ }
+ return mDisplayList;
+ }
- /**
- * This must be invoked after drawing onto this layer.
- *
- * @param currentCanvas The canvas whose rendering needs to be resumed
- */
- abstract void end(Canvas currentCanvas);
+ public void endRecording(Rect dirtyRect) {
+ nUpdateRenderLayer(mFinalizer.mDeferredUpdater, mDisplayList.getNativeDisplayList(),
+ dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom);
+ mRenderer.pushLayerUpdate(this);
+ }
/**
* Copies this layer into the specified bitmap.
- *
+ *
* @param bitmap The bitmap to copy they layer into
- *
+ *
* @return True if the copy was successful, false otherwise
*/
- abstract boolean copyInto(Bitmap bitmap);
+ public boolean copyInto(Bitmap bitmap) {
+ return mRenderer.copyLayerInto(this, bitmap);
+ }
/**
- * Update the layer's properties. This method should be used
- * when the underlying storage is modified by an external entity.
- * To change the underlying storage, use the {@link #resize(int, int)}
- * method instead.
- *
+ * Update the layer's properties. Note that after calling this isValid() may
+ * return false if the requested width/height cannot be satisfied
+ *
* @param width The new width of this layer
* @param height The new height of this layer
* @param isOpaque Whether this layer is opaque
+ *
+ * @return true if the layer's properties will change, false if they already
+ * match the desired values.
*/
- void update(int width, int height, boolean isOpaque) {
- mWidth = width;
- mHeight = height;
- mOpaque = isOpaque;
+ public boolean prepare(int width, int height, boolean isOpaque) {
+ return nPrepare(mFinalizer.mDeferredUpdater, width, height, isOpaque);
}
/**
* Sets an optional transform on this layer.
- *
+ *
* @param matrix The transform to apply to the layer.
*/
- abstract void setTransform(Matrix matrix);
+ public void setTransform(Matrix matrix) {
+ nSetTransform(mFinalizer.mDeferredUpdater, matrix.native_instance);
+ }
/**
- * Specifies the display list to use to refresh the layer.
- *
- * @param displayList The display list containing the drawing commands to
- * execute in this layer
- * @param dirtyRect The dirty region of the layer that needs to be redrawn
+ * Indicates that this layer has lost its texture.
*/
- abstract void redrawLater(DisplayList displayList, Rect dirtyRect);
+ public void onTextureDestroyed() {
+ assertType(LAYER_TYPE_TEXTURE);
+ nOnTextureDestroyed(mFinalizer.mDeferredUpdater);
+ }
/**
- * Indicates that this layer has lost its underlying storage.
+ * This exists to minimize impact into the current HardwareLayer paths as
+ * some of the specifics of how to handle error cases in the fully
+ * deferred model will work
*/
- abstract void clearStorage();
+ @Deprecated
+ public void flushChanges() {
+ if (HardwareRenderer.sUseRenderThread) {
+ // Not supported, don't try.
+ return;
+ }
+
+ boolean success = nFlushChanges(mFinalizer.mDeferredUpdater);
+ if (!success) {
+ destroy();
+ }
+ }
+
+ public long getLayer() {
+ return nGetLayer(mFinalizer.mDeferredUpdater);
+ }
+
+ public void setSurfaceTexture(SurfaceTexture surface) {
+ assertType(LAYER_TYPE_TEXTURE);
+ nSetSurfaceTexture(mFinalizer.mDeferredUpdater, surface, false);
+ }
+
+ public void updateSurfaceTexture() {
+ assertType(LAYER_TYPE_TEXTURE);
+ nUpdateSurfaceTexture(mFinalizer.mDeferredUpdater);
+ }
+
+ /**
+ * This should only be used by HardwareRenderer! Do not call directly
+ */
+ SurfaceTexture createSurfaceTexture() {
+ assertType(LAYER_TYPE_TEXTURE);
+ SurfaceTexture st = new SurfaceTexture(nGetTexName(mFinalizer.mDeferredUpdater));
+ nSetSurfaceTexture(mFinalizer.mDeferredUpdater, st, true);
+ return st;
+ }
+
+ /**
+ * This should only be used by HardwareRenderer! Do not call directly
+ */
+ static HardwareLayer createTextureLayer(HardwareRenderer renderer) {
+ return new HardwareLayer(renderer, nCreateTextureLayer(), LAYER_TYPE_TEXTURE);
+ }
+
+ /**
+ * This should only be used by HardwareRenderer! Do not call directly
+ */
+ static HardwareLayer createRenderLayer(HardwareRenderer renderer,
+ int width, int height) {
+ return new HardwareLayer(renderer, nCreateRenderLayer(width, height), LAYER_TYPE_RENDER);
+ }
+
+ /** This also creates the underlying layer */
+ private static native long nCreateTextureLayer();
+ private static native long nCreateRenderLayer(int width, int height);
+
+ private static native void nOnTextureDestroyed(long layerUpdater);
+ private static native long nDetachBackingLayer(long layerUpdater);
+
+ /** This also destroys the underlying layer if it is still attached.
+ * Note it does not recycle the underlying layer, but instead queues it
+ * for deferred deletion.
+ * The HardwareRenderer should use detachBackingLayer() in the
+ * onLayerDestroyed() callback to do recycling if desired.
+ */
+ private static native void nDestroyLayerUpdater(long layerUpdater);
+
+ private static native boolean nPrepare(long layerUpdater, int width, int height, boolean isOpaque);
+ private static native void nSetLayerPaint(long layerUpdater, long paint, long colorFilter);
+ private static native void nSetTransform(long layerUpdater, long matrix);
+ private static native void nSetSurfaceTexture(long layerUpdater,
+ SurfaceTexture surface, boolean isAlreadyAttached);
+ private static native void nUpdateSurfaceTexture(long layerUpdater);
+ private static native void nUpdateRenderLayer(long layerUpdater, long displayList,
+ int left, int top, int right, int bottom);
+
+ private static native boolean nFlushChanges(long layerUpdater);
+
+ private static native long nGetLayer(long layerUpdater);
+ private static native int nGetTexName(long layerUpdater);
+
+ private static class Finalizer {
+ private long mDeferredUpdater;
+
+ public Finalizer(long deferredUpdater) {
+ mDeferredUpdater = deferredUpdater;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ destroy();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ void destroy() {
+ if (mDeferredUpdater != 0) {
+ nDestroyLayerUpdater(mDeferredUpdater);
+ mDeferredUpdater = 0;
+ }
+ }
+ }
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 352ab83..93cc9d1 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -16,6 +16,7 @@
package android.view;
+import android.graphics.Bitmap;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
@@ -344,19 +345,20 @@
* @param layer The hardware layer that needs an update
*
* @see #flushLayerUpdates()
- * @see #cancelLayerUpdate(HardwareLayer)
*/
abstract void pushLayerUpdate(HardwareLayer layer);
/**
- * Cancels a queued layer update. If the specified layer was not
- * queued for update, this method has no effect.
- *
- * @param layer The layer whose update to cancel
- *
- * @see #pushLayerUpdate(HardwareLayer)
+ * Tells the HardwareRenderer that a layer was created. The renderer should
+ * make sure to apply any pending layer changes at the start of a new frame
*/
- abstract void cancelLayerUpdate(HardwareLayer layer);
+ abstract void onLayerCreated(HardwareLayer hardwareLayer);
+
+ /**
+ * Tells the HardwareRenderer that the layer is destroyed. The renderer
+ * should remove the layer from any update queues.
+ */
+ abstract void onLayerDestroyed(HardwareLayer layer);
/**
* Forces all enqueued layer updates to be executed immediately.
@@ -403,22 +405,19 @@
* Creates a new hardware layer. A hardware layer built by calling this
* method will be treated as a texture layer, instead of as a render target.
*
- * @param isOpaque Whether the layer should be opaque or not
- *
* @return A hardware layer
*/
- abstract HardwareLayer createHardwareLayer(boolean isOpaque);
+ abstract HardwareLayer createTextureLayer();
/**
* Creates a new hardware layer.
*
* @param width The minimum width of the layer
* @param height The minimum height of the layer
- * @param isOpaque Whether the layer should be opaque or not
*
* @return A hardware layer
*/
- abstract HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque);
+ abstract HardwareLayer createDisplayListLayer(int width, int height);
/**
* Creates a new {@link SurfaceTexture} that can be used to render into the
@@ -430,14 +429,7 @@
*/
abstract SurfaceTexture createSurfaceTexture(HardwareLayer layer);
- /**
- * Sets the {@link android.graphics.SurfaceTexture} that will be used to
- * render into the specified hardware layer.
- *
- * @param layer The layer to render into using a {@link android.graphics.SurfaceTexture}
- * @param surfaceTexture The {@link android.graphics.SurfaceTexture} to use for the layer
- */
- abstract void setSurfaceTexture(HardwareLayer layer, SurfaceTexture surfaceTexture);
+ abstract boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap);
/**
* Detaches the specified functor from the current functor execution queue.
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 161fe33..e789407 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -250,7 +250,7 @@
mSurface.detachFromGLContext();
// SurfaceTexture owns the texture name and detachFromGLContext
// should have deleted it
- mLayer.clearStorage();
+ mLayer.onTextureDestroyed();
boolean shouldRelease = true;
if (mListener != null) {
@@ -375,7 +375,7 @@
return null;
}
- mLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(mOpaque);
+ mLayer = mAttachInfo.mHardwareRenderer.createTextureLayer();
if (!mUpdateSurface) {
// Create a new SurfaceTexture for the layer.
mSurface = mAttachInfo.mHardwareRenderer.createSurfaceTexture(mLayer);
@@ -416,7 +416,7 @@
updateLayer();
mMatrixChanged = true;
- mAttachInfo.mHardwareRenderer.setSurfaceTexture(mLayer, mSurface);
+ mLayer.setSurfaceTexture(mSurface);
mSurface.setDefaultBufferSize(getWidth(), getHeight());
}
@@ -469,7 +469,8 @@
}
}
- mLayer.update(getWidth(), getHeight(), mOpaque);
+ mLayer.prepare(getWidth(), getHeight(), mOpaque);
+ mLayer.updateSurfaceTexture();
if (mListener != null) {
mListener.onSurfaceTextureUpdated(mSurface);
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 2c9f1d9..1d7e5b2 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -16,6 +16,7 @@
package android.view;
+import android.graphics.Bitmap;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.os.SystemClock;
@@ -112,8 +113,8 @@
@Override
boolean safelyRun(Runnable action) {
- // TODO:
- return false;
+ nRunWithGlContext(mNativeProxy, action);
+ return true;
}
@Override
@@ -155,7 +156,12 @@
}
@Override
- void cancelLayerUpdate(HardwareLayer layer) {
+ void onLayerCreated(HardwareLayer layer) {
+ throw new NoSuchMethodError();
+ }
+
+ @Override
+ void onLayerDestroyed(HardwareLayer layer) {
throw new NoSuchMethodError();
}
@@ -197,12 +203,12 @@
}
@Override
- HardwareLayer createHardwareLayer(boolean isOpaque) {
+ HardwareLayer createTextureLayer() {
throw new NoSuchMethodError();
}
@Override
- HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque) {
+ HardwareLayer createDisplayListLayer(int width, int height) {
throw new NoSuchMethodError();
}
@@ -212,7 +218,7 @@
}
@Override
- void setSurfaceTexture(HardwareLayer layer, SurfaceTexture surfaceTexture) {
+ boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap) {
throw new NoSuchMethodError();
}
@@ -250,6 +256,7 @@
private static native void nSetup(long nativeProxy, int width, int height);
private static native void nDrawDisplayList(long nativeProxy, long displayList,
int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
+ private static native void nRunWithGlContext(long nativeProxy, Runnable runnable);
private static native void nDestroyCanvas(long nativeProxy);
private static native void nAttachFunctor(long nativeProxy, long functor);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index d017d56..393b166 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -87,7 +87,6 @@
import com.android.internal.R;
import com.android.internal.util.Predicate;
import com.android.internal.view.menu.MenuBuilder;
-
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
@@ -2385,6 +2384,17 @@
*/
static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x80;
+ /**
+ * Flag indicating that an view will cast a shadow onto the Z=0 plane if elevated.
+ */
+ static final int PFLAG3_CASTS_SHADOW = 0x100;
+
+ /**
+ * Flag indicating that view will be transformed by the global camera if rotated in 3d, or given
+ * a non-0 Z translation.
+ */
+ static final int PFLAG3_SHARES_GLOBAL_CAMERA = 0x200;
+
/* End of masks for mPrivateFlags3 */
static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
@@ -10828,6 +10838,13 @@
/**
* @hide
*/
+ public final boolean getClipToOutline() {
+ return ((mPrivateFlags3 & PFLAG3_CLIP_TO_OUTLINE) != 0);
+ }
+
+ /**
+ * @hide
+ */
public void setClipToOutline(boolean clipToOutline) {
// TODO : Add a fast invalidation here.
if (getClipToOutline() != clipToOutline) {
@@ -10845,8 +10862,49 @@
/**
* @hide
*/
- public final boolean getClipToOutline() {
- return ((mPrivateFlags3 & PFLAG3_CLIP_TO_OUTLINE) != 0);
+ public final boolean getCastsShadow() {
+ return ((mPrivateFlags3 & PFLAG3_CASTS_SHADOW) != 0);
+ }
+
+ /**
+ * @hide
+ */
+ public void setCastsShadow(boolean castsShadow) {
+ // TODO : Add a fast invalidation here.
+ if (getCastsShadow() != castsShadow) {
+ if (castsShadow) {
+ mPrivateFlags3 |= PFLAG3_CASTS_SHADOW;
+ } else {
+ mPrivateFlags3 &= ~PFLAG3_CASTS_SHADOW;
+ }
+ if (mDisplayList != null) {
+ mDisplayList.setCastsShadow(castsShadow);
+ }
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public final boolean getSharesGlobalCamera() {
+ return ((mPrivateFlags3 & PFLAG3_SHARES_GLOBAL_CAMERA) != 0);
+ }
+
+ /**
+ * @hide
+ */
+ public void setSharesGlobalCamera(boolean sharesGlobalCamera) {
+ // TODO : Add a fast invalidation here.
+ if (getSharesGlobalCamera() != sharesGlobalCamera) {
+ if (sharesGlobalCamera) {
+ mPrivateFlags3 |= PFLAG3_SHARES_GLOBAL_CAMERA;
+ } else {
+ mPrivateFlags3 &= ~PFLAG3_SHARES_GLOBAL_CAMERA;
+ }
+ if (mDisplayList != null) {
+ mDisplayList.setSharesGlobalCamera(sharesGlobalCamera);
+ }
+ }
}
/**
@@ -13570,16 +13628,10 @@
if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
if (mHardwareLayer == null) {
- mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
- width, height, isOpaque());
+ mHardwareLayer = mAttachInfo.mHardwareRenderer.createDisplayListLayer(
+ width, height);
mLocalDirtyRect.set(0, 0, width, height);
- } else {
- if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) {
- if (mHardwareLayer.resize(width, height)) {
- mLocalDirtyRect.set(0, 0, width, height);
- }
- }
-
+ } else if (mHardwareLayer.isValid()) {
// This should not be necessary but applications that change
// the parameters of their background drawable without calling
// this.setBackground(Drawable) can leave the view in a bad state
@@ -13587,23 +13639,24 @@
// not opaque.)
computeOpaqueFlags();
- final boolean opaque = isOpaque();
- if (mHardwareLayer.isValid() && mHardwareLayer.isOpaque() != opaque) {
- mHardwareLayer.setOpaque(opaque);
+ if (mHardwareLayer.prepare(width, height, isOpaque())) {
mLocalDirtyRect.set(0, 0, width, height);
}
}
// The layer is not valid if the underlying GPU resources cannot be allocated
+ mHardwareLayer.flushChanges();
if (!mHardwareLayer.isValid()) {
return null;
}
mHardwareLayer.setLayerPaint(mLayerPaint);
- mHardwareLayer.redrawLater(getHardwareLayerDisplayList(mHardwareLayer), mLocalDirtyRect);
- ViewRootImpl viewRoot = getViewRootImpl();
- if (viewRoot != null) viewRoot.pushHardwareLayerUpdate(mHardwareLayer);
-
+ DisplayList displayList = mHardwareLayer.startRecording();
+ if (getDisplayList(displayList, true) != displayList) {
+ throw new IllegalStateException("getDisplayList() didn't return"
+ + " the input displaylist for a hardware layer!");
+ }
+ mHardwareLayer.endRecording(mLocalDirtyRect);
mLocalDirtyRect.setEmpty();
}
@@ -13620,18 +13673,11 @@
*/
boolean destroyLayer(boolean valid) {
if (mHardwareLayer != null) {
- AttachInfo info = mAttachInfo;
- if (info != null && info.mHardwareRenderer != null &&
- info.mHardwareRenderer.isEnabled() &&
- (valid || info.mHardwareRenderer.validate())) {
+ mHardwareLayer.destroy();
+ mHardwareLayer = null;
- info.mHardwareRenderer.cancelLayerUpdate(mHardwareLayer);
- mHardwareLayer.destroy();
- mHardwareLayer = null;
-
- invalidate(true);
- invalidateParentCaches();
- }
+ invalidate(true);
+ invalidateParentCaches();
return true;
}
return false;
@@ -13852,19 +13898,6 @@
}
/**
- * Get the DisplayList for the HardwareLayer
- *
- * @param layer The HardwareLayer whose DisplayList we want
- * @return A DisplayList fopr the specified HardwareLayer
- */
- private DisplayList getHardwareLayerDisplayList(HardwareLayer layer) {
- DisplayList displayList = getDisplayList(layer.getDisplayList(), true);
- layer.setDisplayList(displayList);
- return displayList;
- }
-
-
- /**
* <p>Returns a display list that can be used to draw this view again
* without executing its draw method.</p>
*
@@ -14502,6 +14535,8 @@
}
displayList.setOutline(mOutline);
displayList.setClipToOutline(getClipToOutline());
+ displayList.setCastsShadow(getCastsShadow());
+ displayList.setSharesGlobalCamera(getSharesGlobalCamera());
float alpha = 1;
if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 7aa568b..c3bf533 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3178,7 +3178,7 @@
* inherited Z ordering volume.
*/
public void setIsolatedZVolume(boolean isolateZVolume) {
- boolean previousValue = (mGroupFlags & FLAG_ISOLATED_Z_VOLUME) == FLAG_ISOLATED_Z_VOLUME;
+ boolean previousValue = (mGroupFlags & FLAG_ISOLATED_Z_VOLUME) != 0;
if (isolateZVolume != previousValue) {
setBooleanFlag(FLAG_ISOLATED_Z_VOLUME, isolateZVolume);
if (mDisplayList != null) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ccb85a6..ef69948 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -642,12 +642,6 @@
}
}
- void pushHardwareLayerUpdate(HardwareLayer layer) {
- if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
- mAttachInfo.mHardwareRenderer.pushLayerUpdate(layer);
- }
- }
-
void flushHardwareLayerUpdates() {
if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled() &&
mAttachInfo.mHardwareRenderer.validate()) {
diff --git a/core/java/com/android/server/SystemService.java b/core/java/com/android/server/SystemService.java
index d69293a..0c89f94 100644
--- a/core/java/com/android/server/SystemService.java
+++ b/core/java/com/android/server/SystemService.java
@@ -23,24 +23,24 @@
/**
* The base class for services running in the system process. Override and implement
* the lifecycle event callback methods as needed.
- *
+ * <p>
* The lifecycle of a SystemService:
- *
- * {@link #onCreate(android.content.Context)} is called to initialize the
- * service.
- *
- * {@link #onStart()} is called to get the service running. It is common
- * for services to publish their Binder interface at this point. All required
- * dependencies are also assumed to be ready to use.
- *
- * Then {@link #onBootPhase(int)} is called as many times as there are boot phases
+ * </p><ul>
+ * <li>The constructor is called and provided with the system {@link Context}
+ * to initialize the system service.
+ * <li>{@link #onStart()} is called to get the service running. The service should
+ * publish its binder interface at this point using
+ * {@link #publishBinderService(String, IBinder)}. It may also publish additional
+ * local interfaces that other services within the system server may use to access
+ * privileged internal functions.
+ * <li>Then {@link #onBootPhase(int)} is called as many times as there are boot phases
* until {@link #PHASE_BOOT_COMPLETE} is sent, which is the last boot phase. Each phase
* is an opportunity to do special work, like acquiring optional service dependencies,
* waiting to see if SafeMode is enabled, or registering with a service that gets
* started after this one.
- *
- * NOTE: All lifecycle methods are called from the same thread that created the
- * SystemService.
+ * </ul><p>
+ * NOTE: All lifecycle methods are called from the system server's main looper thread.
+ * </p>
*
* {@hide}
*/
@@ -54,17 +54,34 @@
public static final int PHASE_THIRD_PARTY_APPS_CAN_START = 600;
public static final int PHASE_BOOT_COMPLETE = 1000;
- private SystemServiceManager mManager;
- private Context mContext;
+ private final Context mContext;
- final void init(Context context, SystemServiceManager manager) {
+ /**
+ * Initializes the system service.
+ * <p>
+ * Subclasses must define a single argument constructor that accepts the context
+ * and passes it to super.
+ * </p>
+ *
+ * @param context The system server context.
+ */
+ public SystemService(Context context) {
mContext = context;
- mManager = manager;
- onCreate(context);
}
+ /**
+ * Gets the system context.
+ */
+ public final Context getContext() {
+ return mContext;
+ }
+
+ /**
+ * Returns true if the system is running in safe mode.
+ * TODO: we should define in which phase this becomes valid
+ */
public final boolean isSafeMode() {
- return mManager.isSafeMode();
+ return getManager().isSafeMode();
}
/**
@@ -126,8 +143,8 @@
return LocalServices.getService(type);
}
- public final Context getContext() {
- return mContext;
+ private SystemServiceManager getManager() {
+ return LocalServices.getService(SystemServiceManager.class);
}
// /**
diff --git a/core/java/com/android/server/SystemServiceManager.java b/core/java/com/android/server/SystemServiceManager.java
index 06ad7f4..6c853be 100644
--- a/core/java/com/android/server/SystemServiceManager.java
+++ b/core/java/com/android/server/SystemServiceManager.java
@@ -17,14 +17,15 @@
package com.android.server;
import android.content.Context;
-import android.util.Log;
import android.util.Slog;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
/**
* Manages creating, starting, and other lifecycle events of
- * {@link com.android.server.SystemService}s.
+ * {@link com.android.server.SystemService system services}.
*
* {@hide}
*/
@@ -68,24 +69,43 @@
*/
@SuppressWarnings("unchecked")
public <T extends SystemService> T startService(Class<T> serviceClass) {
- final T serviceInstance = (T)createInstance(serviceClass);
+ final String name = serviceClass.getName();
+ Slog.i(TAG, "Starting " + name);
+
+ // Create the service.
+ if (!SystemService.class.isAssignableFrom(serviceClass)) {
+ throw new RuntimeException("Failed to create " + name
+ + ": service must extend " + SystemService.class.getName());
+ }
+ final T service;
try {
- Slog.i(TAG, "Creating " + serviceClass.getSimpleName());
- serviceInstance.init(mContext, this);
- } catch (Throwable e) {
- throw new RuntimeException("Failed to create service " + serviceClass.getName(), e);
+ Constructor<T> constructor = serviceClass.getConstructor(Context.class);
+ service = constructor.newInstance(mContext);
+ } catch (InstantiationException ex) {
+ throw new RuntimeException("Failed to create service " + name
+ + ": service could not be instantiated", ex);
+ } catch (IllegalAccessException ex) {
+ throw new RuntimeException("Failed to create service " + name
+ + ": service must have a public constructor with a Context argument", ex);
+ } catch (NoSuchMethodException ex) {
+ throw new RuntimeException("Failed to create service " + name
+ + ": service must have a public constructor with a Context argument", ex);
+ } catch (InvocationTargetException ex) {
+ throw new RuntimeException("Failed to create service " + name
+ + ": service constructor threw an exception", ex);
}
- mServices.add(serviceInstance);
+ // Register it.
+ mServices.add(service);
+ // Start it.
try {
- Slog.i(TAG, "Starting " + serviceClass.getSimpleName());
- serviceInstance.onStart();
- } catch (Throwable e) {
- throw new RuntimeException("Failed to start service " + serviceClass.getName(), e);
+ service.onStart();
+ } catch (RuntimeException ex) {
+ throw new RuntimeException("Failed to start service " + name
+ + ": onStart threw an exception", ex);
}
-
- return serviceInstance;
+ return service;
}
/**
@@ -107,9 +127,11 @@
final SystemService service = mServices.get(i);
try {
service.onBootPhase(mCurrentPhase);
- } catch (Throwable e) {
- reportWtf("Service " + service.getClass().getName() +
- " threw an Exception processing boot phase " + mCurrentPhase, e);
+ } catch (Exception ex) {
+ throw new RuntimeException("Failed to boot service "
+ + service.getClass().getName()
+ + ": onBootPhase threw an exception during phase "
+ + mCurrentPhase, ex);
}
}
}
@@ -144,34 +166,4 @@
Slog.e(TAG, builder.toString());
}
-
- private SystemService createInstance(Class<?> clazz) {
- // Make sure it's a type we expect
- if (!SystemService.class.isAssignableFrom(clazz)) {
- reportWtf("Class " + clazz.getName() + " does not extend " +
- SystemService.class.getName());
- }
-
- try {
- return (SystemService) clazz.newInstance();
- } catch (InstantiationException e) {
- reportWtf("Class " + clazz.getName() + " is abstract", e);
- } catch (IllegalAccessException e) {
- reportWtf("Class " + clazz.getName() +
- " must have a public no-arg constructor", e);
- }
- return null;
- }
-
- private static void reportWtf(String message) {
- reportWtf(message, null);
- }
-
- private static void reportWtf(String message, Throwable e) {
- Slog.i(TAG, "******************************");
- Log.wtf(TAG, message, e);
-
- // Make sure we die
- throw new RuntimeException(message, e);
- }
}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index f8d96e3..d8041c5 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -57,6 +57,7 @@
android_view_GraphicBuffer.cpp \
android_view_GLRenderer.cpp \
android_view_GLES20Canvas.cpp \
+ android_view_HardwareLayer.cpp \
android_view_ThreadedRenderer.cpp \
android_view_MotionEvent.cpp \
android_view_PointerIcon.cpp \
@@ -193,6 +194,7 @@
libui \
libgui \
libinput \
+ libinputflinger \
libcamera_client \
libcamera_metadata \
libskia \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 7ed6641..77c5c18 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -123,6 +123,7 @@
extern int register_android_view_GraphicBuffer(JNIEnv* env);
extern int register_android_view_GLES20Canvas(JNIEnv* env);
extern int register_android_view_GLRenderer(JNIEnv* env);
+extern int register_android_view_HardwareLayer(JNIEnv* env);
extern int register_android_view_ThreadedRenderer(JNIEnv* env);
extern int register_android_view_Surface(JNIEnv* env);
extern int register_android_view_SurfaceControl(JNIEnv* env);
@@ -1127,6 +1128,7 @@
REG_JNI(register_android_view_GraphicBuffer),
REG_JNI(register_android_view_GLES20Canvas),
REG_JNI(register_android_view_GLRenderer),
+ REG_JNI(register_android_view_HardwareLayer),
REG_JNI(register_android_view_ThreadedRenderer),
REG_JNI(register_android_view_Surface),
REG_JNI(register_android_view_SurfaceControl),
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 3e1f26a..fae93ba 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -474,6 +474,12 @@
bitmapCreateFlags, ninePatchChunk, layoutBounds, -1);
}
+// Need to buffer enough input to be able to rewind as much as might be read by a decoder
+// trying to determine the stream's format. Currently the most is 64, read by
+// SkImageDecoder_libwebp.
+// FIXME: Get this number from SkImageDecoder
+#define BYTES_TO_BUFFER 64
+
static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteArray storage,
jobject padding, jobject options) {
@@ -481,11 +487,8 @@
SkAutoTUnref<SkStream> stream(CreateJavaInputStreamAdaptor(env, is, storage));
if (stream.get()) {
- // Need to buffer enough input to be able to rewind as much as might be read by a decoder
- // trying to determine the stream's format. Currently the most is 64, read by
- // SkImageDecoder_libwebp.
- // FIXME: Get this number from SkImageDecoder
- SkAutoTUnref<SkStreamRewindable> bufferedStream(SkFrontBufferedStream::Create(stream, 64));
+ SkAutoTUnref<SkStreamRewindable> bufferedStream(
+ SkFrontBufferedStream::Create(stream, BYTES_TO_BUFFER));
SkASSERT(bufferedStream.get() != NULL);
// for now we don't allow purgeable with java inputstreams
bitmap = doDecode(env, bufferedStream, padding, options, false, false);
@@ -506,30 +509,48 @@
return nullObjectReturn("fstat return -1");
}
- bool isPurgeable = optionsPurgeable(env, bitmapFactoryOptions);
- bool isShareable = optionsShareable(env, bitmapFactoryOptions);
- bool weOwnTheFD = false;
- if (isPurgeable && isShareable) {
- int newFD = ::dup(descriptor);
- if (-1 != newFD) {
- weOwnTheFD = true;
- descriptor = newFD;
- }
- }
+ // Restore the descriptor's offset on exiting this function.
+ AutoFDSeek autoRestore(descriptor);
FILE* file = fdopen(descriptor, "r");
if (file == NULL) {
return nullObjectReturn("Could not open file");
}
- SkAutoTUnref<SkFILEStream> stream(new SkFILEStream(file,
- weOwnTheFD ? SkFILEStream::kCallerPasses_Ownership :
+ SkAutoTUnref<SkFILEStream> fileStream(new SkFILEStream(file,
SkFILEStream::kCallerRetains_Ownership));
- /* Allow purgeable iff we own the FD, i.e., in the puregeable and
- shareable case.
- */
- return doDecode(env, stream, padding, bitmapFactoryOptions, weOwnTheFD);
+ SkAutoTUnref<SkStreamRewindable> stream;
+
+ // Retain the old behavior of allowing purgeable if both purgeable and
+ // shareable are set to true.
+ bool isPurgeable = optionsPurgeable(env, bitmapFactoryOptions)
+ && optionsShareable(env, bitmapFactoryOptions);
+ if (isPurgeable) {
+ // Copy the stream, so the image can be decoded multiple times without
+ // continuing to modify the original file descriptor.
+ // Copy beginning from the current position.
+ const size_t fileSize = fileStream->getLength() - fileStream->getPosition();
+ void* buffer = sk_malloc_flags(fileSize, 0);
+ if (buffer == NULL) {
+ return nullObjectReturn("Could not make a copy for ashmem");
+ }
+
+ SkAutoTUnref<SkData> data(SkData::NewFromMalloc(buffer, fileSize));
+
+ if (fileStream->read(buffer, fileSize) != fileSize) {
+ return nullObjectReturn("Could not read the file.");
+ }
+
+ stream.reset(new SkMemoryStream(data));
+ } else {
+ // Use a buffered stream. Although an SkFILEStream can be rewound, this
+ // ensures that SkImageDecoder::Factory never rewinds beyond the
+ // current position of the file descriptor.
+ stream.reset(SkFrontBufferedStream::Create(fileStream, BYTES_TO_BUFFER));
+ }
+
+ return doDecode(env, stream, padding, bitmapFactoryOptions, isPurgeable);
}
static jobject nativeDecodeAsset(JNIEnv* env, jobject clazz, jlong native_asset,
diff --git a/core/jni/android/graphics/ColorFilter.cpp b/core/jni/android/graphics/ColorFilter.cpp
index da40acff..09589bd 100644
--- a/core/jni/android/graphics/ColorFilter.cpp
+++ b/core/jni/android/graphics/ColorFilter.cpp
@@ -23,7 +23,6 @@
#include "SkColorMatrixFilter.h"
#include "SkPorterDuff.h"
-#include <SkiaColorFilter.h>
#include <Caches.h>
namespace android {
@@ -32,64 +31,9 @@
class SkColorFilterGlue {
public:
- static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle, jlong fHandle) {
- SkColorFilter* obj = reinterpret_cast<SkColorFilter *>(objHandle);
- SkiaColorFilter* f = reinterpret_cast<SkiaColorFilter *>(fHandle);
- if (obj) SkSafeUnref(obj);
- // f == NULL when not !USE_OPENGL_RENDERER, so no need to delete outside the ifdef
-#ifdef USE_OPENGL_RENDERER
- if (f && android::uirenderer::Caches::hasInstance()) {
- android::uirenderer::Caches::getInstance().resourceCache.destructor(f);
- } else {
- delete f;
- }
-#endif
- }
-
- static jlong glCreatePorterDuffFilter(JNIEnv* env, jobject, jlong skFilterHandle,
- jint srcColor, jint modeHandle) {
- SkColorFilter *skFilter = reinterpret_cast<SkColorFilter *>(skFilterHandle);
- SkPorterDuff::Mode mode = static_cast<SkPorterDuff::Mode>(modeHandle);
-#ifdef USE_OPENGL_RENDERER
- return reinterpret_cast<jlong>(new SkiaBlendFilter(skFilter, srcColor, SkPorterDuff::ToXfermodeMode(mode)));
-#else
- return NULL;
-#endif
- }
-
- static jlong glCreateLightingFilter(JNIEnv* env, jobject, jlong skFilterHandle,
- jint mul, jint add) {
- SkColorFilter *skFilter = reinterpret_cast<SkColorFilter *>(skFilterHandle);
-#ifdef USE_OPENGL_RENDERER
- return reinterpret_cast<jlong>(new SkiaLightingFilter(skFilter, mul, add));
-#else
- return NULL;
-#endif
- }
-
- static jlong glCreateColorMatrixFilter(JNIEnv* env, jobject, jlong skFilterHandle,
- jfloatArray jarray) {
- SkColorFilter *skFilter = reinterpret_cast<SkColorFilter *>(skFilterHandle);
-#ifdef USE_OPENGL_RENDERER
- AutoJavaFloatArray autoArray(env, jarray, 20);
- const float* src = autoArray.ptr();
-
- float* colorMatrix = new float[16];
- memcpy(colorMatrix, src, 4 * sizeof(float));
- memcpy(&colorMatrix[4], &src[5], 4 * sizeof(float));
- memcpy(&colorMatrix[8], &src[10], 4 * sizeof(float));
- memcpy(&colorMatrix[12], &src[15], 4 * sizeof(float));
-
- float* colorVector = new float[4];
- colorVector[0] = src[4];
- colorVector[1] = src[9];
- colorVector[2] = src[14];
- colorVector[3] = src[19];
-
- return reinterpret_cast<jlong>(new SkiaColorMatrixFilter(skFilter, colorMatrix, colorVector));
-#else
- return NULL;
-#endif
+ static void finalizer(JNIEnv* env, jobject clazz, jlong skFilterHandle) {
+ SkColorFilter* filter = reinterpret_cast<SkColorFilter *>(skFilterHandle);
+ if (filter) SkSafeUnref(filter);
}
static jlong CreatePorterDuffFilter(JNIEnv* env, jobject, jint srcColor,
@@ -119,22 +63,19 @@
};
static JNINativeMethod colorfilter_methods[] = {
- {"destroyFilter", "(JJ)V", (void*) SkColorFilterGlue::finalizer}
+ {"destroyFilter", "(J)V", (void*) SkColorFilterGlue::finalizer}
};
static JNINativeMethod porterduff_methods[] = {
{ "native_CreatePorterDuffFilter", "(II)J", (void*) SkColorFilterGlue::CreatePorterDuffFilter },
- { "nCreatePorterDuffFilter", "(JII)J", (void*) SkColorFilterGlue::glCreatePorterDuffFilter }
};
static JNINativeMethod lighting_methods[] = {
{ "native_CreateLightingFilter", "(II)J", (void*) SkColorFilterGlue::CreateLightingFilter },
- { "nCreateLightingFilter", "(JII)J", (void*) SkColorFilterGlue::glCreateLightingFilter },
};
static JNINativeMethod colormatrix_methods[] = {
{ "nativeColorMatrixFilter", "([F)J", (void*) SkColorFilterGlue::CreateColorMatrixFilter },
- { "nColorMatrixFilter", "(J[F)J", (void*) SkColorFilterGlue::glCreateColorMatrixFilter }
};
#define REG(env, name, array) \
diff --git a/core/jni/android/graphics/pdf/PdfDocument.cpp b/core/jni/android/graphics/pdf/PdfDocument.cpp
index 6175a8f..d54aaa8 100644
--- a/core/jni/android/graphics/pdf/PdfDocument.cpp
+++ b/core/jni/android/graphics/pdf/PdfDocument.cpp
@@ -113,24 +113,24 @@
PageRecord* mCurrentPage;
};
-static jint nativeCreateDocument(JNIEnv* env, jobject thiz) {
- return reinterpret_cast<jint>(new PdfDocument());
+static jlong nativeCreateDocument(JNIEnv* env, jobject thiz) {
+ return reinterpret_cast<jlong>(new PdfDocument());
}
-static jint nativeStartPage(JNIEnv* env, jobject thiz, jint documentPtr,
+static jlong nativeStartPage(JNIEnv* env, jobject thiz, jlong documentPtr,
jint pageWidth, jint pageHeight,
jint contentLeft, jint contentTop, jint contentRight, jint contentBottom) {
PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
- return reinterpret_cast<jint>(document->startPage(pageWidth, pageHeight,
+ return reinterpret_cast<jlong>(document->startPage(pageWidth, pageHeight,
contentLeft, contentTop, contentRight, contentBottom));
}
-static void nativeFinishPage(JNIEnv* env, jobject thiz, jint documentPtr) {
+static void nativeFinishPage(JNIEnv* env, jobject thiz, jlong documentPtr) {
PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
document->finishPage();
}
-static void nativeWriteTo(JNIEnv* env, jobject thiz, jint documentPtr, jobject out,
+static void nativeWriteTo(JNIEnv* env, jobject thiz, jlong documentPtr, jobject out,
jbyteArray chunk) {
PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
SkWStream* skWStream = CreateJavaOutputStreamAdaptor(env, out, chunk);
@@ -138,17 +138,17 @@
delete skWStream;
}
-static void nativeClose(JNIEnv* env, jobject thiz, jint documentPtr) {
+static void nativeClose(JNIEnv* env, jobject thiz, jlong documentPtr) {
PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
document->close();
}
static JNINativeMethod gPdfDocument_Methods[] = {
- {"nativeCreateDocument", "()I", (void*) nativeCreateDocument},
- {"nativeStartPage", "(IIIIIII)I", (void*) nativeStartPage},
- {"nativeFinishPage", "(I)V", (void*) nativeFinishPage},
- {"nativeWriteTo", "(ILjava/io/OutputStream;[B)V", (void*) nativeWriteTo},
- {"nativeClose", "(I)V", (void*) nativeClose}
+ {"nativeCreateDocument", "()J", (void*) nativeCreateDocument},
+ {"nativeStartPage", "(JIIIIII)J", (void*) nativeStartPage},
+ {"nativeFinishPage", "(J)V", (void*) nativeFinishPage},
+ {"nativeWriteTo", "(JLjava/io/OutputStream;[B)V", (void*) nativeWriteTo},
+ {"nativeClose", "(J)V", (void*) nativeClose}
};
int register_android_graphics_pdf_PdfDocument(JNIEnv* env) {
diff --git a/core/jni/android_database_SQLiteGlobal.cpp b/core/jni/android_database_SQLiteGlobal.cpp
index acc2276..89d64fa 100644
--- a/core/jni/android_database_SQLiteGlobal.cpp
+++ b/core/jni/android_database_SQLiteGlobal.cpp
@@ -39,7 +39,7 @@
bool verboseLog = !!data;
if (iErrCode == 0 || iErrCode == SQLITE_CONSTRAINT || iErrCode == SQLITE_SCHEMA) {
if (verboseLog) {
- ALOGV(LOG_VERBOSE, SQLITE_LOG_TAG, "(%d) %s\n", iErrCode, zMsg);
+ ALOG(LOG_VERBOSE, SQLITE_LOG_TAG, "(%d) %s\n", iErrCode, zMsg);
}
} else {
ALOG(LOG_ERROR, SQLITE_LOG_TAG, "(%d) %s\n", iErrCode, zMsg);
diff --git a/core/jni/android_emoji_EmojiFactory.cpp b/core/jni/android_emoji_EmojiFactory.cpp
index 5276934..f127d29 100644
--- a/core/jni/android_emoji_EmojiFactory.cpp
+++ b/core/jni/android_emoji_EmojiFactory.cpp
@@ -104,7 +104,7 @@
static jobject create_java_EmojiFactory(
JNIEnv* env, EmojiFactory* factory, jstring name) {
jobject obj = env->NewObject(gEmojiFactory_class, gEmojiFactory_constructorMethodID,
- static_cast<jint>(reinterpret_cast<uintptr_t>(factory)), name);
+ reinterpret_cast<jlong>(factory), name);
if (env->ExceptionCheck() != 0) {
ALOGE("*** Uncaught exception returned from Java call!\n");
env->ExceptionDescribe();
@@ -155,7 +155,7 @@
}
static jobject android_emoji_EmojiFactory_getBitmapFromAndroidPua(
- JNIEnv* env, jobject clazz, jint nativeEmojiFactory, jint pua) {
+ JNIEnv* env, jobject clazz, jlong nativeEmojiFactory, jint pua) {
EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
int size;
@@ -175,7 +175,7 @@
}
static void android_emoji_EmojiFactory_destructor(
- JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
+ JNIEnv* env, jobject obj, jlong nativeEmojiFactory) {
/*
// Must not delete this object!!
EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
@@ -184,49 +184,49 @@
}
static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis(
- JNIEnv* env, jobject obj, jint nativeEmojiFactory, jchar sjis) {
+ JNIEnv* env, jobject obj, jlong nativeEmojiFactory, jchar sjis) {
EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
return factory->GetAndroidPuaFromVendorSpecificSjis(sjis);
}
static jint android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua(
- JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint pua) {
+ JNIEnv* env, jobject obj, jlong nativeEmojiFactory, jint pua) {
EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
return factory->GetVendorSpecificSjisFromAndroidPua(pua);
}
static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua(
- JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint vsu) {
+ JNIEnv* env, jobject obj, jlong nativeEmojiFactory, jint vsu) {
EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
return factory->GetAndroidPuaFromVendorSpecificPua(vsu);
}
static jint android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua(
- JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint pua) {
+ JNIEnv* env, jobject obj, jlong nativeEmojiFactory, jint pua) {
EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
return factory->GetVendorSpecificPuaFromAndroidPua(pua);
}
static jint android_emoji_EmojiFactory_getMaximumVendorSpecificPua(
- JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
+ JNIEnv* env, jobject obj, jlong nativeEmojiFactory) {
EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
return factory->GetMaximumVendorSpecificPua();
}
static jint android_emoji_EmojiFactory_getMinimumVendorSpecificPua(
- JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
+ JNIEnv* env, jobject obj, jlong nativeEmojiFactory) {
EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
return factory->GetMinimumVendorSpecificPua();
}
static jint android_emoji_EmojiFactory_getMaximumAndroidPua(
- JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
+ JNIEnv* env, jobject obj, jlong nativeEmojiFactory) {
EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
return factory->GetMaximumAndroidPua();
}
static jint android_emoji_EmojiFactory_getMinimumAndroidPua(
- JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
+ JNIEnv* env, jobject obj, jlong nativeEmojiFactory) {
EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
return factory->GetMinimumAndroidPua();
}
@@ -236,25 +236,25 @@
(void*)android_emoji_EmojiFactory_newInstance},
{ "newAvailableInstance", "()Landroid/emoji/EmojiFactory;",
(void*)android_emoji_EmojiFactory_newAvailableInstance},
- { "nativeDestructor", "(I)V",
+ { "nativeDestructor", "(J)V",
(void*)android_emoji_EmojiFactory_destructor},
- { "nativeGetBitmapFromAndroidPua", "(II)Landroid/graphics/Bitmap;",
+ { "nativeGetBitmapFromAndroidPua", "(JI)Landroid/graphics/Bitmap;",
(void*)android_emoji_EmojiFactory_getBitmapFromAndroidPua},
- { "nativeGetAndroidPuaFromVendorSpecificSjis", "(IC)I",
+ { "nativeGetAndroidPuaFromVendorSpecificSjis", "(JC)I",
(void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis},
- { "nativeGetVendorSpecificSjisFromAndroidPua", "(II)I",
+ { "nativeGetVendorSpecificSjisFromAndroidPua", "(JI)I",
(void*)android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua},
- { "nativeGetAndroidPuaFromVendorSpecificPua", "(II)I",
+ { "nativeGetAndroidPuaFromVendorSpecificPua", "(JI)I",
(void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua},
- { "nativeGetVendorSpecificPuaFromAndroidPua", "(II)I",
+ { "nativeGetVendorSpecificPuaFromAndroidPua", "(JI)I",
(void*)android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua},
- { "nativeGetMaximumVendorSpecificPua", "(I)I",
+ { "nativeGetMaximumVendorSpecificPua", "(J)I",
(void*)android_emoji_EmojiFactory_getMaximumVendorSpecificPua},
- { "nativeGetMinimumVendorSpecificPua", "(I)I",
+ { "nativeGetMinimumVendorSpecificPua", "(J)I",
(void*)android_emoji_EmojiFactory_getMinimumVendorSpecificPua},
- { "nativeGetMaximumAndroidPua", "(I)I",
+ { "nativeGetMaximumAndroidPua", "(J)I",
(void*)android_emoji_EmojiFactory_getMaximumAndroidPua},
- { "nativeGetMinimumAndroidPua", "(I)I",
+ { "nativeGetMinimumAndroidPua", "(J)I",
(void*)android_emoji_EmojiFactory_getMinimumAndroidPua}
};
@@ -276,7 +276,7 @@
int register_android_emoji_EmojiFactory(JNIEnv* env) {
gEmojiFactory_class = make_globalref(env, "android/emoji/EmojiFactory");
gEmojiFactory_constructorMethodID = env->GetMethodID(
- gEmojiFactory_class, "<init>", "(ILjava/lang/String;)V");
+ gEmojiFactory_class, "<init>", "(JLjava/lang/String;)V");
return jniRegisterNativeMethods(env, "android/emoji/EmojiFactory",
gMethods, NELEM(gMethods));
}
diff --git a/core/jni/android_os_SELinux.cpp b/core/jni/android_os_SELinux.cpp
index 2b85fef..db84d000 100644
--- a/core/jni/android_os_SELinux.cpp
+++ b/core/jni/android_os_SELinux.cpp
@@ -411,7 +411,7 @@
ScopedUtfChars pathname(env, pathnameStr);
if (pathname.c_str() == NULL) {
- ALOGV("restorecon(%p) => threw exception", pathname);
+ ALOGV("restorecon(%p) => threw exception", pathnameStr);
return false;
}
diff --git a/core/jni/android_view_DisplayList.cpp b/core/jni/android_view_DisplayList.cpp
index 5f7912b..de68b97 100644
--- a/core/jni/android_view_DisplayList.cpp
+++ b/core/jni/android_view_DisplayList.cpp
@@ -136,6 +136,18 @@
displayList->setClipToOutline(clipToOutline);
}
+static void android_view_DisplayList_setCastsShadow(JNIEnv* env,
+ jobject clazz, jlong displayListPtr, jboolean castsShadow) {
+ DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
+ displayList->setCastsShadow(castsShadow);
+}
+
+static void android_view_DisplayList_setSharesGlobalCamera(JNIEnv* env,
+ jobject clazz, jlong displayListPtr, jboolean sharesGlobalCamera) {
+ DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
+ displayList->setSharesGlobalCamera(sharesGlobalCamera);
+}
+
static void android_view_DisplayList_setAlpha(JNIEnv* env,
jobject clazz, jlong displayListPtr, float alpha) {
DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
@@ -407,6 +419,8 @@
{ "nSetProjectionReceiver","(JZ)V", (void*) android_view_DisplayList_setProjectionReceiver },
{ "nSetOutline", "(JJ)V", (void*) android_view_DisplayList_setOutline },
{ "nSetClipToOutline", "(JZ)V", (void*) android_view_DisplayList_setClipToOutline },
+ { "nSetCastsShadow", "(JZ)V", (void*) android_view_DisplayList_setCastsShadow },
+ { "nSetSharesGlobalCamera","(JZ)V", (void*) android_view_DisplayList_setSharesGlobalCamera },
{ "nSetAlpha", "(JF)V", (void*) android_view_DisplayList_setAlpha },
{ "nSetHasOverlappingRendering", "(JZ)V",
(void*) android_view_DisplayList_setHasOverlappingRendering },
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 04e51be..dd089f2 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -47,7 +47,6 @@
#include <LayerRenderer.h>
#include <OpenGLRenderer.h>
#include <SkiaShader.h>
-#include <SkiaColorFilter.h>
#include <Stencil.h>
#include <Rect.h>
@@ -81,7 +80,6 @@
#define MODIFIER_SHADOW 1
#define MODIFIER_SHADER 2
-#define MODIFIER_COLOR_FILTER 4
// ----------------------------------------------------------------------------
@@ -638,7 +636,6 @@
OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
if (modifiers & MODIFIER_SHADOW) renderer->resetShadow();
if (modifiers & MODIFIER_SHADER) renderer->resetShader();
- if (modifiers & MODIFIER_COLOR_FILTER) renderer->resetColorFilter();
}
static void android_view_GLES20Canvas_setupShader(JNIEnv* env, jobject clazz,
@@ -648,12 +645,6 @@
renderer->setupShader(shader);
}
-static void android_view_GLES20Canvas_setupColorFilter(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jlong colorFilterPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- SkiaColorFilter* colorFilter = reinterpret_cast<SkiaColorFilter*>(colorFilterPtr);
- renderer->setupColorFilter(colorFilter);
-}
static void android_view_GLES20Canvas_setupShadow(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat radius, jfloat dx, jfloat dy, jint color) {
@@ -923,147 +914,6 @@
renderer->resume();
}
-static jint android_view_GLES20Canvas_createLayerRenderer(JNIEnv* env,
- jobject clazz, jlong layerPtr) {
- Layer* layer = reinterpret_cast<Layer*>(layerPtr);
- if (layer) {
- OpenGLRenderer* renderer = new LayerRenderer(layer);
- renderer->initProperties();
- return reinterpret_cast<jint>(renderer);
- }
- return NULL;
-}
-
-static jlong android_view_GLES20Canvas_createTextureLayer(JNIEnv* env, jobject clazz,
- jboolean isOpaque, jintArray layerInfo) {
- Layer* layer = LayerRenderer::createTextureLayer(isOpaque);
-
- if (layer) {
- jint* storage = env->GetIntArrayElements(layerInfo, NULL);
- storage[0] = layer->getTexture();
- env->ReleaseIntArrayElements(layerInfo, storage, 0);
- }
-
- return reinterpret_cast<jlong>(layer);
-}
-
-static jlong android_view_GLES20Canvas_createLayer(JNIEnv* env, jobject clazz,
- jint width, jint height, jboolean isOpaque, jintArray layerInfo) {
- Layer* layer = LayerRenderer::createLayer(width, height, isOpaque);
-
- if (layer) {
- jint* storage = env->GetIntArrayElements(layerInfo, NULL);
- storage[0] = layer->getWidth();
- storage[1] = layer->getHeight();
- env->ReleaseIntArrayElements(layerInfo, storage, 0);
- }
-
- return reinterpret_cast<jlong>(layer);
-}
-
-static jboolean android_view_GLES20Canvas_resizeLayer(JNIEnv* env, jobject clazz,
- jlong layerPtr, jint width, jint height, jintArray layerInfo) {
- Layer* layer = reinterpret_cast<Layer*>(layerPtr);
- if (LayerRenderer::resizeLayer(layer, width, height)) {
- jint* storage = env->GetIntArrayElements(layerInfo, NULL);
- storage[0] = layer->getWidth();
- storage[1] = layer->getHeight();
- env->ReleaseIntArrayElements(layerInfo, storage, 0);
- return JNI_TRUE;
- }
- return JNI_FALSE;
-}
-
-static void android_view_GLES20Canvas_setLayerPaint(JNIEnv* env, jobject clazz,
- jlong layerPtr, jlong paintPtr) {
- Layer* layer = reinterpret_cast<Layer*>(layerPtr);
- if (layer) {
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
- layer->setPaint(paint);
- }
-}
-
-static void android_view_GLES20Canvas_setLayerColorFilter(JNIEnv* env, jobject clazz,
- jlong layerPtr, jlong colorFilterPtr) {
- Layer* layer = reinterpret_cast<Layer*>(layerPtr);
- if (layer) {
- SkiaColorFilter* colorFilter = reinterpret_cast<SkiaColorFilter*>(colorFilterPtr);
- layer->setColorFilter(colorFilter);
- }
-}
-
-static void android_view_GLES20Canvas_setOpaqueLayer(JNIEnv* env, jobject clazz,
- jlong layerPtr, jboolean isOpaque) {
- Layer* layer = reinterpret_cast<Layer*>(layerPtr);
- if (layer) {
- layer->setBlend(!isOpaque);
- }
-}
-
-static void android_view_GLES20Canvas_updateTextureLayer(JNIEnv* env, jobject clazz,
- jlong layerPtr, jint width, jint height, jboolean isOpaque, jobject surface) {
- float transform[16];
- sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, surface));
-
- if (surfaceTexture->updateTexImage() == NO_ERROR) {
- int64_t frameNumber = surfaceTexture->getFrameNumber();
- // If the GLConsumer queue is in synchronous mode, need to discard all
- // but latest frame, using the frame number to tell when we no longer
- // have newer frames to target. Since we can't tell which mode it is in,
- // do this unconditionally.
- int dropCounter = 0;
- while (surfaceTexture->updateTexImage() == NO_ERROR) {
- int64_t newFrameNumber = surfaceTexture->getFrameNumber();
- if (newFrameNumber == frameNumber) break;
- frameNumber = newFrameNumber;
- dropCounter++;
- }
- #if DEBUG_RENDERER
- if (dropCounter > 0) {
- RENDERER_LOGD("Dropped %d frames on texture layer update", dropCounter);
- }
- #endif
- surfaceTexture->getTransformMatrix(transform);
- GLenum renderTarget = surfaceTexture->getCurrentTextureTarget();
-
- Layer* layer = reinterpret_cast<Layer*>(layerPtr);
- LayerRenderer::updateTextureLayer(layer, width, height, isOpaque, renderTarget, transform);
- }
-}
-
-static void android_view_GLES20Canvas_updateRenderLayer(JNIEnv* env, jobject clazz,
- jlong layerPtr, jlong rendererPtr, jlong displayListPtr,
- jint left, jint top, jint right, jint bottom) {
- Layer* layer = reinterpret_cast<Layer*>(layerPtr);
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
- layer->updateDeferred(renderer, displayList, left, top, right, bottom);
-}
-
-static void android_view_GLES20Canvas_clearLayerTexture(JNIEnv* env, jobject clazz,
- jlong layerPtr) {
- Layer* layer = reinterpret_cast<Layer*>(layerPtr);
- layer->clearTexture();
-}
-
-static void android_view_GLES20Canvas_setTextureLayerTransform(JNIEnv* env, jobject clazz,
- jlong layerPtr, jlong matrixPtr) {
- Layer* layer = reinterpret_cast<Layer*>(layerPtr);
- SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
- layer->getTransform().load(*matrix);
-}
-
-static void android_view_GLES20Canvas_destroyLayer(JNIEnv* env, jobject clazz, jlong layerPtr) {
- Layer* layer = reinterpret_cast<Layer*>(layerPtr);
- LayerRenderer::destroyLayer(layer);
-}
-
-static void android_view_GLES20Canvas_destroyLayerDeferred(JNIEnv* env,
- jobject clazz, jlong layerPtr) {
- Layer* layer = reinterpret_cast<Layer*>(layerPtr);
- LayerRenderer::destroyLayerDeferred(layer);
-}
-
static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
jlong rendererPtr, jlong layerPtr, jfloat x, jfloat y) {
OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
@@ -1222,7 +1072,6 @@
{ "nResetModifiers", "(JI)V", (void*) android_view_GLES20Canvas_resetModifiers },
{ "nSetupShader", "(JJ)V", (void*) android_view_GLES20Canvas_setupShader },
- { "nSetupColorFilter", "(JJ)V", (void*) android_view_GLES20Canvas_setupColorFilter },
{ "nSetupShadow", "(JFFFI)V", (void*) android_view_GLES20Canvas_setupShadow },
{ "nSetupPaintFilter", "(JII)V", (void*) android_view_GLES20Canvas_setupPaintFilter },
@@ -1257,19 +1106,6 @@
{ "nInterrupt", "(J)V", (void*) android_view_GLES20Canvas_interrupt },
{ "nResume", "(J)V", (void*) android_view_GLES20Canvas_resume },
- { "nCreateLayerRenderer", "(J)J", (void*) android_view_GLES20Canvas_createLayerRenderer },
- { "nCreateLayer", "(IIZ[I)J", (void*) android_view_GLES20Canvas_createLayer },
- { "nResizeLayer", "(JII[I)Z" , (void*) android_view_GLES20Canvas_resizeLayer },
- { "nSetLayerPaint", "(JJ)V", (void*) android_view_GLES20Canvas_setLayerPaint },
- { "nSetLayerColorFilter", "(JJ)V", (void*) android_view_GLES20Canvas_setLayerColorFilter },
- { "nSetOpaqueLayer", "(JZ)V", (void*) android_view_GLES20Canvas_setOpaqueLayer },
- { "nCreateTextureLayer", "(Z[I)J", (void*) android_view_GLES20Canvas_createTextureLayer },
- { "nUpdateTextureLayer", "(JIIZLandroid/graphics/SurfaceTexture;)V",
- (void*) android_view_GLES20Canvas_updateTextureLayer },
- { "nUpdateRenderLayer", "(JJJIIII)V", (void*) android_view_GLES20Canvas_updateRenderLayer },
- { "nClearLayerTexture", "(J)V", (void*) android_view_GLES20Canvas_clearLayerTexture },
- { "nDestroyLayer", "(J)V", (void*) android_view_GLES20Canvas_destroyLayer },
- { "nDestroyLayerDeferred", "(J)V", (void*) android_view_GLES20Canvas_destroyLayerDeferred },
{ "nDrawLayer", "(JJFF)V", (void*) android_view_GLES20Canvas_drawLayer },
{ "nCopyLayer", "(JJ)Z", (void*) android_view_GLES20Canvas_copyLayer },
{ "nClearLayerUpdates", "(J)V", (void*) android_view_GLES20Canvas_clearLayerUpdates },
@@ -1277,8 +1113,6 @@
{ "nPushLayerUpdate", "(JJ)V", (void*) android_view_GLES20Canvas_pushLayerUpdate },
{ "nCancelLayerUpdate", "(JJ)V", (void*) android_view_GLES20Canvas_cancelLayerUpdate },
- { "nSetTextureLayerTransform", "(JJ)V", (void*) android_view_GLES20Canvas_setTextureLayerTransform },
-
{ "nGetMaximumTextureWidth", "()I", (void*) android_view_GLES20Canvas_getMaxTextureWidth },
{ "nGetMaximumTextureHeight", "()I", (void*) android_view_GLES20Canvas_getMaxTextureHeight },
diff --git a/core/jni/android_view_HardwareLayer.cpp b/core/jni/android_view_HardwareLayer.cpp
new file mode 100644
index 0000000..8a0a011
--- /dev/null
+++ b/core/jni/android_view_HardwareLayer.cpp
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "OpenGLRenderer"
+
+#include "jni.h"
+#include "GraphicsJNI.h"
+#include <nativehelper/JNIHelp.h>
+
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/android_graphics_SurfaceTexture.h>
+
+#include <gui/GLConsumer.h>
+
+#include <SkBitmap.h>
+#include <SkCanvas.h>
+#include <SkMatrix.h>
+#include <SkPaint.h>
+#include <SkXfermode.h>
+
+#include <DeferredLayerUpdater.h>
+#include <DisplayList.h>
+#include <LayerRenderer.h>
+#include <SkiaShader.h>
+#include <Rect.h>
+
+namespace android {
+
+using namespace uirenderer;
+
+#ifdef USE_OPENGL_RENDERER
+
+static jlong android_view_HardwareLayer_createTextureLayer(JNIEnv* env, jobject clazz) {
+ Layer* layer = LayerRenderer::createTextureLayer();
+ if (!layer) return 0;
+
+ return reinterpret_cast<jlong>( new DeferredLayerUpdater(layer) );
+}
+
+static jlong android_view_HardwareLayer_createRenderLayer(JNIEnv* env, jobject clazz,
+ jint width, jint height) {
+ Layer* layer = LayerRenderer::createRenderLayer(width, height);
+ if (!layer) return 0;
+
+ OpenGLRenderer* renderer = new LayerRenderer(layer);
+ renderer->initProperties();
+ return reinterpret_cast<jlong>( new DeferredLayerUpdater(layer, renderer) );
+}
+
+static void android_view_HardwareLayer_onTextureDestroyed(JNIEnv* env, jobject clazz,
+ jlong layerUpdaterPtr) {
+ DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
+ layer->backingLayer()->clearTexture();
+}
+
+static jlong android_view_HardwareLayer_detachBackingLayer(JNIEnv* env, jobject clazz,
+ jlong layerUpdaterPtr) {
+ DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
+ return reinterpret_cast<jlong>( layer->detachBackingLayer() );
+}
+
+static void android_view_HardwareLayer_destroyLayerUpdater(JNIEnv* env, jobject clazz,
+ jlong layerUpdaterPtr) {
+ DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
+ delete layer;
+}
+
+static jboolean android_view_HardwareLayer_prepare(JNIEnv* env, jobject clazz,
+ jlong layerUpdaterPtr, jint width, jint height, jboolean isOpaque) {
+ DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
+ bool changed = false;
+ changed |= layer->setSize(width, height);
+ changed |= layer->setBlend(!isOpaque);
+ return changed;
+}
+
+static void android_view_HardwareLayer_setLayerPaint(JNIEnv* env, jobject clazz,
+ jlong layerUpdaterPtr, jlong paintPtr, jlong colorFilterPtr) {
+ DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
+ if (layer) {
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
+ SkColorFilter* colorFilter = reinterpret_cast<SkColorFilter*>(colorFilterPtr);
+ layer->setPaint(paint);
+ layer->setColorFilter(colorFilter);
+ }
+}
+
+static void android_view_HardwareLayer_setTransform(JNIEnv* env, jobject clazz,
+ jlong layerUpdaterPtr, jlong matrixPtr) {
+ DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
+ SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
+ layer->setTransform(matrix);
+}
+
+static void android_view_HardwareLayer_setSurfaceTexture(JNIEnv* env, jobject clazz,
+ jlong layerUpdaterPtr, jobject surface, jboolean isAlreadyAttached) {
+ DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
+ sp<GLConsumer> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, surface));
+ layer->setSurfaceTexture(surfaceTexture, !isAlreadyAttached);
+}
+
+static void android_view_HardwareLayer_updateSurfaceTexture(JNIEnv* env, jobject clazz,
+ jlong layerUpdaterPtr) {
+ DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
+ layer->updateTexImage();
+}
+
+static void android_view_HardwareLayer_updateRenderLayer(JNIEnv* env, jobject clazz,
+ jlong layerUpdaterPtr, jlong displayListPtr,
+ jint left, jint top, jint right, jint bottom) {
+ DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
+ DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
+ layer->setDisplayList(displayList, left, top, right, bottom);
+}
+
+static jboolean android_view_HardwareLayer_flushChanges(JNIEnv* env, jobject clazz,
+ jlong layerUpdaterPtr) {
+ DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
+ return layer->apply();
+}
+
+static jlong android_view_HardwareLayer_getLayer(JNIEnv* env, jobject clazz,
+ jlong layerUpdaterPtr) {
+ DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
+ return reinterpret_cast<jlong>( layer->backingLayer() );
+}
+
+static jint android_view_HardwareLayer_getTexName(JNIEnv* env, jobject clazz,
+ jlong layerUpdaterPtr) {
+ DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
+ return layer->backingLayer()->getTexture();
+}
+
+#endif // USE_OPENGL_RENDERER
+
+// ----------------------------------------------------------------------------
+// JNI Glue
+// ----------------------------------------------------------------------------
+
+const char* const kClassPathName = "android/view/HardwareLayer";
+
+static JNINativeMethod gMethods[] = {
+#ifdef USE_OPENGL_RENDERER
+
+ { "nCreateTextureLayer", "()J", (void*) android_view_HardwareLayer_createTextureLayer },
+ { "nCreateRenderLayer", "(II)J", (void*) android_view_HardwareLayer_createRenderLayer },
+ { "nOnTextureDestroyed", "(J)V", (void*) android_view_HardwareLayer_onTextureDestroyed },
+ { "nDetachBackingLayer", "(J)J", (void*) android_view_HardwareLayer_detachBackingLayer },
+ { "nDestroyLayerUpdater", "(J)V", (void*) android_view_HardwareLayer_destroyLayerUpdater },
+
+ { "nPrepare", "(JIIZ)Z", (void*) android_view_HardwareLayer_prepare },
+ { "nSetLayerPaint", "(JJJ)V", (void*) android_view_HardwareLayer_setLayerPaint },
+ { "nSetTransform", "(JJ)V", (void*) android_view_HardwareLayer_setTransform },
+ { "nSetSurfaceTexture", "(JLandroid/graphics/SurfaceTexture;Z)V",
+ (void*) android_view_HardwareLayer_setSurfaceTexture },
+ { "nUpdateSurfaceTexture", "(J)V", (void*) android_view_HardwareLayer_updateSurfaceTexture },
+ { "nUpdateRenderLayer", "(JJIIII)V", (void*) android_view_HardwareLayer_updateRenderLayer },
+
+ { "nFlushChanges", "(J)Z", (void*) android_view_HardwareLayer_flushChanges },
+
+ { "nGetLayer", "(J)J", (void*) android_view_HardwareLayer_getLayer },
+ { "nGetTexName", "(J)I", (void*) android_view_HardwareLayer_getTexName },
+#endif
+};
+
+int register_android_view_HardwareLayer(JNIEnv* env) {
+ return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
+}
+
+};
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 8e121de..e86a2d4 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -131,6 +131,13 @@
proxy->detachFunctor(functor);
}
+static void android_view_ThreadedRenderer_runWithGlContext(JNIEnv* env, jobject clazz,
+ jlong proxyPtr, jobject jrunnable) {
+ RenderProxy* proxy = reinterpret_cast<RenderProxy*>( proxyPtr);
+ RenderTask* task = new JavaTask(env, jrunnable);
+ proxy->runWithGlContext(task);
+}
+
#endif
// ----------------------------------------------------------------------------
@@ -151,6 +158,7 @@
{ "nDestroyCanvas", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvas},
{ "nAttachFunctor", "(JJ)V", (void*) android_view_ThreadedRenderer_attachFunctor},
{ "nDetachFunctor", "(JJ)V", (void*) android_view_ThreadedRenderer_detachFunctor},
+ { "nRunWithGlContext", "(JLjava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_runWithGlContext },
#endif
};
diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
index a0982bd..3035d15 100644
--- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
@@ -50,36 +50,41 @@
static inline EGLDisplay getDisplay(JNIEnv* env, jobject o) {
if (!o) return EGL_NO_DISPLAY;
- return (EGLDisplay)env->GetIntField(o, gDisplay_EGLDisplayFieldID);
+ return (EGLDisplay)env->GetLongField(o, gDisplay_EGLDisplayFieldID);
}
static inline EGLSurface getSurface(JNIEnv* env, jobject o) {
if (!o) return EGL_NO_SURFACE;
- return (EGLSurface)env->GetIntField(o, gSurface_EGLSurfaceFieldID);
+ return (EGLSurface)env->GetLongField(o, gSurface_EGLSurfaceFieldID);
}
static inline EGLContext getContext(JNIEnv* env, jobject o) {
if (!o) return EGL_NO_CONTEXT;
- return (EGLContext)env->GetIntField(o, gContext_EGLContextFieldID);
+ return (EGLContext)env->GetLongField(o, gContext_EGLContextFieldID);
}
static inline EGLConfig getConfig(JNIEnv* env, jobject o) {
if (!o) return 0;
- return (EGLConfig)env->GetIntField(o, gConfig_EGLConfigFieldID);
+ return (EGLConfig)env->GetLongField(o, gConfig_EGLConfigFieldID);
}
+
+static inline jboolean EglBoolToJBool(EGLBoolean eglBool) {
+ return eglBool == EGL_TRUE ? JNI_TRUE : JNI_FALSE;
+}
+
static void nativeClassInit(JNIEnv *_env, jclass eglImplClass)
{
jclass config_class = _env->FindClass("com/google/android/gles_jni/EGLConfigImpl");
gConfig_class = (jclass) _env->NewGlobalRef(config_class);
- gConfig_ctorID = _env->GetMethodID(gConfig_class, "<init>", "(I)V");
- gConfig_EGLConfigFieldID = _env->GetFieldID(gConfig_class, "mEGLConfig", "I");
+ gConfig_ctorID = _env->GetMethodID(gConfig_class, "<init>", "(J)V");
+ gConfig_EGLConfigFieldID = _env->GetFieldID(gConfig_class, "mEGLConfig", "J");
jclass display_class = _env->FindClass("com/google/android/gles_jni/EGLDisplayImpl");
- gDisplay_EGLDisplayFieldID = _env->GetFieldID(display_class, "mEGLDisplay", "I");
+ gDisplay_EGLDisplayFieldID = _env->GetFieldID(display_class, "mEGLDisplay", "J");
jclass context_class = _env->FindClass("com/google/android/gles_jni/EGLContextImpl");
- gContext_EGLContextFieldID = _env->GetFieldID(context_class, "mEGLContext", "I");
+ gContext_EGLContextFieldID = _env->GetFieldID(context_class, "mEGLContext", "J");
jclass surface_class = _env->FindClass("com/google/android/gles_jni/EGLSurfaceImpl");
- gSurface_EGLSurfaceFieldID = _env->GetFieldID(surface_class, "mEGLSurface", "I");
- gSurface_NativePixelRefFieldID = _env->GetFieldID(surface_class, "mNativePixelRef", "I");
+ gSurface_EGLSurfaceFieldID = _env->GetFieldID(surface_class, "mEGLSurface", "J");
+ gSurface_NativePixelRefFieldID = _env->GetFieldID(surface_class, "mNativePixelRef", "J");
jclass bitmap_class = _env->FindClass("android/graphics/Bitmap");
gBitmap_NativeBitmapFieldID = _env->GetFieldID(bitmap_class, "mNativeBitmap", "J");
@@ -123,7 +128,7 @@
}
EGLDisplay dpy = getDisplay(_env, display);
- jboolean success = eglInitialize(dpy, NULL, NULL);
+ EGLBoolean success = eglInitialize(dpy, NULL, NULL);
if (success && major_minor) {
int len = _env->GetArrayLength(major_minor);
if (len) {
@@ -134,7 +139,7 @@
_env->ReleasePrimitiveArrayCritical(major_minor, base, JNI_ABORT);
}
}
- return success;
+ return EglBoolToJBool(success);
}
static jboolean jni_eglQueryContext(JNIEnv *_env, jobject _this, jobject display,
@@ -146,14 +151,14 @@
}
EGLDisplay dpy = getDisplay(_env, display);
EGLContext ctx = getContext(_env, context);
- jboolean success = JNI_FALSE;
+ EGLBoolean success = EGL_FALSE;
int len = _env->GetArrayLength(value);
if (len) {
jint* base = (jint *)_env->GetPrimitiveArrayCritical(value, (jboolean *)0);
success = eglQueryContext(dpy, ctx, attribute, base);
_env->ReleasePrimitiveArrayCritical(value, base, JNI_ABORT);
}
- return success;
+ return EglBoolToJBool(success);
}
static jboolean jni_eglQuerySurface(JNIEnv *_env, jobject _this, jobject display,
@@ -166,14 +171,14 @@
EGLDisplay dpy = getDisplay(_env, display);
EGLContext sur = getSurface(_env, surface);
- jboolean success = JNI_FALSE;
+ EGLBoolean success = EGL_FALSE;
int len = _env->GetArrayLength(value);
if (len) {
jint* base = (jint *)_env->GetPrimitiveArrayCritical(value, (jboolean *)0);
success = eglQuerySurface(dpy, sur, attribute, base);
_env->ReleasePrimitiveArrayCritical(value, base, JNI_ABORT);
}
- return success;
+ return EglBoolToJBool(success);
}
static jint jni_getInitCount(JNIEnv *_env, jobject _clazz, jobject display) {
@@ -183,7 +188,7 @@
}
static jboolean jni_eglReleaseThread(JNIEnv *_env, jobject _this) {
- return eglReleaseThread();
+ return EglBoolToJBool(eglReleaseThread());
}
static jboolean jni_eglChooseConfig(JNIEnv *_env, jobject _this, jobject display,
@@ -196,7 +201,7 @@
return JNI_FALSE;
}
EGLDisplay dpy = getDisplay(_env, display);
- jboolean success = JNI_FALSE;
+ EGLBoolean success = EGL_FALSE;
if (configs == NULL) {
config_size = 0;
@@ -214,14 +219,14 @@
if (success && configs!=NULL) {
for (int i=0 ; i<num ; i++) {
- jobject obj = _env->NewObject(gConfig_class, gConfig_ctorID, (jint)nativeConfigs[i]);
+ jobject obj = _env->NewObject(gConfig_class, gConfig_ctorID, reinterpret_cast<jlong>(nativeConfigs[i]));
_env->SetObjectArrayElement(configs, i, obj);
}
}
- return success;
+ return EglBoolToJBool(success);
}
-static jint jni_eglCreateContext(JNIEnv *_env, jobject _this, jobject display,
+static jlong jni_eglCreateContext(JNIEnv *_env, jobject _this, jobject display,
jobject config, jobject share_context, jintArray attrib_list) {
if (display == NULL || config == NULL || share_context == NULL
|| !validAttribList(_env, attrib_list)) {
@@ -234,10 +239,10 @@
jint* base = beginNativeAttribList(_env, attrib_list);
EGLContext ctx = eglCreateContext(dpy, cnf, shr, base);
endNativeAttributeList(_env, attrib_list, base);
- return (jint)ctx;
+ return reinterpret_cast<jlong>(ctx);
}
-static jint jni_eglCreatePbufferSurface(JNIEnv *_env, jobject _this, jobject display,
+static jlong jni_eglCreatePbufferSurface(JNIEnv *_env, jobject _this, jobject display,
jobject config, jintArray attrib_list) {
if (display == NULL || config == NULL
|| !validAttribList(_env, attrib_list)) {
@@ -249,7 +254,7 @@
jint* base = beginNativeAttribList(_env, attrib_list);
EGLSurface sur = eglCreatePbufferSurface(dpy, cnf, base);
endNativeAttributeList(_env, attrib_list, base);
- return (jint)sur;
+ return reinterpret_cast<jlong>(sur);
}
static PixelFormat convertPixelFormat(SkBitmap::Config format)
@@ -300,15 +305,15 @@
endNativeAttributeList(_env, attrib_list, base);
if (sur != EGL_NO_SURFACE) {
- _env->SetIntField(out_sur, gSurface_EGLSurfaceFieldID, (int)sur);
- _env->SetIntField(out_sur, gSurface_NativePixelRefFieldID, (int)ref);
+ _env->SetLongField(out_sur, gSurface_EGLSurfaceFieldID, reinterpret_cast<jlong>(sur));
+ _env->SetLongField(out_sur, gSurface_NativePixelRefFieldID, reinterpret_cast<jlong>(ref));
} else {
ref->unlockPixels();
SkSafeUnref(ref);
}
}
-static jint jni_eglCreateWindowSurface(JNIEnv *_env, jobject _this, jobject display,
+static jlong jni_eglCreateWindowSurface(JNIEnv *_env, jobject _this, jobject display,
jobject config, jobject native_window, jintArray attrib_list) {
if (display == NULL || config == NULL
|| !validAttribList(_env, attrib_list)) {
@@ -332,15 +337,15 @@
jint* base = beginNativeAttribList(_env, attrib_list);
EGLSurface sur = eglCreateWindowSurface(dpy, cnf, window.get(), base);
endNativeAttributeList(_env, attrib_list, base);
- return (jint)sur;
+ return reinterpret_cast<jlong>(sur);
}
-static jint jni_eglCreateWindowSurfaceTexture(JNIEnv *_env, jobject _this, jobject display,
+static jlong jni_eglCreateWindowSurfaceTexture(JNIEnv *_env, jobject _this, jobject display,
jobject config, jobject native_window, jintArray attrib_list) {
if (display == NULL || config == NULL
|| !validAttribList(_env, attrib_list)) {
jniThrowException(_env, "java/lang/IllegalArgumentException", NULL);
- return JNI_FALSE;
+ return 0;
}
EGLDisplay dpy = getDisplay(_env, display);
EGLContext cnf = getConfig(_env, config);
@@ -360,7 +365,7 @@
jint* base = beginNativeAttribList(_env, attrib_list);
EGLSurface sur = eglCreateWindowSurface(dpy, cnf, window.get(), base);
endNativeAttributeList(_env, attrib_list, base);
- return (jint)sur;
+ return reinterpret_cast<jlong>(sur);
}
static jboolean jni_eglGetConfigAttrib(JNIEnv *_env, jobject _this, jobject display,
@@ -372,13 +377,13 @@
}
EGLDisplay dpy = getDisplay(_env, display);
EGLContext cnf = getConfig(_env, config);
- jboolean success = JNI_FALSE;
+ EGLBoolean success = EGL_FALSE;
jint localValue;
success = eglGetConfigAttrib(dpy, cnf, attribute, &localValue);
if (success) {
_env->SetIntArrayRegion(value, 0, 1, &localValue);
}
- return success;
+ return EglBoolToJBool(success);
}
static jboolean jni_eglGetConfigs(JNIEnv *_env, jobject _this, jobject display,
@@ -389,7 +394,7 @@
return JNI_FALSE;
}
EGLDisplay dpy = getDisplay(_env, display);
- jboolean success = JNI_FALSE;
+ EGLBoolean success = EGL_FALSE;
if (configs == NULL) {
config_size = 0;
}
@@ -401,11 +406,11 @@
}
if (success && configs) {
for (int i=0 ; i<num ; i++) {
- jobject obj = _env->NewObject(gConfig_class, gConfig_ctorID, (jint)nativeConfigs[i]);
+ jobject obj = _env->NewObject(gConfig_class, gConfig_ctorID, reinterpret_cast<jlong>(nativeConfigs[i]));
_env->SetObjectArrayElement(configs, i, obj);
}
}
- return success;
+ return EglBoolToJBool(success);
}
static jint jni_eglGetError(JNIEnv *_env, jobject _this) {
@@ -413,20 +418,20 @@
return error;
}
-static jint jni_eglGetCurrentContext(JNIEnv *_env, jobject _this) {
- return (jint)eglGetCurrentContext();
+static jlong jni_eglGetCurrentContext(JNIEnv *_env, jobject _this) {
+ return reinterpret_cast<jlong>(eglGetCurrentContext());
}
-static jint jni_eglGetCurrentDisplay(JNIEnv *_env, jobject _this) {
- return (jint)eglGetCurrentDisplay();
+static jlong jni_eglGetCurrentDisplay(JNIEnv *_env, jobject _this) {
+ return reinterpret_cast<jlong>(eglGetCurrentDisplay());
}
-static jint jni_eglGetCurrentSurface(JNIEnv *_env, jobject _this, jint readdraw) {
+static jlong jni_eglGetCurrentSurface(JNIEnv *_env, jobject _this, jint readdraw) {
if ((readdraw != EGL_READ) && (readdraw != EGL_DRAW)) {
jniThrowException(_env, "java/lang/IllegalArgumentException", NULL);
return 0;
}
- return (jint)eglGetCurrentSurface(readdraw);
+ return reinterpret_cast<jlong>(eglGetCurrentSurface(readdraw));
}
static jboolean jni_eglDestroyContext(JNIEnv *_env, jobject _this, jobject display, jobject context) {
@@ -436,7 +441,7 @@
}
EGLDisplay dpy = getDisplay(_env, display);
EGLContext ctx = getContext(_env, context);
- return eglDestroyContext(dpy, ctx);
+ return EglBoolToJBool(eglDestroyContext(dpy, ctx));
}
static jboolean jni_eglDestroySurface(JNIEnv *_env, jobject _this, jobject display, jobject surface) {
@@ -448,18 +453,18 @@
EGLSurface sur = getSurface(_env, surface);
if (sur) {
- SkPixelRef* ref = (SkPixelRef*)(_env->GetIntField(surface,
+ SkPixelRef* ref = (SkPixelRef*)(_env->GetLongField(surface,
gSurface_NativePixelRefFieldID));
if (ref) {
ref->unlockPixels();
SkSafeUnref(ref);
}
}
- return eglDestroySurface(dpy, sur);
+ return EglBoolToJBool(eglDestroySurface(dpy, sur));
}
-static jint jni_eglGetDisplay(JNIEnv *_env, jobject _this, jobject native_display) {
- return (jint)eglGetDisplay(EGL_DEFAULT_DISPLAY);
+static jlong jni_eglGetDisplay(JNIEnv *_env, jobject _this, jobject native_display) {
+ return reinterpret_cast<jlong>(eglGetDisplay(EGL_DEFAULT_DISPLAY));
}
static jboolean jni_eglMakeCurrent(JNIEnv *_env, jobject _this, jobject display, jobject draw, jobject read, jobject context) {
@@ -471,7 +476,7 @@
EGLSurface sdr = getSurface(_env, draw);
EGLSurface srd = getSurface(_env, read);
EGLContext ctx = getContext(_env, context);
- return eglMakeCurrent(dpy, sdr, srd, ctx);
+ return EglBoolToJBool(eglMakeCurrent(dpy, sdr, srd, ctx));
}
static jstring jni_eglQueryString(JNIEnv *_env, jobject _this, jobject display, jint name) {
@@ -491,7 +496,7 @@
}
EGLDisplay dpy = getDisplay(_env, display);
EGLSurface sur = getSurface(_env, surface);
- return eglSwapBuffers(dpy, sur);
+ return EglBoolToJBool(eglSwapBuffers(dpy, sur));
}
static jboolean jni_eglTerminate(JNIEnv *_env, jobject _this, jobject display) {
@@ -500,7 +505,7 @@
return JNI_FALSE;
}
EGLDisplay dpy = getDisplay(_env, display);
- return eglTerminate(dpy);
+ return EglBoolToJBool(eglTerminate(dpy));
}
static jboolean jni_eglCopyBuffers(JNIEnv *_env, jobject _this, jobject display,
@@ -514,11 +519,11 @@
}
static jboolean jni_eglWaitGL(JNIEnv *_env, jobject _this) {
- return eglWaitGL();
+ return EglBoolToJBool(eglWaitGL());
}
static jboolean jni_eglWaitNative(JNIEnv *_env, jobject _this, jint engine, jobject bindTarget) {
- return eglWaitNative(engine);
+ return EglBoolToJBool(eglWaitNative(engine));
}
@@ -540,21 +545,21 @@
{"eglReleaseThread","()Z", (void*)jni_eglReleaseThread },
{"getInitCount", "(" DISPLAY ")I", (void*)jni_getInitCount },
{"eglChooseConfig", "(" DISPLAY "[I[" CONFIG "I[I)Z", (void*)jni_eglChooseConfig },
-{"_eglCreateContext","(" DISPLAY CONFIG CONTEXT "[I)I", (void*)jni_eglCreateContext },
+{"_eglCreateContext","(" DISPLAY CONFIG CONTEXT "[I)J", (void*)jni_eglCreateContext },
{"eglGetConfigs", "(" DISPLAY "[" CONFIG "I[I)Z", (void*)jni_eglGetConfigs },
{"eglTerminate", "(" DISPLAY ")Z", (void*)jni_eglTerminate },
{"eglCopyBuffers", "(" DISPLAY SURFACE OBJECT ")Z", (void*)jni_eglCopyBuffers },
{"eglWaitNative", "(I" OBJECT ")Z", (void*)jni_eglWaitNative },
{"eglGetError", "()I", (void*)jni_eglGetError },
{"eglGetConfigAttrib", "(" DISPLAY CONFIG "I[I)Z", (void*)jni_eglGetConfigAttrib },
-{"_eglGetDisplay", "(" OBJECT ")I", (void*)jni_eglGetDisplay },
-{"_eglGetCurrentContext", "()I", (void*)jni_eglGetCurrentContext },
-{"_eglGetCurrentDisplay", "()I", (void*)jni_eglGetCurrentDisplay },
-{"_eglGetCurrentSurface", "(I)I", (void*)jni_eglGetCurrentSurface },
-{"_eglCreatePbufferSurface","(" DISPLAY CONFIG "[I)I", (void*)jni_eglCreatePbufferSurface },
+{"_eglGetDisplay", "(" OBJECT ")J", (void*)jni_eglGetDisplay },
+{"_eglGetCurrentContext", "()J", (void*)jni_eglGetCurrentContext },
+{"_eglGetCurrentDisplay", "()J", (void*)jni_eglGetCurrentDisplay },
+{"_eglGetCurrentSurface", "(I)J", (void*)jni_eglGetCurrentSurface },
+{"_eglCreatePbufferSurface","(" DISPLAY CONFIG "[I)J", (void*)jni_eglCreatePbufferSurface },
{"_eglCreatePixmapSurface", "(" SURFACE DISPLAY CONFIG OBJECT "[I)V", (void*)jni_eglCreatePixmapSurface },
-{"_eglCreateWindowSurface", "(" DISPLAY CONFIG OBJECT "[I)I", (void*)jni_eglCreateWindowSurface },
-{"_eglCreateWindowSurfaceTexture", "(" DISPLAY CONFIG OBJECT "[I)I", (void*)jni_eglCreateWindowSurfaceTexture },
+{"_eglCreateWindowSurface", "(" DISPLAY CONFIG OBJECT "[I)J", (void*)jni_eglCreateWindowSurface },
+{"_eglCreateWindowSurfaceTexture", "(" DISPLAY CONFIG OBJECT "[I)J", (void*)jni_eglCreateWindowSurfaceTexture },
{"eglDestroyContext", "(" DISPLAY CONTEXT ")Z", (void*)jni_eglDestroyContext },
{"eglDestroySurface", "(" DISPLAY SURFACE ")Z", (void*)jni_eglDestroySurface },
{"eglMakeCurrent", "(" DISPLAY SURFACE SURFACE CONTEXT")Z", (void*)jni_eglMakeCurrent },
diff --git a/docs/html/distribute/googleplay/spotlight/index.jd b/docs/html/distribute/googleplay/spotlight/index.jd
index b501f20..6f92c78b 100644
--- a/docs/html/distribute/googleplay/spotlight/index.jd
+++ b/docs/html/distribute/googleplay/spotlight/index.jd
@@ -7,6 +7,34 @@
<p>Android developers, their apps, and their successes with Android and Google Play. </p>
+<div id="Kiwi" style="background: #F0F0F0;
+ border-top: 1px solid #DDD;
+ padding: 0px 0 24px 0;
+ overflow: auto;
+ clear:both;
+ margin-bottom:40px;
+ margin-top:30px;">
+ <div style="padding:0 0 0 29px;">
+ <h4>Developer Story: Kiwi, Inc.</h4>
+ <img alt="" class="screenshot thumbnail" style="-webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ border-radius: 5px height:78px;
+ width: 78px;
+ float: left;
+ margin: 17px 20px 9px 0;"
+ src="//lh4.ggpht.com/qUI-8MJy70l4qoVBR_sx-56ckR_m0R_ZXcJ1DiTYUR3R_owWzsCFTYkAk4p5DMnaSdY3=w124" >
+ <div style="width:700px;">
+ <p style="margin-top:26px;
+ margin-bottom:12px;">
+ Android-first developer <a href="//play.google.com/store/apps/developer?id=Kiwi,+Inc." target="_android">Kiwi, Inc.</a> has five of the top 25 grossing games on Google Play, including <a href="https://play.google.com/store/apps/details?id=com.kiwi.shipwrecked" target="_android">Shipwrecked: Lost Island</a>, <a href="https://play.google.com/store/apps/details?id=com.kiwi.monsterpark" target="_android">Monsterama Park</a>, and <a href="https://play.google.com/store/apps/details?id=com.kiwi.mysteryestate" target="_android">Hidden Object: Mystery Estate</a>. Hear how Google Play helped them double revenue every six months with features like instant updates, staged rollouts, and more.</p>
+ </div>
+ <iframe style="float:left;
+ margin-right:24px;
+ margin-top:14px;" width="700" height="394" src=
+ "http://www.youtube.com/embed/WWArLD6nqrk?HD=1;rel=0;origin=developer.android.com;" frameborder="0" allowfullscreen>
+ </iframe>
+ </div>
+</div>
<div style="background: #F0F0F0;
border-top: 1px solid #DDD;
padding: 0px 0 24px 0;
diff --git a/docs/html/google/gcm/client.jd b/docs/html/google/gcm/client.jd
index 916ecee..ac446dc 100644
--- a/docs/html/google/gcm/client.jd
+++ b/docs/html/google/gcm/client.jd
@@ -75,7 +75,7 @@
{@code dependency} section of your application's {@code build.gradle} file:</p>
<pre>dependencies {
- compile: "com.google.android.gms:play-services:3.1.+"
+ compile "com.google.android.gms:play-services:3.1.+"
}
</pre>
diff --git a/docs/html/google/gcm/gs.jd b/docs/html/google/gcm/gs.jd
index d2e65d4..4cfe1bc 100644
--- a/docs/html/google/gcm/gs.jd
+++ b/docs/html/google/gcm/gs.jd
@@ -64,14 +64,10 @@
<li>Under <strong>Public API access</strong>, click <strong>Create new key</strong>.</li>
-<li>In the <strong>Create a new key</strong> dialog, click <strong>Android key</strong>.</li>
+<li>In the <strong>Create a new key</strong> dialog, click <strong>Server key</strong>.</li>
-<li>In the resulting configuration dialog, supply one SHA1 fingerprint and
-the package name for your app, separated by a semicolon. For example,
-{@code 45:B5:E4:6F:36:AD:0A:98:94:B4:02:66:2B:12:17:F2:56:26:A0:E0;com.myexample}.
-<p>To get the value for the SHA1 fingerprint, follow the instructions in the
-<a href="http://developers.google.com/console/help/new/#installedapplications">console
-help</a>.</p></li>
+<li>In the resulting configuration dialog, supply your server's IP address. For testing
+purposes, you can use {@code 0.0.0.0/0}.</p></li>
<li>Click <strong>Create</strong>.</li>
<li>In the refreshed page, copy the
@@ -102,4 +98,3 @@
<li>Write your client app. This is the GCM-enabled Android application that runs
on a device. See <a href="client.html">Implementing GCM Client</a> for more information.</li>
</ol>
-
diff --git a/docs/html/google/gcm/server.jd b/docs/html/google/gcm/server.jd
index 7ba1bd5..ccd1267 100644
--- a/docs/html/google/gcm/server.jd
+++ b/docs/html/google/gcm/server.jd
@@ -120,7 +120,6 @@
<li>Able to store the API key and client registration IDs. The
API key is included in the header of POST requests that send
messages.</li>
- <li>Able to store the API key and client registration IDs.</li>
<li>Able to generate message IDs to uniquely identify each message it sends.</li>
</ul>
diff --git a/docs/html/images/video-kiwi.jpg b/docs/html/images/video-kiwi.jpg
new file mode 100644
index 0000000..1c1146c
--- /dev/null
+++ b/docs/html/images/video-kiwi.jpg
Binary files differ
diff --git a/docs/html/index.jd b/docs/html/index.jd
index 191e0fb..d976c1e 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -18,6 +18,52 @@
<!-- set explicit widths as needed to prevent overflow issues -->
<li class="item carousel-home">
+ <div class="content-left col-11" style="padding-top:65px;">
+ <script src="//ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
+ <div style="box-shadow: 3px 10px 18px 1px #999;width:600px;height:336px">
+ <div id="ytapiplayer">
+ <a href="http://www.youtube.com/watch?v=WWArLD6nqrk"><img width=600 src="{@docRoot}images/video-kiwi.jpg"></a><!--You need Flash player 8+ and JavaScript enabled to view this video. -->
+ </div>
+ <script type="text/javascript">
+ var params = { allowScriptAccess: "always" };
+ var atts = { id: "ytapiplayer" };
+ swfobject.embedSWF("//www.youtube.com/v/WWArLD6nqrk?enablejsapi=1&playerapiid=ytplayer&version=3&HD=1;rel=0;showinfo=0;modestbranding;origin=developer.android.com;autohide=1",
+ "ytapiplayer", "600", "336", "8", null, null, params, atts);
+
+ // Callback used to pause/resume carousel based on video state
+ function onytplayerStateChange(newState) {
+ var isPaused = $("#pauseButton").hasClass("paused");
+ if ((newState == 1) || (newState == 3)) {
+ // if playing or buffering, pause the carousel
+ if (!isPaused) {
+ $("#pauseButton").click();
+ }
+ } else {
+ // otherwise, make sure carousel is running
+ if (isPaused) {
+ $("#pauseButton").click();
+ }
+ }
+ }
+
+ // Callback received when YouTube player loads to setup callback (above)
+ function onYouTubePlayerReady(playerId) {
+ var ytplayer = document.getElementById("ytapiplayer");
+ ytplayer.addEventListener("onStateChange", "onytplayerStateChange");
+ }
+
+ </script>
+ </div>
+ </div>
+ <div class="content-right col-4">
+ <h1 style="white-space:nowrap;line-height:1.2em;">Developer Story: <br />Kiwi, Inc.</h1>
+ <p>Game developer Kiwi has five of the top 25 grossing titles on Google Play. Hear how Google Play
+ has helped them double revenue every six months.</p>
+ <p><a href="{@docRoot}distribute/googleplay/spotlight/index.html" class="button">Watch more videos </a></p>
+ </div>
+ </li>
+
+ <li class="item carousel-home">
<div class="content-left col-7" style="width:400px;">
<a href="{@docRoot}about/versions/kitkat.html">
<img src="{@docRoot}images/home/kk-hero.jpg" width="242" style="padding-top:72px;">
diff --git a/docs/html/training/animation/screen-slide.jd b/docs/html/training/animation/screen-slide.jd
index 07d779f..a68d475 100644
--- a/docs/html/training/animation/screen-slide.jd
+++ b/docs/html/training/animation/screen-slide.jd
@@ -63,22 +63,23 @@
contains a text view to display some text:
<pre>
-<com.example.android.animationsdemo.ScrollView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/content"
+<!-- fragment_screen_slide_page.xml -->
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/content"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent" >
- <TextView style="?android:textAppearanceMedium"
- android:padding="16dp"
- android:lineSpacingMultiplier="1.2"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/lorem_ipsum" />
-
-</com.example.android.animationsdemo.ScrollView>
+ <TextView style="?android:textAppearanceMedium"
+ android:padding="16dp"
+ android:lineSpacingMultiplier="1.2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/lorem_ipsum" />
+</ScrollView>
</pre>
+ <p>Define also a string for the contents of the fragment.</p>
+
<h2 id="fragment">Create the Fragment</h2>
<p>Create a {@link android.support.v4.app.Fragment} class that returns the layout
that you just created in the {@link android.app.Fragment#onCreateView onCreateView()}
@@ -87,6 +88,8 @@
<pre>
+import android.support.v4.app.Fragment;
+...
public class ScreenSlidePageFragment extends Fragment {
@Override
@@ -111,6 +114,7 @@
<p>To begin, create a layout that contains a {@link android.support.v4.view.ViewPager}:</p>
<pre>
+<!-- activity_screen_slide.xml -->
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
@@ -133,6 +137,9 @@
</ul>
<pre>
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+...
public class ScreenSlidePagerActivity extends FragmentActivity {
/**
* The number of pages (wizard steps) to show in this demo.
@@ -153,11 +160,11 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_screen_slide_pager);
+ setContentView(R.layout.activity_screen_slide);
// Instantiate a ViewPager and a PagerAdapter.
mPager = (ViewPager) findViewById(R.id.pager);
- mPagerAdapter = new ScreenSlidePagerAdapter(getFragmentManager());
+ mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
}
@@ -224,9 +231,9 @@
<code>ZoomOutPageTransformer</code>, you can set your custom animations
like this:</p>
<pre>
-ViewPager pager = (ViewPager) findViewById(R.id.pager);
+ViewPager mPager = (ViewPager) findViewById(R.id.pager);
...
-pager.setPageTransformer(true, new ZoomOutPageTransformer());
+mPager.setPageTransformer(true, new ZoomOutPageTransformer());
</pre>
@@ -257,8 +264,8 @@
<pre>
public class ZoomOutPageTransformer implements ViewPager.PageTransformer {
- private static float MIN_SCALE = 0.85f;
- private static float MIN_ALPHA = 0.5f;
+ private static final float MIN_SCALE = 0.85f;
+ private static final float MIN_ALPHA = 0.5f;
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
@@ -332,7 +339,7 @@
<pre>
public class DepthPageTransformer implements ViewPager.PageTransformer {
- private static float MIN_SCALE = 0.75f;
+ private static final float MIN_SCALE = 0.75f;
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
diff --git a/graphics/java/android/graphics/ColorFilter.java b/graphics/java/android/graphics/ColorFilter.java
index d3c1974..4838aa0 100644
--- a/graphics/java/android/graphics/ColorFilter.java
+++ b/graphics/java/android/graphics/ColorFilter.java
@@ -27,24 +27,21 @@
* never be used directly.
*/
public class ColorFilter {
- // Holds the pointer to the native SkColorFilter instance
- long native_instance;
-
/**
- * Holds the pointer to the native SkiaColorFilter instance, from libhwui.
+ * Holds the pointer to the native SkColorFilter instance.
*
* @hide
*/
- public long nativeColorFilter;
+ public long native_instance;
@Override
protected void finalize() throws Throwable {
try {
super.finalize();
} finally {
- destroyFilter(native_instance, nativeColorFilter);
+ destroyFilter(native_instance);
}
}
- static native void destroyFilter(long native_instance, long nativeColorFilter);
+ static native void destroyFilter(long native_instance);
}
diff --git a/graphics/java/android/graphics/ColorMatrixColorFilter.java b/graphics/java/android/graphics/ColorMatrixColorFilter.java
index 3f7331d..7822c41 100644
--- a/graphics/java/android/graphics/ColorMatrixColorFilter.java
+++ b/graphics/java/android/graphics/ColorMatrixColorFilter.java
@@ -114,11 +114,9 @@
private void update() {
final float[] colorMatrix = mMatrix.getArray();
- destroyFilter(native_instance, nativeColorFilter);
+ destroyFilter(native_instance);
native_instance = nativeColorMatrixFilter(colorMatrix);
- nativeColorFilter = nColorMatrixFilter(native_instance, colorMatrix);
}
private static native long nativeColorMatrixFilter(float[] array);
- private static native long nColorMatrixFilter(long nativeFilter, float[] array);
}
diff --git a/graphics/java/android/graphics/LightingColorFilter.java b/graphics/java/android/graphics/LightingColorFilter.java
index 5829edf..70a3fe8 100644
--- a/graphics/java/android/graphics/LightingColorFilter.java
+++ b/graphics/java/android/graphics/LightingColorFilter.java
@@ -99,11 +99,9 @@
}
private void update() {
- destroyFilter(native_instance, nativeColorFilter);
+ destroyFilter(native_instance);
native_instance = native_CreateLightingFilter(mMul, mAdd);
- nativeColorFilter = nCreateLightingFilter(native_instance, mMul, mAdd);
}
private static native long native_CreateLightingFilter(int mul, int add);
- private static native long nCreateLightingFilter(long nativeFilter, int mul, int add);
}
diff --git a/graphics/java/android/graphics/PorterDuffColorFilter.java b/graphics/java/android/graphics/PorterDuffColorFilter.java
index 93fc1c7..c078c1c 100644
--- a/graphics/java/android/graphics/PorterDuffColorFilter.java
+++ b/graphics/java/android/graphics/PorterDuffColorFilter.java
@@ -91,12 +91,9 @@
}
private void update() {
- destroyFilter(native_instance, nativeColorFilter);
+ destroyFilter(native_instance);
native_instance = native_CreatePorterDuffFilter(mColor, mMode.nativeInt);
- nativeColorFilter = nCreatePorterDuffFilter(native_instance, mColor, mMode.nativeInt);
}
private static native long native_CreatePorterDuffFilter(int srcColor, int porterDuffMode);
- private static native long nCreatePorterDuffFilter(long nativeFilter, int srcColor,
- int porterDuffMode);
}
diff --git a/graphics/java/android/graphics/pdf/PdfDocument.java b/graphics/java/android/graphics/pdf/PdfDocument.java
index 29d14a2..f5b07c1 100644
--- a/graphics/java/android/graphics/pdf/PdfDocument.java
+++ b/graphics/java/android/graphics/pdf/PdfDocument.java
@@ -82,7 +82,7 @@
private final List<PageInfo> mPages = new ArrayList<PageInfo>();
- private int mNativeDocument;
+ private long mNativeDocument;
private Page mCurrentPage;
@@ -235,20 +235,20 @@
}
}
- private native int nativeCreateDocument();
+ private native long nativeCreateDocument();
- private native void nativeClose(int document);
+ private native void nativeClose(long nativeDocument);
- private native void nativeFinishPage(int document);
+ private native void nativeFinishPage(long nativeDocument);
- private native void nativeWriteTo(int document, OutputStream out, byte[] chunk);
+ private native void nativeWriteTo(long nativeDocument, OutputStream out, byte[] chunk);
- private static native int nativeStartPage(int documentPtr, int pageWidth, int pageHeight,
+ private static native long nativeStartPage(long nativeDocument, int pageWidth, int pageHeight,
int contentLeft, int contentTop, int contentRight, int contentBottom);
private final class PdfCanvas extends Canvas {
- public PdfCanvas(int nativeCanvas) {
+ public PdfCanvas(long nativeCanvas) {
super(nativeCanvas);
}
diff --git a/include/androidfw/PowerManager.h b/include/androidfw/PowerManager.h
deleted file mode 100644
index ba98db0..0000000
--- a/include/androidfw/PowerManager.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _ANDROIDFW_POWER_MANAGER_H
-#define _ANDROIDFW_POWER_MANAGER_H
-
-
-namespace android {
-
-enum {
- USER_ACTIVITY_EVENT_OTHER = 0,
- USER_ACTIVITY_EVENT_BUTTON = 1,
- USER_ACTIVITY_EVENT_TOUCH = 2,
-
- USER_ACTIVITY_EVENT_LAST = USER_ACTIVITY_EVENT_TOUCH, // Last valid event code.
-};
-
-} // namespace android
-
-#endif // _ANDROIDFW_POWER_MANAGER_H
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 6799766..610465e 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -808,6 +808,19 @@
uint32_t lastPublicKey;
};
+// The most specific locale can consist of:
+//
+// - a 3 char language code
+// - a 3 char region code prefixed by a 'r'
+// - a 4 char script code prefixed by a 's'
+// - a 8 char variant code prefixed by a 'v'
+//
+// each separated by a single char separator, which sums up to a total of 24
+// chars, (25 include the string terminator) rounded up to 28 to be 4 byte
+// aligned.
+#define RESTABLE_MAX_LOCALE_LEN 28
+
+
/**
* Describes a particular resource configuration.
*/
@@ -828,10 +841,42 @@
union {
struct {
- // \0\0 means "any". Otherwise, en, fr, etc.
+ // This field can take three different forms:
+ // - \0\0 means "any".
+ //
+ // - Two 7 bit ascii values interpreted as ISO-639-1 language
+ // codes ('fr', 'en' etc. etc.). The high bit for both bytes is
+ // zero.
+ //
+ // - A single 16 bit little endian packed value representing an
+ // ISO-639-2 3 letter language code. This will be of the form:
+ //
+ // {1, t, t, t, t, t, s, s, s, s, s, f, f, f, f, f}
+ //
+ // bit[0, 4] = first letter of the language code
+ // bit[5, 9] = second letter of the language code
+ // bit[10, 14] = third letter of the language code.
+ // bit[15] = 1 always
+ //
+ // For backwards compatibility, languages that have unambiguous
+ // two letter codes are represented in that format.
+ //
+ // The layout is always bigendian irrespective of the runtime
+ // architecture.
char language[2];
- // \0\0 means "any". Otherwise, US, CA, etc.
+ // This field can take three different forms:
+ // - \0\0 means "any".
+ //
+ // - Two 7 bit ascii values interpreted as 2 letter region
+ // codes ('US', 'GB' etc.). The high bit for both bytes is zero.
+ //
+ // - An UN M.49 3 digit region code. For simplicity, these are packed
+ // in the same manner as the language codes, though we should need
+ // only 10 bits to represent them, instead of the 15.
+ //
+ // The layout is always bigendian irrespective of the runtime
+ // architecture.
char country[2];
};
uint32_t locale;
@@ -933,7 +978,7 @@
SDKVERSION_ANY = 0
};
- enum {
+ enum {
MINORVERSION_ANY = 0
};
@@ -1006,6 +1051,15 @@
uint32_t screenSizeDp;
};
+ // The ISO-15924 short name for the script corresponding to this
+ // configuration. (eg. Hant, Latn, etc.). Interpreted in conjunction with
+ // the locale field.
+ char localeScript[4];
+
+ // A single BCP-47 variant subtag. Will vary in length between 5 and 8
+ // chars. Interpreted in conjunction with the locale field.
+ char localeVariant[8];
+
void copyFromDeviceNoSwap(const ResTable_config& o);
void copyFromDtoH(const ResTable_config& o);
@@ -1063,7 +1117,46 @@
// settings is the requested settings
bool match(const ResTable_config& settings) const;
- void getLocale(char str[6]) const;
+ // Get the string representation of the locale component of this
+ // Config. The maximum size of this representation will be
+ // |RESTABLE_MAX_LOCALE_LEN| (including a terminating '\0').
+ //
+ // Example: en-US, en-Latn-US, en-POSIX.
+ void getBcp47Locale(char* out) const;
+
+ // Sets the values of language, region, script and variant to the
+ // well formed BCP-47 locale contained in |in|. The input locale is
+ // assumed to be valid and no validation is performed.
+ void setBcp47Locale(const char* in);
+
+ inline void clearLocale() {
+ locale = 0;
+ memset(localeScript, 0, sizeof(localeScript));
+ memset(localeVariant, 0, sizeof(localeVariant));
+ }
+
+ // Get the 2 or 3 letter language code of this configuration. Trailing
+ // bytes are set to '\0'.
+ size_t unpackLanguage(char language[4]) const;
+ // Get the 2 or 3 letter language code of this configuration. Trailing
+ // bytes are set to '\0'.
+ size_t unpackRegion(char region[4]) const;
+
+ // Sets the language code of this configuration to the first three
+ // chars at |language|.
+ //
+ // If |language| is a 2 letter code, the trailing byte must be '\0' or
+ // the BCP-47 separator '-'.
+ void packLanguage(const char* language);
+ // Sets the region code of this configuration to the first three bytes
+ // at |region|. If |region| is a 2 letter code, the trailing byte must be '\0'
+ // or the BCP-47 separator '-'.
+ void packRegion(const char* region);
+
+ // Returns a positive integer if this config is more specific than |o|
+ // with respect to their locales, a negative integer if |o| is more specific
+ // and 0 if they're equally specific.
+ int isLocaleMoreSpecificThan(const ResTable_config &o) const;
String8 toString() const;
};
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 501b83e..9cea68c 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -463,17 +463,8 @@
if (locale) {
setLocaleLocked(locale);
} else if (config.language[0] != 0) {
- char spec[9];
- spec[0] = config.language[0];
- spec[1] = config.language[1];
- if (config.country[0] != 0) {
- spec[2] = '_';
- spec[3] = config.country[0];
- spec[4] = config.country[1];
- spec[5] = 0;
- } else {
- spec[3] = 0;
- }
+ char spec[RESTABLE_MAX_LOCALE_LEN];
+ config.getBcp47Locale(spec);
setLocaleLocked(spec);
} else {
updateResourceParamsLocked();
@@ -733,20 +724,11 @@
return;
}
- size_t llen = mLocale ? strlen(mLocale) : 0;
- mConfig->language[0] = 0;
- mConfig->language[1] = 0;
- mConfig->country[0] = 0;
- mConfig->country[1] = 0;
- if (llen >= 2) {
- mConfig->language[0] = mLocale[0];
- mConfig->language[1] = mLocale[1];
+ if (mLocale) {
+ mConfig->setBcp47Locale(mLocale);
+ } else {
+ mConfig->clearLocale();
}
- if (llen >= 5) {
- mConfig->country[0] = mLocale[3];
- mConfig->country[1] = mLocale[4];
- }
- mConfig->size = sizeof(*mConfig);
res->setParameters(mConfig);
}
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 72d331c..94d150a 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -66,11 +66,6 @@
// size measured in sizeof(uint32_t)
#define IDMAP_HEADER_SIZE (ResTable::IDMAP_HEADER_SIZE_BYTES / sizeof(uint32_t))
-static void printToLogFunc(int32_t cookie, const char* txt)
-{
- ALOGV("[cookie=%d] %s", cookie, txt);
-}
-
// Standard C isspace() is only required to look at the low byte of its input, so
// produces incorrect results for UTF-16 characters. For safety's sake, assume that
// any high-byte UTF-16 code point is not whitespace.
@@ -1539,6 +1534,71 @@
}
}
+/* static */ size_t unpackLanguageOrRegion(const char in[2], const char base,
+ char out[4]) {
+ if (in[0] & 0x80) {
+ // The high bit is "1", which means this is a packed three letter
+ // language code.
+
+ // The smallest 5 bits of the second char are the first alphabet.
+ const uint8_t first = in[1] & 0x1f;
+ // The last three bits of the second char and the first two bits
+ // of the first char are the second alphabet.
+ const uint8_t second = ((in[1] & 0xe0) >> 5) + ((in[0] & 0x03) << 3);
+ // Bits 3 to 7 (inclusive) of the first char are the third alphabet.
+ const uint8_t third = (in[0] & 0x7c) >> 2;
+
+ out[0] = first + base;
+ out[1] = second + base;
+ out[2] = third + base;
+ out[3] = 0;
+
+ return 3;
+ }
+
+ if (in[0]) {
+ memcpy(out, in, 2);
+ memset(out + 2, 0, 2);
+ return 2;
+ }
+
+ memset(out, 0, 4);
+ return 0;
+}
+
+/* static */ void packLanguageOrRegion(const char* in, const char base,
+ char out[2]) {
+ if (in[2] == 0 || in[2] == '-') {
+ out[0] = in[0];
+ out[1] = in[1];
+ } else {
+ uint8_t first = (in[0] - base) & 0x00ef;
+ uint8_t second = (in[1] - base) & 0x00ef;
+ uint8_t third = (in[2] - base) & 0x00ef;
+
+ out[0] = (0x80 | (third << 2) | (second >> 3));
+ out[1] = ((second << 5) | first);
+ }
+}
+
+
+void ResTable_config::packLanguage(const char* language) {
+ packLanguageOrRegion(language, 'a', this->language);
+}
+
+void ResTable_config::packRegion(const char* region) {
+ packLanguageOrRegion(region, '0', this->country);
+}
+
+size_t ResTable_config::unpackLanguage(char language[4]) const {
+ return unpackLanguageOrRegion(this->language, 'a', language);
+}
+
+size_t ResTable_config::unpackRegion(char region[4]) const {
+ return unpackLanguageOrRegion(this->country, '0', region);
+}
+
+
void ResTable_config::copyFromDtoH(const ResTable_config& o) {
copyFromDeviceNoSwap(o);
size = sizeof(ResTable_config);
@@ -1568,10 +1628,30 @@
screenHeightDp = htods(screenHeightDp);
}
+/* static */ inline int compareLocales(const ResTable_config &l, const ResTable_config &r) {
+ if (l.locale != r.locale) {
+ // NOTE: This is the old behaviour with respect to comparison orders.
+ // The diff value here doesn't make much sense (given our bit packing scheme)
+ // but it's stable, and that's all we need.
+ return l.locale - r.locale;
+ }
+
+ // The language & region are equal, so compare the scripts and variants.
+ int script = memcmp(l.localeScript, r.localeScript, sizeof(l.localeScript));
+ if (script) {
+ return script;
+ }
+
+ // The language, region and script are equal, so compare variants.
+ //
+ // This should happen very infrequently (if at all.)
+ return memcmp(l.localeVariant, r.localeVariant, sizeof(l.localeVariant));
+}
+
int ResTable_config::compare(const ResTable_config& o) const {
int32_t diff = (int32_t)(imsi - o.imsi);
if (diff != 0) return diff;
- diff = (int32_t)(locale - o.locale);
+ diff = compareLocales(*this, o);
if (diff != 0) return diff;
diff = (int32_t)(screenType - o.screenType);
if (diff != 0) return diff;
@@ -1598,18 +1678,15 @@
if (mnc != o.mnc) {
return mnc < o.mnc ? -1 : 1;
}
- if (language[0] != o.language[0]) {
- return language[0] < o.language[0] ? -1 : 1;
+
+ int diff = compareLocales(*this, o);
+ if (diff < 0) {
+ return -1;
}
- if (language[1] != o.language[1]) {
- return language[1] < o.language[1] ? -1 : 1;
+ if (diff > 0) {
+ return 1;
}
- if (country[0] != o.country[0]) {
- return country[0] < o.country[0] ? -1 : 1;
- }
- if (country[1] != o.country[1]) {
- return country[1] < o.country[1] ? -1 : 1;
- }
+
if ((screenLayout & MASK_LAYOUTDIR) != (o.screenLayout & MASK_LAYOUTDIR)) {
return (screenLayout & MASK_LAYOUTDIR) < (o.screenLayout & MASK_LAYOUTDIR) ? -1 : 1;
}
@@ -1656,7 +1733,6 @@
int diffs = 0;
if (mcc != o.mcc) diffs |= CONFIG_MCC;
if (mnc != o.mnc) diffs |= CONFIG_MNC;
- if (locale != o.locale) diffs |= CONFIG_LOCALE;
if (orientation != o.orientation) diffs |= CONFIG_ORIENTATION;
if (density != o.density) diffs |= CONFIG_DENSITY;
if (touchscreen != o.touchscreen) diffs |= CONFIG_TOUCHSCREEN;
@@ -1671,9 +1747,44 @@
if (uiMode != o.uiMode) diffs |= CONFIG_UI_MODE;
if (smallestScreenWidthDp != o.smallestScreenWidthDp) diffs |= CONFIG_SMALLEST_SCREEN_SIZE;
if (screenSizeDp != o.screenSizeDp) diffs |= CONFIG_SCREEN_SIZE;
+
+ const int diff = compareLocales(*this, o);
+ if (diff) diffs |= CONFIG_LOCALE;
+
return diffs;
}
+int ResTable_config::isLocaleMoreSpecificThan(const ResTable_config& o) const {
+ if (locale || o.locale) {
+ if (language[0] != o.language[0]) {
+ if (!language[0]) return -1;
+ if (!o.language[0]) return 1;
+ }
+
+ if (country[0] != o.country[0]) {
+ if (!country[0]) return -1;
+ if (!o.country[0]) return 1;
+ }
+ }
+
+ // There isn't a well specified "importance" order between variants and
+ // scripts. We can't easily tell whether, say "en-Latn-US" is more or less
+ // specific than "en-US-POSIX".
+ //
+ // We therefore arbitrarily decide to give priority to variants over
+ // scripts since it seems more useful to do so. We will consider
+ // "en-US-POSIX" to be more specific than "en-Latn-US".
+
+ const int score = ((localeScript[0] != 0) ? 1 : 0) +
+ ((localeVariant[0] != 0) ? 2 : 0);
+
+ const int oScore = ((o.localeScript[0] != 0) ? 1 : 0) +
+ ((o.localeVariant[0] != 0) ? 2 : 0);
+
+ return score - oScore;
+
+}
+
bool ResTable_config::isMoreSpecificThan(const ResTable_config& o) const {
// The order of the following tests defines the importance of one
// configuration parameter over another. Those tests first are more
@@ -1691,14 +1802,13 @@
}
if (locale || o.locale) {
- if (language[0] != o.language[0]) {
- if (!language[0]) return false;
- if (!o.language[0]) return true;
+ const int diff = isLocaleMoreSpecificThan(o);
+ if (diff < 0) {
+ return false;
}
- if (country[0] != o.country[0]) {
- if (!country[0]) return false;
- if (!o.country[0]) return true;
+ if (diff > 0) {
+ return true;
}
}
@@ -1834,6 +1944,18 @@
}
}
+ if (localeScript[0] || o.localeScript[0]) {
+ if (localeScript[0] != o.localeScript[0] && requested->localeScript[0]) {
+ return localeScript[0];
+ }
+ }
+
+ if (localeVariant[0] || o.localeVariant[0]) {
+ if (localeVariant[0] != o.localeVariant[0] && requested->localeVariant[0]) {
+ return localeVariant[0];
+ }
+ }
+
if (screenLayout || o.screenLayout) {
if (((screenLayout^o.screenLayout) & MASK_LAYOUTDIR) != 0
&& (requested->screenLayout & MASK_LAYOUTDIR)) {
@@ -2054,17 +2176,23 @@
}
}
if (locale != 0) {
+ // Don't consider the script & variants when deciding matches.
+ //
+ // If we two configs differ only in their script or language, they
+ // can be weeded out in the isMoreSpecificThan test.
if (language[0] != 0
&& (language[0] != settings.language[0]
|| language[1] != settings.language[1])) {
return false;
}
+
if (country[0] != 0
&& (country[0] != settings.country[0]
|| country[1] != settings.country[1])) {
return false;
}
}
+
if (screenConfig != 0) {
const int layoutDir = screenLayout&MASK_LAYOUTDIR;
const int setLayoutDir = settings.screenLayout&MASK_LAYOUTDIR;
@@ -2166,17 +2294,92 @@
return true;
}
-void ResTable_config::getLocale(char str[6]) const {
- memset(str, 0, 6);
- if (language[0]) {
- str[0] = language[0];
- str[1] = language[1];
- if (country[0]) {
- str[2] = '_';
- str[3] = country[0];
- str[4] = country[1];
- }
+void ResTable_config::getBcp47Locale(char str[RESTABLE_MAX_LOCALE_LEN]) const {
+ memset(str, 0, RESTABLE_MAX_LOCALE_LEN);
+
+ // This represents the "any" locale value, which has traditionally been
+ // represented by the empty string.
+ if (!language[0] && !country[0]) {
+ return;
}
+
+ size_t charsWritten = 0;
+ if (language[0]) {
+ charsWritten += unpackLanguage(str);
+ }
+
+ if (localeScript[0]) {
+ if (charsWritten) {
+ str[charsWritten++] = '-';
+ }
+ memcpy(str + charsWritten, localeScript, sizeof(localeScript));
+ charsWritten += sizeof(localeScript);
+ }
+
+ if (country[0]) {
+ if (charsWritten) {
+ str[charsWritten++] = '-';
+ }
+ charsWritten += unpackRegion(str + charsWritten);
+ }
+
+ if (localeVariant[0]) {
+ if (charsWritten) {
+ str[charsWritten++] = '-';
+ }
+ memcpy(str + charsWritten, localeVariant, sizeof(localeVariant));
+ }
+}
+
+/* static */ inline bool assignLocaleComponent(ResTable_config* config,
+ const char* start, size_t size) {
+
+ switch (size) {
+ case 0:
+ return false;
+ case 2:
+ case 3:
+ config->language[0] ? config->packRegion(start) : config->packLanguage(start);
+ break;
+ case 4:
+ config->localeScript[0] = toupper(start[0]);
+ for (size_t i = 1; i < 4; ++i) {
+ config->localeScript[i] = tolower(start[i]);
+ }
+ break;
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ for (size_t i = 0; i < size; ++i) {
+ config->localeVariant[i] = tolower(start[i]);
+ }
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+void ResTable_config::setBcp47Locale(const char* in) {
+ locale = 0;
+ memset(localeScript, 0, sizeof(localeScript));
+ memset(localeVariant, 0, sizeof(localeVariant));
+
+ const char* separator = in;
+ const char* start = in;
+ while ((separator = strchr(start, '-')) != NULL) {
+ const size_t size = separator - start;
+ if (!assignLocaleComponent(this, start, size)) {
+ fprintf(stderr, "Invalid BCP-47 locale string: %s", in);
+ }
+
+ start = (separator + 1);
+ }
+
+ const size_t size = in + strlen(in) - start;
+ assignLocaleComponent(this, start, size);
}
String8 ResTable_config::toString() const {
@@ -2190,14 +2393,10 @@
if (res.size() > 0) res.append("-");
res.appendFormat("%dmnc", dtohs(mnc));
}
- if (language[0] != 0) {
- if (res.size() > 0) res.append("-");
- res.append(language, 2);
- }
- if (country[0] != 0) {
- if (res.size() > 0) res.append("-");
- res.append(country, 2);
- }
+ char localeStr[RESTABLE_MAX_LOCALE_LEN];
+ getBcp47Locale(localeStr);
+ res.append(localeStr);
+
if ((screenLayout&MASK_LAYOUTDIR) != 0) {
if (res.size() > 0) res.append("-");
switch (screenLayout&ResTable_config::MASK_LAYOUTDIR) {
@@ -4950,18 +5149,20 @@
const size_t L = type->configs.size();
for (size_t l=0; l<L; l++) {
const ResTable_type* config = type->configs[l];
- const ResTable_config* cfg = &config->config;
+ ResTable_config cfg;
+ memset(&cfg, 0, sizeof(ResTable_config));
+ cfg.copyFromDtoH(config->config);
// only insert unique
const size_t M = configs->size();
size_t m;
for (m=0; m<M; m++) {
- if (0 == (*configs)[m].compare(*cfg)) {
+ if (0 == (*configs)[m].compare(cfg)) {
break;
}
}
// if we didn't find it
if (m == M) {
- configs->add(*cfg);
+ configs->add(cfg);
}
}
}
@@ -4976,9 +5177,10 @@
getConfigurations(&configs);
ALOGV("called getConfigurations size=%d", (int)configs.size());
const size_t I = configs.size();
+
+ char locale[RESTABLE_MAX_LOCALE_LEN];
for (size_t i=0; i<I; i++) {
- char locale[6];
- configs[i].getLocale(locale);
+ configs[i].getBcp47Locale(locale);
const size_t J = locales->size();
size_t j;
for (j=0; j<J; j++) {
@@ -5601,9 +5803,9 @@
printf("mError=0x%x (%s)\n", mError, strerror(mError));
}
#if 0
- printf("mParams=%c%c-%c%c,\n",
- mParams.language[0], mParams.language[1],
- mParams.country[0], mParams.country[1]);
+ char localeStr[RESTABLE_MAX_LOCALE_LEN];
+ mParams.getBcp47Locale(localeStr);
+ printf("mParams=%s,\n" localeStr);
#endif
size_t pgCount = mPackageGroups.size();
printf("Package Groups (%d)\n", (int)pgCount);
@@ -5732,7 +5934,7 @@
continue;
}
- uint16_t esize = dtohs(ent->size);
+ uintptr_t esize = dtohs(ent->size);
if ((esize&0x3) != 0) {
printf("NON-INTEGER ResTable_entry SIZE: %p\n", (void*)esize);
continue;
diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk
index 6e6522c..9e9649c 100644
--- a/libs/androidfw/tests/Android.mk
+++ b/libs/androidfw/tests/Android.mk
@@ -6,7 +6,8 @@
test_src_files := \
BackupData_test.cpp \
ObbFile_test.cpp \
- ZipUtils_test.cpp
+ ZipUtils_test.cpp \
+ ResourceTypes_test.cpp
shared_libraries := \
libandroidfw \
diff --git a/libs/androidfw/tests/ResourceTypes_test.cpp b/libs/androidfw/tests/ResourceTypes_test.cpp
new file mode 100644
index 0000000..4888b4a
--- /dev/null
+++ b/libs/androidfw/tests/ResourceTypes_test.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <androidfw/ResourceTypes.h>
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+#include <gtest/gtest.h>
+namespace android {
+
+TEST(ResourceTypesTest, ResourceConfig_packAndUnpack2LetterLanguage) {
+ ResTable_config config;
+ config.packLanguage("en");
+
+ EXPECT_EQ('e', config.language[0]);
+ EXPECT_EQ('n', config.language[1]);
+
+ char out[4] = { 1, 1, 1, 1};
+ config.unpackLanguage(out);
+ EXPECT_EQ('e', out[0]);
+ EXPECT_EQ('n', out[1]);
+ EXPECT_EQ(0, out[2]);
+ EXPECT_EQ(0, out[3]);
+
+ memset(out, 1, sizeof(out));
+ config.locale = 0;
+ config.unpackLanguage(out);
+ EXPECT_EQ(0, out[0]);
+ EXPECT_EQ(0, out[1]);
+ EXPECT_EQ(0, out[2]);
+ EXPECT_EQ(0, out[3]);
+}
+
+TEST(ResourceTypesTest, ResourceConfig_packAndUnpack2LetterRegion) {
+ ResTable_config config;
+ config.packRegion("US");
+
+ EXPECT_EQ('U', config.country[0]);
+ EXPECT_EQ('S', config.country[1]);
+
+ char out[4] = { 1, 1, 1, 1};
+ config.unpackRegion(out);
+ EXPECT_EQ('U', out[0]);
+ EXPECT_EQ('S', out[1]);
+ EXPECT_EQ(0, out[2]);
+ EXPECT_EQ(0, out[3]);
+}
+
+TEST(ResourceTypesTest, ResourceConfig_packAndUnpack3LetterLanguage) {
+ ResTable_config config;
+ config.packLanguage("eng");
+
+ // 1-00110-01 101-00100
+ EXPECT_EQ(0x99, config.language[0]);
+ EXPECT_EQ(0xa4, config.language[1]);
+
+ char out[4] = { 1, 1, 1, 1};
+ config.unpackLanguage(out);
+ EXPECT_EQ('e', out[0]);
+ EXPECT_EQ('n', out[1]);
+ EXPECT_EQ('g', out[2]);
+ EXPECT_EQ(0, out[3]);
+}
+
+TEST(ResourceTypesTest, ResourceConfig_packAndUnpack3LetterRegion) {
+ ResTable_config config;
+ config.packRegion("419");
+
+ char out[4] = { 1, 1, 1, 1};
+ config.unpackRegion(out);
+
+ EXPECT_EQ('4', out[0]);
+ EXPECT_EQ('1', out[1]);
+ EXPECT_EQ('9', out[2]);
+}
+
+/* static */ void fillIn(const char* lang, const char* country,
+ const char* script, const char* variant, ResTable_config* out) {
+ memset(out, 0, sizeof(ResTable_config));
+ if (lang != NULL) {
+ out->packLanguage(lang);
+ }
+
+ if (country != NULL) {
+ out->packRegion(country);
+ }
+
+ if (script != NULL) {
+ memcpy(out->localeScript, script, 4);
+ }
+
+ if (variant != NULL) {
+ memcpy(out->localeVariant, variant, strlen(variant));
+ }
+}
+
+TEST(ResourceTypesTest, IsMoreSpecificThan) {
+ ResTable_config l;
+ ResTable_config r;
+
+ fillIn("en", NULL, NULL, NULL, &l);
+ fillIn(NULL, NULL, NULL, NULL, &r);
+
+ EXPECT_TRUE(l.isMoreSpecificThan(r));
+ EXPECT_FALSE(r.isMoreSpecificThan(l));
+
+ fillIn("eng", NULL, NULL, NULL, &l);
+ EXPECT_TRUE(l.isMoreSpecificThan(r));
+ EXPECT_FALSE(r.isMoreSpecificThan(l));
+
+ fillIn("eng", "419", NULL, NULL, &r);
+ EXPECT_FALSE(l.isMoreSpecificThan(r));
+ EXPECT_TRUE(r.isMoreSpecificThan(l));
+
+ fillIn("en", NULL, NULL, NULL, &l);
+ fillIn("en", "US", NULL, NULL, &r);
+ EXPECT_FALSE(l.isMoreSpecificThan(r));
+ EXPECT_TRUE(r.isMoreSpecificThan(l));
+
+ fillIn("en", "US", NULL, NULL, &l);
+ fillIn("en", "US", "Latn", NULL, &r);
+ EXPECT_FALSE(l.isMoreSpecificThan(r));
+ EXPECT_TRUE(r.isMoreSpecificThan(l));
+
+ fillIn("en", "US", NULL, NULL, &l);
+ fillIn("en", "US", NULL, "POSIX", &r);
+ EXPECT_FALSE(l.isMoreSpecificThan(r));
+ EXPECT_TRUE(r.isMoreSpecificThan(l));
+
+ fillIn("en", "US", "Latn", NULL, &l);
+ fillIn("en", "US", NULL, "POSIX", &r);
+ EXPECT_FALSE(l.isMoreSpecificThan(r));
+ EXPECT_TRUE(r.isMoreSpecificThan(l));
+}
+
+TEST(ResourceTypesTest, setLocale) {
+ ResTable_config test;
+ test.setBcp47Locale("en-US");
+ EXPECT_EQ('e', test.language[0]);
+ EXPECT_EQ('n', test.language[1]);
+ EXPECT_EQ('U', test.country[0]);
+ EXPECT_EQ('S', test.country[1]);
+ EXPECT_EQ(0, test.localeScript[0]);
+ EXPECT_EQ(0, test.localeVariant[0]);
+
+ test.setBcp47Locale("eng-419");
+ char out[4] = { 1, 1, 1, 1};
+ test.unpackLanguage(out);
+ EXPECT_EQ('e', out[0]);
+ EXPECT_EQ('n', out[1]);
+ EXPECT_EQ('g', out[2]);
+ EXPECT_EQ(0, out[3]);
+ memset(out, 1, 4);
+ test.unpackRegion(out);
+ EXPECT_EQ('4', out[0]);
+ EXPECT_EQ('1', out[1]);
+ EXPECT_EQ('9', out[2]);
+
+
+ test.setBcp47Locale("en-Latn-419");
+ memset(out, 1, 4);
+ EXPECT_EQ('e', test.language[0]);
+ EXPECT_EQ('n', test.language[1]);
+
+ EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4));
+ test.unpackRegion(out);
+ EXPECT_EQ('4', out[0]);
+ EXPECT_EQ('1', out[1]);
+ EXPECT_EQ('9', out[2]);
+}
+
+} // namespace android.
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index e4648f6..495ad19 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -17,6 +17,7 @@
Caches.cpp \
DisplayList.cpp \
DeferredDisplayList.cpp \
+ DeferredLayerUpdater.cpp \
DisplayListLogBuffer.cpp \
DisplayListRenderer.cpp \
Dither.cpp \
@@ -39,7 +40,6 @@
RenderBufferCache.cpp \
ResourceCache.cpp \
ShadowTessellator.cpp \
- SkiaColorFilter.cpp \
SkiaShader.cpp \
Snapshot.cpp \
SpotShadow.cpp \
@@ -71,7 +71,7 @@
LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER -DEGL_EGLEXT_PROTOTYPES -DGL_GLEXT_PROTOTYPES
LOCAL_CFLAGS += -Wno-unused-parameter
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
- LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libEGL libGLESv2 libskia libui
+ LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libEGL libGLESv2 libskia libui libgui
LOCAL_MODULE := libhwui
LOCAL_MODULE_TAGS := optional
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index 7eb7028..3d58964 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -224,6 +224,11 @@
if (op->getPaintAlpha() != mOps[0].op->getPaintAlpha()) return false;
+ if (op->mPaint && mOps[0].op->mPaint &&
+ op->mPaint->getColorFilter() != mOps[0].op->mPaint->getColorFilter()) {
+ return false;
+ }
+
/* Draw Modifiers compatibility check
*
* Shadows are ignored, as only text uses them, and in that case they are drawn
@@ -239,7 +244,6 @@
const DrawModifiers& lhsMod = lhs->mDrawModifiers;
const DrawModifiers& rhsMod = rhs->mDrawModifiers;
if (lhsMod.mShader != rhsMod.mShader) return false;
- if (lhsMod.mColorFilter != rhsMod.mColorFilter) return false;
// Draw filter testing expects bit fields to be clear if filter not set.
if (lhsMod.mHasDrawFilter != rhsMod.mHasDrawFilter) return false;
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
new file mode 100644
index 0000000..ed05d04
--- /dev/null
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "DeferredLayerUpdater.h"
+
+#include "OpenGLRenderer.h"
+
+#include "LayerRenderer.h"
+
+namespace android {
+namespace uirenderer {
+
+DeferredLayerUpdater::DeferredLayerUpdater(Layer* layer, OpenGLRenderer* renderer)
+ : mDisplayList(0)
+ , mSurfaceTexture(0)
+ , mTransform(0)
+ , mNeedsGLContextAttach(false)
+ , mUpdateTexImage(false)
+ , mLayer(layer)
+ , mRenderer(renderer)
+ , mCaches(Caches::getInstance()) {
+ mCaches.resourceCache.incrementRefcount(mLayer);
+ mWidth = mLayer->layer.getWidth();
+ mHeight = mLayer->layer.getHeight();
+ mBlend = mLayer->isBlend();
+ mColorFilter = mLayer->getColorFilter();
+ mAlpha = mLayer->getAlpha();
+ mMode = mLayer->getMode();
+ mDirtyRect.setEmpty();
+}
+
+DeferredLayerUpdater::~DeferredLayerUpdater() {
+ setColorFilter(NULL);
+ if (mLayer) {
+ mCaches.resourceCache.decrementRefcount(mLayer);
+ }
+ delete mRenderer;
+}
+
+void DeferredLayerUpdater::setColorFilter(SkColorFilter* colorFilter) {
+ SkRefCnt_SafeAssign(mColorFilter, colorFilter);
+}
+
+void DeferredLayerUpdater::setDisplayList(DisplayList* displayList,
+ int left, int top, int right, int bottom) {
+ mDisplayList = displayList;
+ if (mDirtyRect.isEmpty()) {
+ mDirtyRect.set(left, top, right, bottom);
+ } else {
+ mDirtyRect.unionWith(Rect(left, top, right, bottom));
+ }
+}
+
+bool DeferredLayerUpdater::apply() {
+ bool success = true;
+ // These properties are applied the same to both layer types
+ mLayer->setColorFilter(mColorFilter);
+ mLayer->setAlpha(mAlpha, mMode);
+
+ if (mDisplayList) {
+ if (mWidth != mLayer->layer.getWidth() || mHeight != mLayer->layer.getHeight()) {
+ success = LayerRenderer::resizeLayer(mLayer, mWidth, mHeight);
+ }
+ mLayer->setBlend(mBlend);
+ mLayer->updateDeferred(mRenderer, mDisplayList,
+ mDirtyRect.left, mDirtyRect.top, mDirtyRect.right, mDirtyRect.bottom);
+ mDirtyRect.setEmpty();
+ mDisplayList = 0;
+ } else if (mSurfaceTexture.get()) {
+ if (mNeedsGLContextAttach) {
+ mNeedsGLContextAttach = false;
+ mSurfaceTexture->attachToContext(mLayer->getTexture());
+ }
+ if (mUpdateTexImage) {
+ mUpdateTexImage = false;
+ doUpdateTexImage();
+ }
+ if (mTransform) {
+ mLayer->getTransform().load(*mTransform);
+ setTransform(0);
+ }
+ }
+ return success;
+}
+
+void DeferredLayerUpdater::doUpdateTexImage() {
+ if (mSurfaceTexture->updateTexImage() == NO_ERROR) {
+ float transform[16];
+
+ int64_t frameNumber = mSurfaceTexture->getFrameNumber();
+ // If the GLConsumer queue is in synchronous mode, need to discard all
+ // but latest frame, using the frame number to tell when we no longer
+ // have newer frames to target. Since we can't tell which mode it is in,
+ // do this unconditionally.
+ int dropCounter = 0;
+ while (mSurfaceTexture->updateTexImage() == NO_ERROR) {
+ int64_t newFrameNumber = mSurfaceTexture->getFrameNumber();
+ if (newFrameNumber == frameNumber) break;
+ frameNumber = newFrameNumber;
+ dropCounter++;
+ }
+ #if DEBUG_RENDERER
+ if (dropCounter > 0) {
+ RENDERER_LOGD("Dropped %d frames on texture layer update", dropCounter);
+ }
+ #endif
+ mSurfaceTexture->getTransformMatrix(transform);
+ GLenum renderTarget = mSurfaceTexture->getCurrentTextureTarget();
+
+ LayerRenderer::updateTextureLayer(mLayer, mWidth, mHeight, !mBlend,
+ renderTarget, transform);
+ }
+}
+
+void DeferredLayerUpdater::applyDeferred(DeferredLayerUpdater* deferredApply) {
+ // Default assignment operator doesn't quite work, and fails due to mCaches anyway
+ deferredApply->mWidth = mWidth;
+ deferredApply->mHeight = mHeight;
+ deferredApply->mBlend = mBlend;
+ deferredApply->mAlpha = mAlpha;
+ deferredApply->mMode = mMode;
+ deferredApply->mDirtyRect.set(mDirtyRect);
+ deferredApply->mDisplayList = mDisplayList;
+ deferredApply->mSurfaceTexture = mSurfaceTexture;
+ deferredApply->mNeedsGLContextAttach = mNeedsGLContextAttach;
+ deferredApply->mUpdateTexImage = mUpdateTexImage;
+ deferredApply->setColorFilter(mColorFilter);
+ deferredApply->setTransform(mTransform);
+
+ mDisplayList = 0;
+ mDirtyRect.setEmpty();
+ mTransform = 0;
+ mNeedsGLContextAttach = false;
+ mUpdateTexImage = false;
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
new file mode 100644
index 0000000..0350eef
--- /dev/null
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef DEFERREDLAYERUPDATE_H_
+#define DEFERREDLAYERUPDATE_H_
+
+#include <cutils/compiler.h>
+#include <gui/GLConsumer.h>
+#include <SkColorFilter.h>
+#include <SkMatrix.h>
+#include <utils/StrongPointer.h>
+
+#include "DisplayList.h"
+#include "Layer.h"
+#include "OpenGLRenderer.h"
+#include "Rect.h"
+
+namespace android {
+namespace uirenderer {
+
+// Container to hold the properties a layer should be set to at the start
+// of a render pass
+class DeferredLayerUpdater {
+public:
+ ANDROID_API DeferredLayerUpdater(Layer* layer, OpenGLRenderer* renderer = 0);
+ ANDROID_API ~DeferredLayerUpdater();
+
+ ANDROID_API bool setSize(uint32_t width, uint32_t height) {
+ if (mWidth != width || mHeight != height) {
+ mWidth = width;
+ mHeight = height;
+ return true;
+ }
+ return false;
+ }
+
+ ANDROID_API bool setBlend(bool blend) {
+ if (blend != mBlend) {
+ mBlend = blend;
+ return true;
+ }
+ return false;
+ }
+
+ ANDROID_API void setSurfaceTexture(const sp<GLConsumer>& texture, bool needsAttach) {
+ if (texture.get() != mSurfaceTexture.get()) {
+ mNeedsGLContextAttach = needsAttach;
+ mSurfaceTexture = texture;
+ }
+ }
+
+ ANDROID_API void updateTexImage() {
+ mUpdateTexImage = true;
+ }
+
+ ANDROID_API void setTransform(const SkMatrix* matrix) {
+ delete mTransform;
+ mTransform = matrix ? new SkMatrix(*matrix) : 0;
+ }
+
+ ANDROID_API void setDisplayList(DisplayList* displayList,
+ int left, int top, int right, int bottom);
+
+ ANDROID_API void setPaint(const SkPaint* paint) {
+ OpenGLRenderer::getAlphaAndModeDirect(paint, &mAlpha, &mMode);
+ }
+
+ ANDROID_API void setColorFilter(SkColorFilter* colorFilter);
+
+ ANDROID_API bool apply();
+ ANDROID_API void applyDeferred(DeferredLayerUpdater* deferredApply);
+
+ ANDROID_API Layer* backingLayer() {
+ return mLayer;
+ }
+
+ ANDROID_API Layer* detachBackingLayer() {
+ Layer* layer = mLayer;
+ mLayer = 0;
+ return layer;
+ }
+
+private:
+ // Generic properties
+ uint32_t mWidth;
+ uint32_t mHeight;
+ bool mBlend;
+ SkColorFilter* mColorFilter;
+ int mAlpha;
+ SkXfermode::Mode mMode;
+
+ // Layer type specific properties
+ // displayList and surfaceTexture are mutually exclusive, only 1 may be set
+ // dirtyRect is only valid if displayList is set
+ DisplayList* mDisplayList;
+ Rect mDirtyRect;
+ sp<GLConsumer> mSurfaceTexture;
+ SkMatrix* mTransform;
+ bool mNeedsGLContextAttach;
+ bool mUpdateTexImage;
+
+ Layer* mLayer;
+ OpenGLRenderer* mRenderer;
+ Caches& mCaches;
+
+ void doUpdateTexImage();
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* DEFERREDLAYERUPDATE_H_ */
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 2a39bd9..a5e66fa 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -96,10 +96,6 @@
caches.resourceCache.destructorLocked(bitmap);
}
- for (size_t i = 0; i < mFilterResources.size(); i++) {
- caches.resourceCache.decrementRefcountLocked(mFilterResources.itemAt(i));
- }
-
for (size_t i = 0; i < mPatchResources.size(); i++) {
caches.resourceCache.decrementRefcountLocked(mPatchResources.itemAt(i));
}
@@ -137,7 +133,6 @@
mBitmapResources.clear();
mOwnedBitmapResources.clear();
- mFilterResources.clear();
mPatchResources.clear();
mShaders.clear();
mSourcePaths.clear();
@@ -188,13 +183,6 @@
caches.resourceCache.incrementRefcountLocked(resource);
}
- const Vector<SkiaColorFilter*>& filterResources = recorder.getFilterResources();
- for (size_t i = 0; i < filterResources.size(); i++) {
- SkiaColorFilter* resource = filterResources.itemAt(i);
- mFilterResources.add(resource);
- caches.resourceCache.incrementRefcountLocked(resource);
- }
-
const Vector<const Res_png_9patch*>& patchResources = recorder.getPatchResources();
for (size_t i = 0; i < patchResources.size(); i++) {
const Res_png_9patch* resource = patchResources.itemAt(i);
@@ -243,6 +231,8 @@
mProjectionReceiver = false;
mOutline.rewind();
mClipToOutline = false;
+ mCastsShadow = false;
+ mSharesGlobalCamera = false;
mAlpha = 1;
mHasOverlappingRendering = true;
mTranslationX = 0;
@@ -670,16 +660,13 @@
if (mode == kPositiveZChildren && zValue < 0.0f) continue;
if (mode == kNegativeZChildren && zValue > 0.0f) break;
- if (mode == kPositiveZChildren && zValue > 0.0f) {
+ DisplayList* child = childOp->mDisplayList;
+ if (mode == kPositiveZChildren && zValue > 0.0f && child->mCastsShadow) {
/* draw shadow with parent matrix applied, passing in the child's total matrix
- *
- * TODO:
- * -view must opt-in to shadows
- * -consider depth in more complex scenarios (neg z, added shadow depth)
+ * TODO: consider depth in more complex scenarios (neg z, added shadow depth)
*/
mat4 shadowMatrix(childOp->mTransformFromCompositingAncestor);
- childOp->mDisplayList->applyViewPropertyTransforms(shadowMatrix);
- DisplayList* child = childOp->mDisplayList;
+ child->applyViewPropertyTransforms(shadowMatrix);
DisplayListOp* shadowOp = new (alloc) DrawShadowOp(shadowMatrix,
child->mAlpha, &(child->mOutline), child->mWidth, child->mHeight);
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 42a4e74..c3d9fd7 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -61,7 +61,6 @@
class OpenGLRenderer;
class Rect;
class Layer;
-class SkiaColorFilter;
class SkiaShader;
class ClipRectOp;
@@ -193,6 +192,14 @@
mIsolatedZVolume = shouldIsolate;
}
+ void setCastsShadow(bool castsShadow) {
+ mCastsShadow = castsShadow;
+ }
+
+ void setSharesGlobalCamera(bool sharesGlobalCamera) {
+ mSharesGlobalCamera = sharesGlobalCamera;
+ }
+
void setProjectBackwards(bool shouldProject) {
mProjectBackwards = shouldProject;
}
@@ -586,7 +593,6 @@
Vector<const SkBitmap*> mBitmapResources;
Vector<const SkBitmap*> mOwnedBitmapResources;
- Vector<SkiaColorFilter*> mFilterResources;
Vector<const Res_png_9patch*> mPatchResources;
Vector<const SkPaint*> mPaints;
@@ -614,6 +620,8 @@
bool mProjectionReceiver;
SkPath mOutline;
bool mClipToOutline;
+ bool mCastsShadow;
+ bool mSharesGlobalCamera; // TODO: respect value when rendering
float mAlpha;
bool mHasOverlappingRendering;
float mTranslationX, mTranslationY, mTranslationZ;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index d4f82ea..0589a022 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -620,38 +620,6 @@
SkiaShader* mShader;
};
-class ResetColorFilterOp : public StateOp {
-public:
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
- renderer.resetColorFilter();
- }
-
- virtual void output(int level, uint32_t logFlags) const {
- OP_LOGS("ResetColorFilter");
- }
-
- virtual const char* name() { return "ResetColorFilter"; }
-};
-
-class SetupColorFilterOp : public StateOp {
-public:
- SetupColorFilterOp(SkiaColorFilter* colorFilter)
- : mColorFilter(colorFilter) {}
-
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
- renderer.setupColorFilter(mColorFilter);
- }
-
- virtual void output(int level, uint32_t logFlags) const {
- OP_LOG("SetupColorFilter, filter %p", mColorFilter);
- }
-
- virtual const char* name() { return "SetupColorFilter"; }
-
-private:
- SkiaColorFilter* mColorFilter;
-};
-
class ResetShadowOp : public StateOp {
public:
virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 7c85297..0cbf088 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -53,10 +53,6 @@
mCaches.resourceCache.decrementRefcountLocked(mOwnedBitmapResources.itemAt(i));
}
- for (size_t i = 0; i < mFilterResources.size(); i++) {
- mCaches.resourceCache.decrementRefcountLocked(mFilterResources.itemAt(i));
- }
-
for (size_t i = 0; i < mPatchResources.size(); i++) {
mCaches.resourceCache.decrementRefcountLocked(mPatchResources.itemAt(i));
}
@@ -77,7 +73,6 @@
mBitmapResources.clear();
mOwnedBitmapResources.clear();
- mFilterResources.clear();
mPatchResources.clear();
mSourcePaths.clear();
@@ -457,15 +452,6 @@
addStateOp(new (alloc()) SetupShaderOp(shader));
}
-void DisplayListRenderer::resetColorFilter() {
- addStateOp(new (alloc()) ResetColorFilterOp());
-}
-
-void DisplayListRenderer::setupColorFilter(SkiaColorFilter* filter) {
- filter = refColorFilter(filter);
- addStateOp(new (alloc()) SetupColorFilterOp(filter));
-}
-
void DisplayListRenderer::resetShadow() {
addStateOp(new (alloc()) ResetShadowOp());
OpenGLRenderer::resetShadow();
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 3c14212..7e62c5d 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -102,9 +102,6 @@
virtual void resetShader();
virtual void setupShader(SkiaShader* shader);
- virtual void resetColorFilter();
- virtual void setupColorFilter(SkiaColorFilter* filter);
-
virtual void resetShadow();
virtual void setupShadow(float radius, float dx, float dy, int color);
@@ -182,10 +179,6 @@
return mOwnedBitmapResources;
}
- const Vector<SkiaColorFilter*>& getFilterResources() const {
- return mFilterResources;
- }
-
const Vector<const Res_png_9patch*>& getPatchResources() const {
return mPatchResources;
}
@@ -349,12 +342,6 @@
return shaderCopy;
}
- inline SkiaColorFilter* refColorFilter(SkiaColorFilter* colorFilter) {
- mFilterResources.add(colorFilter);
- mCaches.resourceCache.incrementRefcount(colorFilter);
- return colorFilter;
- }
-
inline const Res_png_9patch* refPatch(const Res_png_9patch* patch) {
mPatchResources.add(patch);
mCaches.resourceCache.incrementRefcount(patch);
@@ -364,7 +351,6 @@
// TODO: move these to DisplayListData
Vector<const SkBitmap*> mBitmapResources;
Vector<const SkBitmap*> mOwnedBitmapResources;
- Vector<SkiaColorFilter*> mFilterResources;
Vector<const Res_png_9patch*> mPatchResources;
Vector<const SkPaint*> mPaints;
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index f907d64..b79a3b0 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -72,9 +72,9 @@
break;
}
}
- renderer->setupDrawColorFilter();
+ renderer->setupDrawColorFilter(paint->getColorFilter());
renderer->setupDrawShader();
- renderer->setupDrawBlending(true, mode);
+ renderer->setupDrawBlending(paint);
renderer->setupDrawProgram();
renderer->setupDrawModelView(kModelViewMode_Translate, false,
0.0f, 0.0f, 0.0f, 0.0f, pureTranslate);
@@ -84,7 +84,7 @@
// needed
renderer->setupDrawTexture(0);
renderer->setupDrawPureColorUniforms();
- renderer->setupDrawColorFilterUniforms();
+ renderer->setupDrawColorFilterUniforms(paint->getColorFilter());
renderer->setupDrawShaderUniforms(pureTranslate);
renderer->setupDrawTextGammaUniforms();
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 742ffd47..70eeb39 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -51,7 +51,7 @@
}
Layer::~Layer() {
- if (colorFilter) caches.resourceCache.decrementRefcount(colorFilter);
+ SkSafeUnref(colorFilter);
removeFbo();
deleteTexture();
@@ -135,14 +135,8 @@
OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode);
}
-void Layer::setColorFilter(SkiaColorFilter* filter) {
- if (colorFilter) {
- caches.resourceCache.decrementRefcount(colorFilter);
- }
- colorFilter = filter;
- if (colorFilter) {
- caches.resourceCache.incrementRefcount(colorFilter);
- }
+void Layer::setColorFilter(SkColorFilter* filter) {
+ SkRefCnt_SafeAssign(colorFilter, filter);
}
void Layer::bindTexture() const {
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 471a4a6..ec80e9c 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_HWUI_LAYER_H
#define ANDROID_HWUI_LAYER_H
+#include <cutils/compiler.h>
#include <sys/types.h>
#include <GLES2/gl2.h>
@@ -26,9 +27,9 @@
#include <SkPaint.h>
#include <SkXfermode.h>
+#include "Matrix.h"
#include "Rect.h"
#include "RenderBuffer.h"
-#include "SkiaColorFilter.h"
#include "Texture.h"
#include "Vertex.h"
@@ -217,11 +218,11 @@
this->textureLayer = textureLayer;
}
- inline SkiaColorFilter* getColorFilter() const {
+ inline SkColorFilter* getColorFilter() const {
return colorFilter;
}
- ANDROID_API void setColorFilter(SkiaColorFilter* filter);
+ ANDROID_API void setColorFilter(SkColorFilter* filter);
void bindStencilRenderBuffer() const;
@@ -339,7 +340,7 @@
/**
* Color filter used to draw this layer. Optional.
*/
- SkiaColorFilter* colorFilter;
+ SkColorFilter* colorFilter;
/**
* Opacity of the layer.
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 0b38c4d..ea8eb31 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -184,7 +184,7 @@
// Layers management
///////////////////////////////////////////////////////////////////////////////
-Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque) {
+Layer* LayerRenderer::createRenderLayer(uint32_t width, uint32_t height) {
LAYER_RENDERER_LOGD("Requesting new render layer %dx%d", width, height);
Caches& caches = Caches::getInstance();
@@ -221,7 +221,6 @@
layer->texCoords.set(0.0f, height / float(layer->getHeight()),
width / float(layer->getWidth()), 0.0f);
layer->setAlpha(255, SkXfermode::kSrcOver_Mode);
- layer->setBlend(!isOpaque);
layer->setColorFilter(NULL);
layer->setDirty(true);
layer->region.clear();
@@ -270,13 +269,12 @@
return true;
}
-Layer* LayerRenderer::createTextureLayer(bool isOpaque) {
+Layer* LayerRenderer::createTextureLayer() {
LAYER_RENDERER_LOGD("Creating new texture layer");
Layer* layer = new Layer(0, 0);
layer->setCacheable(false);
layer->setTextureLayer(true);
- layer->setBlend(!isOpaque);
layer->setEmpty(true);
layer->setFbo(0);
layer->setAlpha(255, SkXfermode::kSrcOver_Mode);
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index f24c8d4..84acd44 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -52,8 +52,8 @@
virtual status_t clear(float left, float top, float right, float bottom, bool opaque);
virtual void finish();
- ANDROID_API static Layer* createTextureLayer(bool isOpaque);
- ANDROID_API static Layer* createLayer(uint32_t width, uint32_t height, bool isOpaque = false);
+ ANDROID_API static Layer* createTextureLayer();
+ ANDROID_API static Layer* createRenderLayer(uint32_t width, uint32_t height);
ANDROID_API static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height);
ANDROID_API static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
bool isOpaque, GLenum renderTarget, float* transform);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 4b947a6..fee916b 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -893,7 +893,7 @@
layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->getHeight()),
bounds.getWidth() / float(layer->getWidth()), 0.0f);
- layer->setColorFilter(mDrawModifiers.mColorFilter);
+ layer->setColorFilter(getColorFilter(paint));
layer->setBlend(true);
layer->setDirty(false);
@@ -1011,8 +1011,13 @@
}
if (!fboLayer && layer->getAlpha() < 255) {
- drawColorRect(rect.left, rect.top, rect.right, rect.bottom,
- layer->getAlpha() << 24, SkXfermode::kDstIn_Mode, true);
+ // TODO: this seems to point to the fact that the layer should store the paint
+ SkPaint layerPaint;
+ layerPaint.setAlpha(layer->getAlpha());
+ layerPaint.setXfermodeMode(SkXfermode::kDstIn_Mode);
+ layerPaint.setColorFilter(layer->getColorFilter());
+
+ drawColorRect(rect.left, rect.top, rect.right, rect.bottom, &layerPaint, true);
// Required below, composeLayerRect() will divide by 255
layer->setAlpha(255);
}
@@ -1025,13 +1030,7 @@
// drawing only the dirty region
if (fboLayer) {
dirtyLayer(rect.left, rect.top, rect.right, rect.bottom, *restored.transform);
- if (layer->getColorFilter()) {
- setupColorFilter(layer->getColorFilter());
- }
composeLayerRegion(layer, rect);
- if (layer->getColorFilter()) {
- resetColorFilter();
- }
} else if (!rect.isEmpty()) {
dirtyLayer(rect.left, rect.top, rect.right, rect.bottom);
@@ -1063,11 +1062,11 @@
}
setupDrawTextureTransform();
setupDrawColor(alpha, alpha, alpha, alpha);
- setupDrawColorFilter();
- setupDrawBlending(layer->isBlend() || alpha < 1.0f, layer->getMode());
+ setupDrawColorFilter(layer->getColorFilter());
+ setupDrawBlending(layer);
setupDrawProgram();
setupDrawPureColorUniforms();
- setupDrawColorFilterUniforms();
+ setupDrawColorFilterUniforms(layer->getColorFilter());
if (layer->getRenderTarget() == GL_TEXTURE_2D) {
setupDrawTexture(layer->getTexture());
} else {
@@ -1117,10 +1116,14 @@
layer->setFilter(GL_LINEAR, true);
}
- float alpha = getLayerAlpha(layer);
- bool blend = layer->isBlend() || alpha < 1.0f;
+ SkPaint layerPaint;
+ layerPaint.setAlpha(getLayerAlpha(layer) * 255);
+ layerPaint.setXfermodeMode(layer->getMode());
+ layerPaint.setColorFilter(layer->getColorFilter());
+
+ bool blend = layer->isBlend() || getLayerAlpha(layer) < 1.0f;
drawTextureMesh(x, y, x + rect.getWidth(), y + rect.getHeight(),
- layer->getTexture(), alpha, layer->getMode(), blend,
+ layer->getTexture(), &layerPaint, blend,
&mMeshVertices[0].x, &mMeshVertices[0].u,
GL_TRIANGLE_STRIP, gMeshCount, swap, swap || simpleTransform);
@@ -1185,12 +1188,12 @@
setupDrawWithTexture();
setupDrawColor(alpha, alpha, alpha, alpha);
- setupDrawColorFilter();
- setupDrawBlending(layer->isBlend() || alpha < 1.0f, layer->getMode(), false);
+ setupDrawColorFilter(layer->getColorFilter());
+ setupDrawBlending(layer);
setupDrawProgram();
setupDrawDirtyRegionsDisabled();
setupDrawPureColorUniforms();
- setupDrawColorFilterUniforms();
+ setupDrawColorFilterUniforms(layer->getColorFilter());
setupDrawTexture(layer->getTexture());
if (currentTransform()->isPureTranslate()) {
const float x = (int) floorf(rect.left + currentTransform()->getTranslateX() + 0.5f);
@@ -1262,15 +1265,15 @@
top = rects[i].top;
}
+ SkPaint paint;
+ paint.setColor(colors[offset + (i & 0x1)]);
Rect r(rects[i].left, rects[i].top, rects[i].right, rects[i].bottom);
- drawColorRect(r.left, r.top, r.right, r.bottom, colors[offset + (i & 0x1)],
- SkXfermode::kSrcOver_Mode);
+ drawColorRect(r.left, r.top, r.right, r.bottom, paint);
}
}
#endif
-void OpenGLRenderer::drawRegionRects(const SkRegion& region, int color,
- SkXfermode::Mode mode, bool dirty) {
+void OpenGLRenderer::drawRegionRects(const SkRegion& region, const SkPaint& paint, bool dirty) {
Vector<float> rects;
SkRegion::Iterator it(region);
@@ -1283,7 +1286,7 @@
it.next();
}
- drawColorRects(rects.array(), rects.size(), color, mode, true, dirty, false);
+ drawColorRects(rects.array(), rects.size(), &paint, true, dirty, false);
}
void OpenGLRenderer::dirtyLayer(const float left, const float top,
@@ -1360,9 +1363,12 @@
// the same thing again
mLayers.clear();
+ SkPaint clearPaint;
+ clearPaint.setXfermodeMode(SkXfermode::kClear_Mode);
+
setupDraw(false);
setupDrawColor(0.0f, 0.0f, 0.0f, 1.0f);
- setupDrawBlending(true, SkXfermode::kClear_Mode);
+ setupDrawBlending(&clearPaint, true);
setupDrawProgram();
setupDrawPureColorUniforms();
setupDrawModelView(kModelViewMode_Translate, false,
@@ -1521,22 +1527,26 @@
mCaches.stencil.clear();
if (resetScissor) mCaches.disableScissor();
+ SkPaint paint;
+ paint.setColor(0xff000000);
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+
// NOTE: We could use the region contour path to generate a smaller mesh
// Since we are using the stencil we could use the red book path
// drawing technique. It might increase bandwidth usage though.
// The last parameter is important: we are not drawing in the color buffer
// so we don't want to dirty the current layer, if any
- drawRegionRects(*(currentSnapshot()->clipRegion),
- 0xff000000, SkXfermode::kSrc_Mode, false);
+ drawRegionRects(*(currentSnapshot()->clipRegion), paint, false);
mCaches.stencil.enableTest();
// Draw the region used to generate the stencil if the appropriate debug
// mode is enabled
if (mCaches.debugStencilClip == Caches::kStencilShowRegion) {
- drawRegionRects(*(currentSnapshot()->clipRegion),
- 0x7f0000ff, SkXfermode::kSrcOver_Mode);
+ paint.setColor(0x7f0000ff);
+ paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
+ drawRegionRects(*(currentSnapshot()->clipRegion), paint);
}
} else {
mCaches.stencil.disable();
@@ -1577,7 +1587,10 @@
void OpenGLRenderer::debugClip() {
#if DEBUG_CLIP_REGIONS
if (!isRecording() && !currentSnapshot()->clipRegion->isEmpty()) {
- drawRegionRects(*(currentSnapshot()->clipRegion), 0x7f00ff00, SkXfermode::kSrcOver_Mode);
+ SkPaint paint;
+ paint.setColor(0x7f00ff00);
+ drawRegionRects(*(currentSnapshot()->clipRegion, paint);
+
}
#endif
}
@@ -1676,9 +1689,17 @@
}
}
-void OpenGLRenderer::setupDrawColorFilter() {
- if (mDrawModifiers.mColorFilter) {
- mDrawModifiers.mColorFilter->describe(mDescription, mExtensions);
+void OpenGLRenderer::setupDrawColorFilter(const SkColorFilter* filter) {
+ if (filter == NULL) {
+ return;
+ }
+
+ SkXfermode::Mode mode;
+ if (filter->asColorMode(NULL, &mode)) {
+ mDescription.colorOp = ProgramDescription::kColorBlend;
+ mDescription.colorMode = mode;
+ } else if (filter->asColorMatrix(NULL)) {
+ mDescription.colorOp = ProgramDescription::kColorMatrix;
}
}
@@ -1690,22 +1711,26 @@
}
}
-void OpenGLRenderer::setupDrawBlending(SkXfermode::Mode mode, bool swapSrcDst) {
+void OpenGLRenderer::setupDrawBlending(const Layer* layer, bool swapSrcDst) {
+ SkXfermode::Mode mode = layer->getMode();
// When the blending mode is kClear_Mode, we need to use a modulate color
// argb=1,0,0,0
accountForClear(mode);
- bool blend = (mColorSet && mColorA < 1.0f) ||
- (mDrawModifiers.mShader && mDrawModifiers.mShader->blend());
+ bool blend = layer->isBlend() || getLayerAlpha(layer) < 1.0f ||
+ (mColorSet && mColorA < 1.0f) ||
+ (mDrawModifiers.mShader && mDrawModifiers.mShader->blend()) ||
+ layer->getColorFilter();
chooseBlending(blend, mode, mDescription, swapSrcDst);
}
-void OpenGLRenderer::setupDrawBlending(bool blend, SkXfermode::Mode mode, bool swapSrcDst) {
+void OpenGLRenderer::setupDrawBlending(const SkPaint* paint, bool blend, bool swapSrcDst) {
+ SkXfermode::Mode mode = getXfermodeDirect(paint);
// When the blending mode is kClear_Mode, we need to use a modulate color
// argb=1,0,0,0
accountForClear(mode);
blend |= (mColorSet && mColorA < 1.0f) ||
(mDrawModifiers.mShader && mDrawModifiers.mShader->blend()) ||
- (mDrawModifiers.mColorFilter && mDrawModifiers.mColorFilter->blend());
+ (paint && paint->getColorFilter());
chooseBlending(blend, mode, mDescription, swapSrcDst);
}
@@ -1762,10 +1787,47 @@
}
}
-void OpenGLRenderer::setupDrawColorFilterUniforms() {
- if (mDrawModifiers.mColorFilter) {
- mDrawModifiers.mColorFilter->setupProgram(mCaches.currentProgram);
+void OpenGLRenderer::setupDrawColorFilterUniforms(const SkColorFilter* filter) {
+ if (NULL == filter) {
+ return;
}
+
+ SkColor color;
+ SkXfermode::Mode mode;
+ if (filter->asColorMode(&color, &mode)) {
+ const int alpha = SkColorGetA(color);
+ const GLfloat a = alpha / 255.0f;
+ const GLfloat r = a * SkColorGetR(color) / 255.0f;
+ const GLfloat g = a * SkColorGetG(color) / 255.0f;
+ const GLfloat b = a * SkColorGetB(color) / 255.0f;
+ glUniform4f(mCaches.currentProgram->getUniform("colorBlend"), r, g, b, a);
+ return;
+ }
+
+ SkScalar srcColorMatrix[20];
+ if (filter->asColorMatrix(srcColorMatrix)) {
+
+ float colorMatrix[16];
+ memcpy(colorMatrix, srcColorMatrix, 4 * sizeof(float));
+ memcpy(&colorMatrix[4], &srcColorMatrix[5], 4 * sizeof(float));
+ memcpy(&colorMatrix[8], &srcColorMatrix[10], 4 * sizeof(float));
+ memcpy(&colorMatrix[12], &srcColorMatrix[15], 4 * sizeof(float));
+
+ // Skia uses the range [0..255] for the addition vector, but we need
+ // the [0..1] range to apply the vector in GLSL
+ float colorVector[4];
+ colorVector[0] = srcColorMatrix[4] / 255.0f;
+ colorVector[1] = srcColorMatrix[9] / 255.0f;
+ colorVector[2] = srcColorMatrix[14] / 255.0f;
+ colorVector[3] = srcColorMatrix[19] / 255.0f;
+
+ glUniformMatrix4fv(mCaches.currentProgram->getUniform("colorMatrix"), 1,
+ GL_FALSE, colorMatrix);
+ glUniform4fv(mCaches.currentProgram->getUniform("colorMatrixVector"), 1, colorVector);
+ return;
+ }
+
+ // it is an error if we ever get here
}
void OpenGLRenderer::setupDrawTextGammaUniforms() {
@@ -1900,10 +1962,6 @@
}
void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top, const SkPaint* paint) {
- int alpha;
- SkXfermode::Mode mode;
- getAlphaAndMode(paint, &alpha, &mode);
-
int color = paint != NULL ? paint->getColor() : 0;
float x = left;
@@ -1925,7 +1983,7 @@
// No need to check for a UV mapper on the texture object, only ARGB_8888
// bitmaps get packed in the atlas
drawAlpha8TextureMesh(x, y, x + texture->width, y + texture->height, texture->id,
- paint != NULL, color, alpha, mode, (GLvoid*) NULL, (GLvoid*) gMeshTextureOffset,
+ paint, (GLvoid*) NULL, (GLvoid*) gMeshTextureOffset,
GL_TRIANGLE_STRIP, gMeshCount, ignoreTransform);
}
@@ -1943,26 +2001,19 @@
const AutoTexture autoCleanup(texture);
- int alpha;
- SkXfermode::Mode mode;
- getAlphaAndMode(paint, &alpha, &mode);
-
texture->setWrap(GL_CLAMP_TO_EDGE, true);
texture->setFilter(pureTranslate ? GL_NEAREST : FILTER(paint), true);
const float x = (int) floorf(bounds.left + 0.5f);
const float y = (int) floorf(bounds.top + 0.5f);
if (CC_UNLIKELY(bitmap->config() == SkBitmap::kA8_Config)) {
- int color = paint != NULL ? paint->getColor() : 0;
drawAlpha8TextureMesh(x, y, x + bounds.getWidth(), y + bounds.getHeight(),
- texture->id, paint != NULL, color, alpha, mode,
- &vertices[0].x, &vertices[0].u,
+ texture->id, paint, &vertices[0].x, &vertices[0].u,
GL_TRIANGLES, bitmapCount * 6, true,
kModelViewMode_Translate, false);
} else {
drawTextureMesh(x, y, x + bounds.getWidth(), y + bounds.getHeight(),
- texture->id, alpha / 255.0f, mode, texture->blend,
- &vertices[0].x, &vertices[0].u,
+ texture->id, paint, texture->blend, &vertices[0].x, &vertices[0].u,
GL_TRIANGLES, bitmapCount * 6, false, true, 0,
kModelViewMode_Translate, false);
}
@@ -2142,14 +2193,14 @@
setupDraw();
setupDrawWithTextureAndColor();
setupDrawColor(a, a, a, a);
- setupDrawColorFilter();
- setupDrawBlending(true, mode, false);
+ setupDrawColorFilter(getColorFilter(paint));
+ setupDrawBlending(paint, true);
setupDrawProgram();
setupDrawDirtyRegionsDisabled();
setupDrawModelView(kModelViewMode_TranslateAndScale, false, 0.0f, 0.0f, 1.0f, 1.0f);
setupDrawTexture(texture->id);
setupDrawPureColorUniforms();
- setupDrawColorFilterUniforms();
+ setupDrawColorFilterUniforms(getColorFilter(paint));
setupDrawMesh(&mesh[0].x, &mesh[0].u, &mesh[0].r);
glDrawArrays(GL_TRIANGLES, 0, count);
@@ -2190,10 +2241,6 @@
mCaches.unbindMeshBuffer();
resetDrawTextureTexCoords(u1, v1, u2, v2);
- int alpha;
- SkXfermode::Mode mode;
- getAlphaAndMode(paint, &alpha, &mode);
-
texture->setWrap(GL_CLAMP_TO_EDGE, true);
float scaleX = (dstRight - dstLeft) / (srcRight - srcLeft);
@@ -2235,14 +2282,13 @@
}
if (CC_UNLIKELY(bitmap->config() == SkBitmap::kA8_Config)) {
- int color = paint ? paint->getColor() : 0;
drawAlpha8TextureMesh(dstLeft, dstTop, dstRight, dstBottom,
- texture->id, paint != NULL, color, alpha, mode,
+ texture->id, paint,
&mMeshVertices[0].x, &mMeshVertices[0].u,
GL_TRIANGLE_STRIP, gMeshCount, ignoreTransform);
} else {
drawTextureMesh(dstLeft, dstTop, dstRight, dstBottom,
- texture->id, alpha / 255.0f, mode, texture->blend,
+ texture->id, paint, texture->blend,
&mMeshVertices[0].x, &mMeshVertices[0].u,
GL_TRIANGLE_STRIP, gMeshCount, false, ignoreTransform);
}
@@ -2285,10 +2331,6 @@
texture->setWrap(GL_CLAMP_TO_EDGE, true);
texture->setFilter(GL_LINEAR, true);
- int alpha;
- SkXfermode::Mode mode;
- getAlphaAndMode(paint, &alpha, &mode);
-
const bool pureTranslate = currentTransform()->isPureTranslate();
// Mark the current layer dirty where we are going to draw the patch
if (hasLayer() && mesh->hasEmptyQuads) {
@@ -2319,8 +2361,8 @@
top = y;
ignoreTransform = true;
}
- drawIndexedTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f,
- mode, texture->blend, (GLvoid*) mesh->offset, (GLvoid*) mesh->textureOffset,
+ drawIndexedTextureMesh(left, top, right, bottom, texture->id, paint,
+ texture->blend, (GLvoid*) mesh->offset, (GLvoid*) mesh->textureOffset,
GL_TRIANGLES, mesh->indexCount, false, ignoreTransform,
mCaches.patchCache.getMeshBuffer(), kModelViewMode_Translate, !mesh->hasEmptyQuads);
}
@@ -2343,12 +2385,8 @@
texture->setWrap(GL_CLAMP_TO_EDGE, true);
texture->setFilter(GL_LINEAR, true);
- int alpha;
- SkXfermode::Mode mode;
- getAlphaAndMode(paint, &alpha, &mode);
-
- drawIndexedTextureMesh(0.0f, 0.0f, 1.0f, 1.0f, texture->id, alpha / 255.0f,
- mode, texture->blend, &vertices[0].x, &vertices[0].u,
+ drawIndexedTextureMesh(0.0f, 0.0f, 1.0f, 1.0f, texture->id, paint,
+ texture->blend, &vertices[0].x, &vertices[0].u,
GL_TRIANGLES, indexCount, false, true, 0, kModelViewMode_Translate, false);
return DrawGlInfo::kStatusDrew;
@@ -2364,20 +2402,19 @@
}
int color = paint->getColor();
- SkXfermode::Mode mode = getXfermode(paint->getXfermode());
bool isAA = paint->isAntiAlias();
setupDraw();
setupDrawNoTexture();
if (isAA) setupDrawAA();
setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
- setupDrawColorFilter();
+ setupDrawColorFilter(getColorFilter(paint));
setupDrawShader();
- setupDrawBlending(isAA, mode);
+ setupDrawBlending(paint, isAA);
setupDrawProgram();
setupDrawModelView(kModelViewMode_Translate, useOffset, 0, 0, 0, 0);
setupDrawColorUniforms();
- setupDrawColorFilterUniforms();
+ setupDrawColorFilterUniforms(getColorFilter(paint));
setupDrawShaderUniforms();
const void* vertices = vertexBuffer.getBuffer();
@@ -2486,7 +2523,11 @@
Rect clip(*currentClipRect());
clip.snapToPixelBoundaries();
- drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode, true);
+ SkPaint paint;
+ paint.setColor(color);
+ paint.setXfermodeMode(mode);
+
+ drawColorRect(clip.left, clip.top, clip.right, clip.bottom, &paint, true);
return DrawGlInfo::kStatusDrew;
}
@@ -2642,14 +2683,14 @@
path.addRect(left, top, right, bottom);
return drawConvexPath(path, p);
} else {
- drawColorRect(left, top, right, bottom, p->getColor(), getXfermode(p->getXfermode()));
+ drawColorRect(left, top, right, bottom, p);
return DrawGlInfo::kStatusDrew;
}
}
void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text,
int bytesCount, int count, const float* positions,
- FontRenderer& fontRenderer, int alpha, SkXfermode::Mode mode, float x, float y) {
+ FontRenderer& fontRenderer, int alpha, float x, float y) {
mCaches.activeTexture(0);
// NOTE: The drop shadow will not perform gamma correction
@@ -2674,15 +2715,15 @@
setupDraw();
setupDrawWithTexture(true);
setupDrawAlpha8Color(shadowColor, shadowAlpha < 255 ? shadowAlpha : alpha);
- setupDrawColorFilter();
+ setupDrawColorFilter(getColorFilter(paint));
setupDrawShader();
- setupDrawBlending(true, mode);
+ setupDrawBlending(paint, true);
setupDrawProgram();
setupDrawModelView(kModelViewMode_TranslateAndScale, false,
sx, sy, sx + shadow->width, sy + shadow->height);
setupDrawTexture(shadow->id);
setupDrawPureColorUniforms();
- setupDrawColorFilterUniforms();
+ setupDrawColorFilterUniforms(getColorFilter(paint));
setupDrawShaderUniforms();
setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
@@ -2724,7 +2765,7 @@
if (CC_UNLIKELY(mDrawModifiers.mHasShadow)) {
drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer,
- alpha, mode, 0.0f, 0.0f);
+ alpha, 0.0f, 0.0f);
}
// Pick the appropriate texture filtering
@@ -2802,7 +2843,7 @@
if (CC_UNLIKELY(mDrawModifiers.mHasShadow)) {
fontRenderer.setFont(paint, mat4::identity());
drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer,
- alpha, mode, oldX, oldY);
+ alpha, oldX, oldY);
}
const bool hasActiveLayer = hasLayer();
@@ -2938,22 +2979,20 @@
mCaches.activeTexture(0);
if (CC_LIKELY(!layer->region.isEmpty())) {
- SkiaColorFilter* oldFilter = mDrawModifiers.mColorFilter;
- mDrawModifiers.mColorFilter = layer->getColorFilter();
-
if (layer->region.isRect()) {
DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate,
composeLayerRect(layer, layer->regionRect));
} else if (layer->mesh) {
+
const float a = getLayerAlpha(layer);
setupDraw();
setupDrawWithTexture();
setupDrawColor(a, a, a, a);
- setupDrawColorFilter();
- setupDrawBlending(layer->isBlend() || a < 1.0f, layer->getMode(), false);
+ setupDrawColorFilter(layer->getColorFilter());
+ setupDrawBlending(layer);
setupDrawProgram();
setupDrawPureColorUniforms();
- setupDrawColorFilterUniforms();
+ setupDrawColorFilterUniforms(layer->getColorFilter());
setupDrawTexture(layer->getTexture());
if (CC_LIKELY(currentTransform()->isPureTranslate())) {
int tx = (int) floorf(x + currentTransform()->getTranslateX() + 0.5f);
@@ -2989,12 +3028,12 @@
#endif
}
- mDrawModifiers.mColorFilter = oldFilter;
-
if (layer->debugDrawUpdate) {
layer->debugDrawUpdate = false;
- drawColorRect(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight(),
- 0x7f00ff00, SkXfermode::kSrcOver_Mode);
+
+ SkPaint paint;
+ paint.setColor(0x7f00ff00);
+ drawColorRect(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight(), &paint);
}
}
layer->hasDrawnSinceUpdate = true;
@@ -3022,18 +3061,6 @@
}
///////////////////////////////////////////////////////////////////////////////
-// Color filters
-///////////////////////////////////////////////////////////////////////////////
-
-void OpenGLRenderer::resetColorFilter() {
- mDrawModifiers.mColorFilter = NULL;
-}
-
-void OpenGLRenderer::setupColorFilter(SkiaColorFilter* filter) {
- mDrawModifiers.mColorFilter = filter;
-}
-
-///////////////////////////////////////////////////////////////////////////////
// Drop shadow
///////////////////////////////////////////////////////////////////////////////
@@ -3106,15 +3133,15 @@
setupDraw();
setupDrawWithTexture(true);
setupDrawAlpha8Color(paint->getColor(), alpha);
- setupDrawColorFilter();
+ setupDrawColorFilter(getColorFilter(paint));
setupDrawShader();
- setupDrawBlending(true, mode);
+ setupDrawBlending(paint, true);
setupDrawProgram();
setupDrawModelView(kModelViewMode_TranslateAndScale, false,
x, y, x + texture->width, y + texture->height);
setupDrawTexture(texture->id);
setupDrawPureColorUniforms();
- setupDrawColorFilterUniforms();
+ setupDrawColorFilterUniforms(getColorFilter(paint));
setupDrawShaderUniforms();
setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
@@ -3176,14 +3203,7 @@
return DrawGlInfo::kStatusDone;
}
- int color = paint->getColor();
- // If a shader is set, preserve only the alpha
- if (mDrawModifiers.mShader) {
- color |= 0x00ffffff;
- }
- SkXfermode::Mode mode = getXfermode(paint->getXfermode());
-
- return drawColorRects(rects, count, color, mode);
+ return drawColorRects(rects, count, paint, false, true, true);
}
status_t OpenGLRenderer::drawShadow(const mat4& casterTransform, float casterAlpha,
@@ -3235,12 +3255,18 @@
return DrawGlInfo::kStatusDrew;
}
-status_t OpenGLRenderer::drawColorRects(const float* rects, int count, int color,
- SkXfermode::Mode mode, bool ignoreTransform, bool dirty, bool clip) {
+status_t OpenGLRenderer::drawColorRects(const float* rects, int count, const SkPaint* paint,
+ bool ignoreTransform, bool dirty, bool clip) {
if (count == 0) {
return DrawGlInfo::kStatusDone;
}
+ int color = paint->getColor();
+ // If a shader is set, preserve only the alpha
+ if (mDrawModifiers.mShader) {
+ color |= 0x00ffffff;
+ }
+
float left = FLT_MAX;
float top = FLT_MAX;
float right = FLT_MIN;
@@ -3274,15 +3300,15 @@
setupDrawNoTexture();
setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha);
setupDrawShader();
- setupDrawColorFilter();
- setupDrawBlending(mode);
+ setupDrawColorFilter(getColorFilter(paint));
+ setupDrawBlending(paint);
setupDrawProgram();
setupDrawDirtyRegionsDisabled();
setupDrawModelView(kModelViewMode_Translate, false,
0.0f, 0.0f, 0.0f, 0.0f, ignoreTransform);
setupDrawColorUniforms();
setupDrawShaderUniforms();
- setupDrawColorFilterUniforms();
+ setupDrawColorFilterUniforms(getColorFilter(paint));
if (dirty && hasLayer()) {
dirtyLayer(left, top, right, bottom, *currentTransform());
@@ -3294,7 +3320,8 @@
}
void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom,
- int color, SkXfermode::Mode mode, bool ignoreTransform) {
+ const SkPaint* paint, bool ignoreTransform) {
+ int color = paint->getColor();
// If a shader is set, preserve only the alpha
if (mDrawModifiers.mShader) {
color |= 0x00ffffff;
@@ -3304,14 +3331,14 @@
setupDrawNoTexture();
setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha);
setupDrawShader();
- setupDrawColorFilter();
- setupDrawBlending(mode);
+ setupDrawColorFilter(getColorFilter(paint));
+ setupDrawBlending(paint);
setupDrawProgram();
setupDrawModelView(kModelViewMode_TranslateAndScale, false,
left, top, right, bottom, ignoreTransform);
setupDrawColorUniforms();
setupDrawShaderUniforms(ignoreTransform);
- setupDrawColorFilterUniforms();
+ setupDrawColorFilterUniforms(getColorFilter(paint));
setupDrawSimpleMesh();
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
@@ -3319,10 +3346,6 @@
void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
Texture* texture, const SkPaint* paint) {
- int alpha;
- SkXfermode::Mode mode;
- getAlphaAndMode(paint, &alpha, &mode);
-
texture->setWrap(GL_CLAMP_TO_EDGE, true);
GLvoid* vertices = (GLvoid*) NULL;
@@ -3344,11 +3367,11 @@
texture->setFilter(GL_NEAREST, true);
drawTextureMesh(x, y, x + texture->width, y + texture->height, texture->id,
- alpha / 255.0f, mode, texture->blend, vertices, texCoords,
+ paint, texture->blend, vertices, texCoords,
GL_TRIANGLE_STRIP, gMeshCount, false, true);
} else {
texture->setFilter(FILTER(paint), true);
- drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode,
+ drawTextureMesh(left, top, right, bottom, texture->id, paint,
texture->blend, vertices, texCoords, GL_TRIANGLE_STRIP, gMeshCount);
}
@@ -3357,75 +3380,84 @@
}
}
-void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
- GLuint texture, float alpha, SkXfermode::Mode mode, bool blend) {
- drawTextureMesh(left, top, right, bottom, texture, alpha, mode, blend,
- (GLvoid*) NULL, (GLvoid*) gMeshTextureOffset, GL_TRIANGLE_STRIP, gMeshCount);
-}
-
void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float bottom,
- GLuint texture, float alpha, SkXfermode::Mode mode, bool blend,
+ GLuint texture, const SkPaint* paint, bool blend,
GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
bool swapSrcDst, bool ignoreTransform, GLuint vbo,
ModelViewMode modelViewMode, bool dirty) {
+ int a;
+ SkXfermode::Mode mode;
+ getAlphaAndMode(paint, &a, &mode);
+ const float alpha = a / 255.0f;
+
setupDraw();
setupDrawWithTexture();
setupDrawColor(alpha, alpha, alpha, alpha);
- setupDrawColorFilter();
- setupDrawBlending(blend, mode, swapSrcDst);
+ setupDrawColorFilter(getColorFilter(paint));
+ setupDrawBlending(paint, blend, swapSrcDst);
setupDrawProgram();
if (!dirty) setupDrawDirtyRegionsDisabled();
setupDrawModelView(modelViewMode, false, left, top, right, bottom, ignoreTransform);
setupDrawTexture(texture);
setupDrawPureColorUniforms();
- setupDrawColorFilterUniforms();
+ setupDrawColorFilterUniforms(getColorFilter(paint));
setupDrawMesh(vertices, texCoords, vbo);
glDrawArrays(drawMode, 0, elementsCount);
}
void OpenGLRenderer::drawIndexedTextureMesh(float left, float top, float right, float bottom,
- GLuint texture, float alpha, SkXfermode::Mode mode, bool blend,
+ GLuint texture, const SkPaint* paint, bool blend,
GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
bool swapSrcDst, bool ignoreTransform, GLuint vbo,
ModelViewMode modelViewMode, bool dirty) {
+ int a;
+ SkXfermode::Mode mode;
+ getAlphaAndMode(paint, &a, &mode);
+ const float alpha = a / 255.0f;
+
setupDraw();
setupDrawWithTexture();
setupDrawColor(alpha, alpha, alpha, alpha);
- setupDrawColorFilter();
- setupDrawBlending(blend, mode, swapSrcDst);
+ setupDrawColorFilter(getColorFilter(paint));
+ setupDrawBlending(paint, blend, swapSrcDst);
setupDrawProgram();
if (!dirty) setupDrawDirtyRegionsDisabled();
setupDrawModelView(modelViewMode, false, left, top, right, bottom, ignoreTransform);
setupDrawTexture(texture);
setupDrawPureColorUniforms();
- setupDrawColorFilterUniforms();
+ setupDrawColorFilterUniforms(getColorFilter(paint));
setupDrawMeshIndices(vertices, texCoords, vbo);
glDrawElements(drawMode, elementsCount, GL_UNSIGNED_SHORT, NULL);
}
void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, float bottom,
- GLuint texture, bool hasColor, int color, int alpha, SkXfermode::Mode mode,
+ GLuint texture, const SkPaint* paint,
GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
bool ignoreTransform, ModelViewMode modelViewMode, bool dirty) {
+ int color = paint != NULL ? paint->getColor() : 0;
+ int alpha;
+ SkXfermode::Mode mode;
+ getAlphaAndMode(paint, &alpha, &mode);
+
setupDraw();
setupDrawWithTexture(true);
- if (hasColor) {
+ if (paint != NULL) {
setupDrawAlpha8Color(color, alpha);
}
- setupDrawColorFilter();
+ setupDrawColorFilter(getColorFilter(paint));
setupDrawShader();
- setupDrawBlending(true, mode);
+ setupDrawBlending(paint, true);
setupDrawProgram();
if (!dirty) setupDrawDirtyRegionsDisabled();
setupDrawModelView(modelViewMode, false, left, top, right, bottom, ignoreTransform);
setupDrawTexture(texture);
setupDrawPureColorUniforms();
- setupDrawColorFilterUniforms();
+ setupDrawColorFilterUniforms(getColorFilter(paint));
setupDrawShaderUniforms(ignoreTransform);
setupDrawMesh(vertices, texCoords);
@@ -3516,7 +3548,7 @@
*alpha *= currentSnapshot()->alpha;
}
-float OpenGLRenderer::getLayerAlpha(Layer* layer) const {
+float OpenGLRenderer::getLayerAlpha(const Layer* layer) const {
float alpha;
if (mDrawModifiers.mOverrideLayerAlpha < 1.0f) {
alpha = mDrawModifiers.mOverrideLayerAlpha;
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 131681e..e4d133d 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -21,6 +21,8 @@
#include <GLES2/gl2ext.h>
#include <SkBitmap.h>
+#include <SkCanvas.h>
+#include <SkColorFilter.h>
#include <SkMatrix.h>
#include <SkPaint.h>
#include <SkRegion.h>
@@ -43,7 +45,6 @@
#include "Rect.h"
#include "Renderer.h"
#include "StatefulBaseRenderer.h"
-#include "SkiaColorFilter.h"
#include "Snapshot.h"
#include "UvMapper.h"
#include "Vertex.h"
@@ -68,7 +69,6 @@
}
SkiaShader* mShader;
- SkiaColorFilter* mColorFilter;
float mOverrideLayerAlpha;
// Drop shadow
@@ -209,9 +209,6 @@
virtual void resetShader();
virtual void setupShader(SkiaShader* shader);
- virtual void resetColorFilter();
- virtual void setupColorFilter(SkiaColorFilter* filter);
-
virtual void resetShadow();
virtual void setupShadow(float radius, float dx, float dy, int color);
@@ -432,18 +429,14 @@
*
* @param layer The layer from which the alpha is extracted
*/
- inline float getLayerAlpha(Layer* layer) const;
+ inline float getLayerAlpha(const Layer* layer) const;
/**
- * Safely retrieves the mode from the specified xfermode. If the specified
- * xfermode is null, the mode is assumed to be SkXfermode::kSrcOver_Mode.
+ * Safely retrieves the ColorFilter from the given Paint. If the paint is
+ * null then null is returned.
*/
- static inline SkXfermode::Mode getXfermode(SkXfermode* mode) {
- SkXfermode::Mode resultMode;
- if (!SkXfermode::AsMode(mode, &resultMode)) {
- resultMode = SkXfermode::kSrcOver_Mode;
- }
- return resultMode;
+ static inline SkColorFilter* getColorFilter(const SkPaint* paint) {
+ return paint ? paint->getColorFilter() : NULL;
}
/**
@@ -584,12 +577,11 @@
* @param top The top coordinate of the rectangle
* @param right The right coordinate of the rectangle
* @param bottom The bottom coordinate of the rectangle
- * @param color The rectangle's ARGB color, defined as a packed 32 bits word
- * @param mode The Skia xfermode to use
+ * @param paint The paint containing the color, blending mode, etc.
* @param ignoreTransform True if the current transform should be ignored
*/
void drawColorRect(float left, float top, float right, float bottom,
- int color, SkXfermode::Mode mode, bool ignoreTransform = false);
+ const SkPaint* paint, bool ignoreTransform = false);
/**
* Draws a series of colored rectangles with the specified color. The specified
@@ -598,15 +590,13 @@
*
* @param rects A list of rectangles, 4 floats (left, top, right, bottom)
* per rectangle
- * @param color The rectangles' ARGB color, defined as a packed 32 bits word
- * @param mode The Skia xfermode to use
+ * @param paint The paint containing the color, blending mode, etc.
* @param ignoreTransform True if the current transform should be ignored
* @param dirty True if calling this method should dirty the current layer
* @param clip True if the rects should be clipped, false otherwise
*/
- status_t drawColorRects(const float* rects, int count, int color,
- SkXfermode::Mode mode, bool ignoreTransform = false,
- bool dirty = true, bool clip = true);
+ status_t drawColorRects(const float* rects, int count, const SkPaint* paint,
+ bool ignoreTransform = false, bool dirty = true, bool clip = true);
/**
* Draws the shape represented by the specified path texture.
@@ -658,22 +648,6 @@
* @param top The top coordinate of the rectangle
* @param right The right coordinate of the rectangle
* @param bottom The bottom coordinate of the rectangle
- * @param texture The texture name to map onto the rectangle
- * @param alpha An additional translucency parameter, between 0.0f and 1.0f
- * @param mode The blending mode
- * @param blend True if the texture contains an alpha channel
- */
- void drawTextureRect(float left, float top, float right, float bottom, GLuint texture,
- float alpha, SkXfermode::Mode mode, bool blend);
-
- /**
- * Draws a textured rectangle with the specified texture. The specified coordinates
- * are transformed by the current snapshot's transform matrix.
- *
- * @param left The left coordinate of the rectangle
- * @param top The top coordinate of the rectangle
- * @param right The right coordinate of the rectangle
- * @param bottom The bottom coordinate of the rectangle
* @param texture The texture to use
* @param paint The paint containing the alpha, blending mode, etc.
*/
@@ -690,8 +664,7 @@
* @param right The right coordinate of the rectangle
* @param bottom The bottom coordinate of the rectangle
* @param texture The texture name to map onto the rectangle
- * @param alpha An additional translucency parameter, between 0.0f and 1.0f
- * @param mode The blending mode
+ * @param paint The paint containing the alpha, blending mode, colorFilter, etc.
* @param blend True if the texture contains an alpha channel
* @param vertices The vertices that define the mesh
* @param texCoords The texture coordinates of each vertex
@@ -703,19 +676,19 @@
* @param dirty True if calling this method should dirty the current layer
*/
void drawTextureMesh(float left, float top, float right, float bottom, GLuint texture,
- float alpha, SkXfermode::Mode mode, bool blend,
+ const SkPaint* paint, bool blend,
GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
bool swapSrcDst = false, bool ignoreTransform = false, GLuint vbo = 0,
ModelViewMode modelViewMode = kModelViewMode_TranslateAndScale, bool dirty = true);
void drawIndexedTextureMesh(float left, float top, float right, float bottom, GLuint texture,
- float alpha, SkXfermode::Mode mode, bool blend,
+ const SkPaint* paint, bool blend,
GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
bool swapSrcDst = false, bool ignoreTransform = false, GLuint vbo = 0,
ModelViewMode modelViewMode = kModelViewMode_TranslateAndScale, bool dirty = true);
void drawAlpha8TextureMesh(float left, float top, float right, float bottom,
- GLuint texture, bool hasColor, int color, int alpha, SkXfermode::Mode mode,
+ GLuint texture, const SkPaint* paint,
GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
bool ignoreTransform, ModelViewMode modelViewMode = kModelViewMode_TranslateAndScale,
bool dirty = true);
@@ -749,12 +722,11 @@
* @param positions The x, y positions of individual glyphs (or NULL)
* @param fontRenderer The font renderer object
* @param alpha The alpha value for drawing the shadow
- * @param mode The xfermode for drawing the shadow
* @param x The x coordinate where the shadow will be drawn
* @param y The y coordinate where the shadow will be drawn
*/
void drawTextShadow(const SkPaint* paint, const char* text, int bytesCount, int count,
- const float* positions, FontRenderer& fontRenderer, int alpha, SkXfermode::Mode mode,
+ const float* positions, FontRenderer& fontRenderer, int alpha,
float x, float y);
/**
@@ -839,11 +811,9 @@
void setupDrawAlpha8Color(int color, int alpha);
void setupDrawTextGamma(const SkPaint* paint);
void setupDrawShader();
- void setupDrawColorFilter();
- void setupDrawBlending(SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode,
- bool swapSrcDst = false);
- void setupDrawBlending(bool blend = true, SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode,
- bool swapSrcDst = false);
+ void setupDrawColorFilter(const SkColorFilter* filter);
+ void setupDrawBlending(const Layer* layer, bool swapSrcDst = false);
+ void setupDrawBlending(const SkPaint* paint, bool blend = true, bool swapSrcDst = false);
void setupDrawProgram();
void setupDrawDirtyRegionsDisabled();
@@ -867,7 +837,7 @@
void setupDrawColorUniforms();
void setupDrawPureColorUniforms();
void setupDrawShaderUniforms(bool ignoreTransform = false);
- void setupDrawColorFilterUniforms();
+ void setupDrawColorFilterUniforms(const SkColorFilter* paint);
void setupDrawSimpleMesh();
void setupDrawTexture(GLuint texture);
void setupDrawExternalTexture(GLuint texture);
@@ -896,8 +866,7 @@
* Renders the specified region as a series of rectangles. The region
* must be in screen-space coordinates.
*/
- void drawRegionRects(const SkRegion& region, int color, SkXfermode::Mode mode,
- bool dirty = false);
+ void drawRegionRects(const SkRegion& region, const SkPaint& paint, bool dirty = false);
/**
* Draws the current clip region if any. Only when DEBUG_CLIP_REGIONS
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index 5dfb2fa..33c91b3 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -51,9 +51,8 @@
#define PROGRAM_KEY_GRADIENT 0x8
#define PROGRAM_KEY_BITMAP_FIRST 0x10
#define PROGRAM_KEY_COLOR_MATRIX 0x20
-#define PROGRAM_KEY_COLOR_LIGHTING 0x40
-#define PROGRAM_KEY_COLOR_BLEND 0x80
-#define PROGRAM_KEY_BITMAP_NPOT 0x100
+#define PROGRAM_KEY_COLOR_BLEND 0x40
+#define PROGRAM_KEY_BITMAP_NPOT 0x80
#define PROGRAM_KEY_SWAP_SRC_DST 0x2000
#define PROGRAM_KEY_BITMAP_WRAPS_MASK 0x600
@@ -104,7 +103,6 @@
enum ColorModifier {
kColorNone = 0,
kColorMatrix,
- kColorLighting,
kColorBlend
};
@@ -248,9 +246,6 @@
case kColorMatrix:
key |= PROGRAM_KEY_COLOR_MATRIX;
break;
- case kColorLighting:
- key |= PROGRAM_KEY_COLOR_LIGHTING;
- break;
case kColorBlend:
key |= PROGRAM_KEY_COLOR_BLEND;
key |= (colorMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_COLOR_OP_SHIFT;
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index a5ce6f6..6d50410 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -148,15 +148,12 @@
};
const char* gFS_Uniforms_BitmapSampler =
"uniform sampler2D bitmapSampler;\n";
-const char* gFS_Uniforms_ColorOp[4] = {
+const char* gFS_Uniforms_ColorOp[3] = {
// None
"",
// Matrix
"uniform mat4 colorMatrix;\n"
"uniform vec4 colorMatrixVector;\n",
- // Lighting
- "uniform vec4 lightingMul;\n"
- "uniform vec4 lightingAdd;\n",
// PorterDuff
"uniform vec4 colorBlend;\n"
};
@@ -311,17 +308,13 @@
" gl_FragColor = blendFramebuffer(fragColor, gl_LastFragColor);\n";
const char* gFS_Main_FragColor_Blend_Swap =
" gl_FragColor = blendFramebuffer(gl_LastFragColor, fragColor);\n";
-const char* gFS_Main_ApplyColorOp[4] = {
+const char* gFS_Main_ApplyColorOp[3] = {
// None
"",
// Matrix
" fragColor *= colorMatrix;\n"
" fragColor += colorMatrixVector;\n"
" fragColor.rgb *= fragColor.a;\n",
- // Lighting
- " float lightingAlpha = fragColor.a;\n"
- " fragColor = min(fragColor * lightingMul + (lightingAdd * lightingAlpha), lightingAlpha);\n"
- " fragColor.a = lightingAlpha;\n",
// PorterDuff
" fragColor = blendColors(colorBlend, fragColor);\n"
};
diff --git a/libs/hwui/Renderer.h b/libs/hwui/Renderer.h
index 058548a..4754bad 100644
--- a/libs/hwui/Renderer.h
+++ b/libs/hwui/Renderer.h
@@ -178,9 +178,6 @@
virtual void resetShader() = 0;
virtual void setupShader(SkiaShader* shader) = 0;
- virtual void resetColorFilter() = 0;
- virtual void setupColorFilter(SkiaColorFilter* filter) = 0;
-
virtual void resetShadow() = 0;
virtual void setupShadow(float radius, float dx, float dy, int color) = 0;
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index e58857c..457cfa9 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -76,11 +76,6 @@
incrementRefcount((void*) shaderResource, kShader);
}
-void ResourceCache::incrementRefcount(SkiaColorFilter* filterResource) {
- SkSafeRef(filterResource->getSkColorFilter());
- incrementRefcount((void*) filterResource, kColorFilter);
-}
-
void ResourceCache::incrementRefcount(const Res_png_9patch* patchResource) {
incrementRefcount((void*) patchResource, kNinePatch);
}
@@ -114,11 +109,6 @@
incrementRefcountLocked((void*) shaderResource, kShader);
}
-void ResourceCache::incrementRefcountLocked(SkiaColorFilter* filterResource) {
- SkSafeRef(filterResource->getSkColorFilter());
- incrementRefcountLocked((void*) filterResource, kColorFilter);
-}
-
void ResourceCache::incrementRefcountLocked(const Res_png_9patch* patchResource) {
incrementRefcountLocked((void*) patchResource, kNinePatch);
}
@@ -147,11 +137,6 @@
decrementRefcount((void*) shaderResource);
}
-void ResourceCache::decrementRefcount(SkiaColorFilter* filterResource) {
- SkSafeUnref(filterResource->getSkColorFilter());
- decrementRefcount((void*) filterResource);
-}
-
void ResourceCache::decrementRefcount(const Res_png_9patch* patchResource) {
decrementRefcount((void*) patchResource);
}
@@ -188,11 +173,6 @@
decrementRefcountLocked((void*) shaderResource);
}
-void ResourceCache::decrementRefcountLocked(SkiaColorFilter* filterResource) {
- SkSafeUnref(filterResource->getSkColorFilter());
- decrementRefcountLocked((void*) filterResource);
-}
-
void ResourceCache::decrementRefcountLocked(const Res_png_9patch* patchResource) {
decrementRefcountLocked((void*) patchResource);
}
@@ -264,25 +244,6 @@
}
}
-void ResourceCache::destructor(SkiaColorFilter* resource) {
- Mutex::Autolock _l(mLock);
- destructorLocked(resource);
-}
-
-void ResourceCache::destructorLocked(SkiaColorFilter* resource) {
- ssize_t index = mCache->indexOfKey(resource);
- ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
- if (ref == NULL) {
- // If we're not tracking this resource, just delete it
- delete resource;
- return;
- }
- ref->destroyed = true;
- if (ref->refCount == 0) {
- deleteResourceReferenceLocked(resource, ref);
- }
-}
-
void ResourceCache::destructor(Res_png_9patch* resource) {
Mutex::Autolock _l(mLock);
destructorLocked(resource);
@@ -372,11 +333,6 @@
delete shader;
}
break;
- case kColorFilter: {
- SkiaColorFilter* filter = (SkiaColorFilter*) resource;
- delete filter;
- }
- break;
case kNinePatch: {
if (Caches::hasInstance()) {
Caches::getInstance().patchCache.removeDeferred((Res_png_9patch*) resource);
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index c06b09b..4097ba4 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -20,7 +20,6 @@
#include <cutils/compiler.h>
#include <SkBitmap.h>
-#include <SkiaColorFilter.h>
#include <SkiaShader.h>
#include <utils/KeyedVector.h>
@@ -38,7 +37,6 @@
enum ResourceType {
kBitmap,
kShader,
- kColorFilter,
kNinePatch,
kPath,
kLayer
@@ -73,41 +71,35 @@
void incrementRefcount(const SkPath* resource);
void incrementRefcount(const SkBitmap* resource);
void incrementRefcount(SkiaShader* resource);
- void incrementRefcount(SkiaColorFilter* resource);
void incrementRefcount(const Res_png_9patch* resource);
void incrementRefcount(Layer* resource);
void incrementRefcountLocked(const SkPath* resource);
void incrementRefcountLocked(const SkBitmap* resource);
void incrementRefcountLocked(SkiaShader* resource);
- void incrementRefcountLocked(SkiaColorFilter* resource);
void incrementRefcountLocked(const Res_png_9patch* resource);
void incrementRefcountLocked(Layer* resource);
void decrementRefcount(const SkBitmap* resource);
void decrementRefcount(const SkPath* resource);
void decrementRefcount(SkiaShader* resource);
- void decrementRefcount(SkiaColorFilter* resource);
void decrementRefcount(const Res_png_9patch* resource);
void decrementRefcount(Layer* resource);
void decrementRefcountLocked(const SkBitmap* resource);
void decrementRefcountLocked(const SkPath* resource);
void decrementRefcountLocked(SkiaShader* resource);
- void decrementRefcountLocked(SkiaColorFilter* resource);
void decrementRefcountLocked(const Res_png_9patch* resource);
void decrementRefcountLocked(Layer* resource);
void destructor(SkPath* resource);
void destructor(const SkBitmap* resource);
void destructor(SkiaShader* resource);
- void destructor(SkiaColorFilter* resource);
void destructor(Res_png_9patch* resource);
void destructorLocked(SkPath* resource);
void destructorLocked(const SkBitmap* resource);
void destructorLocked(SkiaShader* resource);
- void destructorLocked(SkiaColorFilter* resource);
void destructorLocked(Res_png_9patch* resource);
bool recycle(SkBitmap* resource);
diff --git a/libs/hwui/SkiaColorFilter.cpp b/libs/hwui/SkiaColorFilter.cpp
deleted file mode 100644
index df918be..0000000
--- a/libs/hwui/SkiaColorFilter.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "SkiaColorFilter.h"
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Base color filter
-///////////////////////////////////////////////////////////////////////////////
-
-SkiaColorFilter::SkiaColorFilter(SkColorFilter *skFilter, Type type, bool blend):
- mType(type), mBlend(blend), mSkFilter(skFilter) {
-}
-
-SkiaColorFilter::~SkiaColorFilter() {
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Color matrix filter
-///////////////////////////////////////////////////////////////////////////////
-
-SkiaColorMatrixFilter::SkiaColorMatrixFilter(SkColorFilter* skFilter, float* matrix, float* vector):
- SkiaColorFilter(skFilter, kColorMatrix, true), mMatrix(matrix), mVector(vector) {
- // Skia uses the range [0..255] for the addition vector, but we need
- // the [0..1] range to apply the vector in GLSL
- for (int i = 0; i < 4; i++) {
- mVector[i] /= 255.0f;
- }
-
- // TODO: We should be smarter about this
- mBlend = true;
-}
-
-SkiaColorMatrixFilter::~SkiaColorMatrixFilter() {
- delete[] mMatrix;
- delete[] mVector;
-}
-
-void SkiaColorMatrixFilter::describe(ProgramDescription& description,
- const Extensions& extensions) {
- description.colorOp = ProgramDescription::kColorMatrix;
-}
-
-void SkiaColorMatrixFilter::setupProgram(Program* program) {
- glUniformMatrix4fv(program->getUniform("colorMatrix"), 1, GL_FALSE, &mMatrix[0]);
- glUniform4fv(program->getUniform("colorMatrixVector"), 1, mVector);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Lighting color filter
-///////////////////////////////////////////////////////////////////////////////
-
-SkiaLightingFilter::SkiaLightingFilter(SkColorFilter* skFilter, int multiply, int add):
- SkiaColorFilter(skFilter, kLighting, true) {
- mMulR = ((multiply >> 16) & 0xFF) / 255.0f;
- mMulG = ((multiply >> 8) & 0xFF) / 255.0f;
- mMulB = ((multiply ) & 0xFF) / 255.0f;
-
- mAddR = ((add >> 16) & 0xFF) / 255.0f;
- mAddG = ((add >> 8) & 0xFF) / 255.0f;
- mAddB = ((add ) & 0xFF) / 255.0f;
-
- // A lighting filter always ignores alpha
- mBlend = false;
-}
-
-void SkiaLightingFilter::describe(ProgramDescription& description, const Extensions& extensions) {
- description.colorOp = ProgramDescription::kColorLighting;
-}
-
-void SkiaLightingFilter::setupProgram(Program* program) {
- glUniform4f(program->getUniform("lightingMul"), mMulR, mMulG, mMulB, 1.0f);
- glUniform4f(program->getUniform("lightingAdd"), mAddR, mAddG, mAddB, 0.0f);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Blend color filter
-///////////////////////////////////////////////////////////////////////////////
-
-SkiaBlendFilter::SkiaBlendFilter(SkColorFilter* skFilter, int color, SkXfermode::Mode mode):
- SkiaColorFilter(skFilter, kBlend, true), mMode(mode) {
- const int alpha = (color >> 24) & 0xFF;
- mA = alpha / 255.0f;
- mR = mA * ((color >> 16) & 0xFF) / 255.0f;
- mG = mA * ((color >> 8) & 0xFF) / 255.0f;
- mB = mA * ((color ) & 0xFF) / 255.0f;
-
- // TODO: We should do something smarter here
- mBlend = true;
-}
-
-void SkiaBlendFilter::describe(ProgramDescription& description, const Extensions& extensions) {
- description.colorOp = ProgramDescription::kColorBlend;
- description.colorMode = mMode;
-}
-
-void SkiaBlendFilter::setupProgram(Program* program) {
- glUniform4f(program->getUniform("colorBlend"), mR, mG, mB, mA);
-}
-
-}; // namespace uirenderer
-}; // namespace android
diff --git a/libs/hwui/SkiaColorFilter.h b/libs/hwui/SkiaColorFilter.h
deleted file mode 100644
index c222a2d..0000000
--- a/libs/hwui/SkiaColorFilter.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HWUI_SKIA_COLOR_FILTER_H
-#define ANDROID_HWUI_SKIA_COLOR_FILTER_H
-
-#include <GLES2/gl2.h>
-#include <SkColorFilter.h>
-
-#include <cutils/compiler.h>
-
-#include "ProgramCache.h"
-#include "Extensions.h"
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Base color filter
-///////////////////////////////////////////////////////////////////////////////
-
-/**
- * Represents a Skia color filter. A color filter modifies a ProgramDescription
- * and sets uniforms on the resulting shaders.
- */
-class SkiaColorFilter {
-public:
- /**
- * Type of Skia color filter in use.
- */
- enum Type {
- kNone,
- kColorMatrix,
- kLighting,
- kBlend,
- };
-
- ANDROID_API SkiaColorFilter(SkColorFilter *skFilter, Type type, bool blend);
- virtual ~SkiaColorFilter();
-
- virtual void describe(ProgramDescription& description, const Extensions& extensions) = 0;
- virtual void setupProgram(Program* program) = 0;
-
- inline bool blend() const {
- return mBlend;
- }
-
- Type type() const {
- return mType;
- }
-
- SkColorFilter* getSkColorFilter() {
- return mSkFilter;
- }
-
-protected:
- Type mType;
- bool mBlend;
-
-private:
- SkColorFilter *mSkFilter;
-}; // struct SkiaColorFilter
-
-///////////////////////////////////////////////////////////////////////////////
-// Implementations
-///////////////////////////////////////////////////////////////////////////////
-
-/**
- * A color filter that multiplies the source color with a matrix and adds a vector.
- */
-class SkiaColorMatrixFilter: public SkiaColorFilter {
-public:
- ANDROID_API SkiaColorMatrixFilter(SkColorFilter *skFilter, float* matrix, float* vector);
- ~SkiaColorMatrixFilter();
-
- void describe(ProgramDescription& description, const Extensions& extensions);
- void setupProgram(Program* program);
-
-private:
- float* mMatrix;
- float* mVector;
-}; // struct SkiaColorMatrixFilter
-
-/**
- * A color filters that multiplies the source color with a fixed value and adds
- * another fixed value. Ignores the alpha channel of both arguments.
- */
-class SkiaLightingFilter: public SkiaColorFilter {
-public:
- ANDROID_API SkiaLightingFilter(SkColorFilter *skFilter, int multiply, int add);
-
- void describe(ProgramDescription& description, const Extensions& extensions);
- void setupProgram(Program* program);
-
-private:
- GLfloat mMulR, mMulG, mMulB;
- GLfloat mAddR, mAddG, mAddB;
-}; // struct SkiaLightingFilter
-
-/**
- * A color filters that blends the source color with a specified destination color
- * and PorterDuff blending mode.
- */
-class SkiaBlendFilter: public SkiaColorFilter {
-public:
- ANDROID_API SkiaBlendFilter(SkColorFilter *skFilter, int color, SkXfermode::Mode mode);
-
- void describe(ProgramDescription& description, const Extensions& extensions);
- void setupProgram(Program* program);
-
-private:
- SkXfermode::Mode mMode;
- GLfloat mR, mG, mB, mA;
-}; // struct SkiaBlendFilter
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_SKIA_COLOR_FILTER_H
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index a848c8f..4e665d9 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -462,6 +462,16 @@
mRenderThread.queueDelayed(&mInvokeFunctorsTask, delayMs);
}
+void CanvasContext::runWithGlContext(RenderTask* task) {
+ if (mEglSurface != EGL_NO_SURFACE) {
+ mGlobalContext->makeCurrent(mEglSurface);
+ } else {
+ mGlobalContext->usePBufferSurface();
+ }
+
+ task->run();
+}
+
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 2daa905..3197df3 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -65,6 +65,8 @@
void attachFunctor(Functor* functor);
void detachFunctor(Functor* functor);
+ void runWithGlContext(RenderTask* task);
+
private:
void setSurface(EGLNativeWindowType window);
void swapBuffers();
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 25badac..34f1961 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -170,6 +170,18 @@
post(task);
}
+CREATE_BRIDGE2(runWithGlContext, CanvasContext* context, RenderTask* task) {
+ args->context->runWithGlContext(args->task);
+ return NULL;
+}
+
+void RenderProxy::runWithGlContext(RenderTask* gltask) {
+ SETUP_TASK(runWithGlContext);
+ args->context = mContext;
+ args->task = gltask;
+ postAndWait(task);
+}
+
MethodInvokeRenderTask* RenderProxy::createTask(RunnableMethod method) {
// TODO: Consider having a small pool of these to avoid alloc churn
return new MethodInvokeRenderTask(method);
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 113c5a8..1ad0c2d 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -62,6 +62,8 @@
ANDROID_API void attachFunctor(Functor* functor);
ANDROID_API void detachFunctor(Functor* functor);
+ ANDROID_API void runWithGlContext(RenderTask* task);
+
private:
RenderThread& mRenderThread;
CanvasContext* mContext;
diff --git a/libs/hwui/utils/TinyHashMap.h b/libs/hwui/utils/TinyHashMap.h
index 8855140..4ff9a42 100644
--- a/libs/hwui/utils/TinyHashMap.h
+++ b/libs/hwui/utils/TinyHashMap.h
@@ -24,8 +24,6 @@
/**
* A very simple hash map that doesn't allow duplicate keys, overwriting the older entry.
- *
- * Currently, expects simple keys that are handled by hash_t()
*/
template <typename TKey, typename TValue>
class TinyHashMap {
@@ -36,7 +34,7 @@
* Puts an entry in the hash, removing any existing entry with the same key
*/
void put(TKey key, TValue value) {
- hash_t hash = hash_t(key);
+ hash_t hash = android::hash_type(key);
ssize_t index = mTable.find(-1, hash, key);
if (index != -1) {
@@ -51,7 +49,7 @@
* Return true if key is in the map, in which case stores the value in the output ref
*/
bool get(TKey key, TValue& outValue) {
- hash_t hash = hash_t(key);
+ hash_t hash = android::hash_type(key);
ssize_t index = mTable.find(-1, hash, key);
if (index == -1) {
return false;
diff --git a/libs/input/Android.mk b/libs/input/Android.mk
index eb2bebe..6011ff0 100644
--- a/libs/input/Android.mk
+++ b/libs/input/Android.mk
@@ -17,30 +17,23 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- EventHub.cpp \
- InputApplication.cpp \
- InputDispatcher.cpp \
- InputListener.cpp \
- InputManager.cpp \
- InputReader.cpp \
- InputWindow.cpp \
PointerController.cpp \
SpriteController.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
liblog \
- libandroidfw \
libutils \
- libhardware \
- libhardware_legacy \
libskia \
libgui \
libui \
- libinput
+ libinput \
+ libinputflinger
LOCAL_C_INCLUDES := \
- external/skia/include/core
+ external/skia/include/core \
+ frameworks/native/services
+
LOCAL_CFLAGS += -Wno-unused-parameter
diff --git a/libs/input/EventHub.cpp b/libs/input/EventHub.cpp
deleted file mode 100644
index e2efd17..0000000
--- a/libs/input/EventHub.cpp
+++ /dev/null
@@ -1,1669 +0,0 @@
-/*
- * Copyright (C) 2005 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "EventHub"
-
-// #define LOG_NDEBUG 0
-
-#include "EventHub.h"
-
-#include <hardware_legacy/power.h>
-
-#include <cutils/properties.h>
-#include <utils/Log.h>
-#include <utils/Timers.h>
-#include <utils/threads.h>
-#include <utils/Errors.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <memory.h>
-#include <errno.h>
-#include <assert.h>
-
-#include <input/KeyLayoutMap.h>
-#include <input/KeyCharacterMap.h>
-#include <input/VirtualKeyMap.h>
-
-#include <string.h>
-#include <stdint.h>
-#include <dirent.h>
-
-#include <sys/inotify.h>
-#include <sys/epoll.h>
-#include <sys/ioctl.h>
-#include <sys/limits.h>
-#include <sys/sha1.h>
-#include <sys/utsname.h>
-
-/* this macro is used to tell if "bit" is set in "array"
- * it selects a byte from the array, and does a boolean AND
- * operation with a byte that only has the relevant bit set.
- * eg. to check for the 12th bit, we do (array[1] & 1<<4)
- */
-#define test_bit(bit, array) (array[bit/8] & (1<<(bit%8)))
-
-/* this macro computes the number of bytes needed to represent a bit array of the specified size */
-#define sizeof_bit_array(bits) ((bits + 7) / 8)
-
-#define INDENT " "
-#define INDENT2 " "
-#define INDENT3 " "
-
-namespace android {
-
-static const char *WAKE_LOCK_ID = "KeyEvents";
-static const char *DEVICE_PATH = "/dev/input";
-
-/* return the larger integer */
-static inline int max(int v1, int v2)
-{
- return (v1 > v2) ? v1 : v2;
-}
-
-static inline const char* toString(bool value) {
- return value ? "true" : "false";
-}
-
-static String8 sha1(const String8& in) {
- SHA1_CTX ctx;
- SHA1Init(&ctx);
- SHA1Update(&ctx, reinterpret_cast<const u_char*>(in.string()), in.size());
- u_char digest[SHA1_DIGEST_LENGTH];
- SHA1Final(digest, &ctx);
-
- String8 out;
- for (size_t i = 0; i < SHA1_DIGEST_LENGTH; i++) {
- out.appendFormat("%02x", digest[i]);
- }
- return out;
-}
-
-static void getLinuxRelease(int* major, int* minor) {
- struct utsname info;
- if (uname(&info) || sscanf(info.release, "%d.%d", major, minor) <= 0) {
- *major = 0, *minor = 0;
- ALOGE("Could not get linux version: %s", strerror(errno));
- }
-}
-
-// --- Global Functions ---
-
-uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses) {
- // Touch devices get dibs on touch-related axes.
- if (deviceClasses & INPUT_DEVICE_CLASS_TOUCH) {
- switch (axis) {
- case ABS_X:
- case ABS_Y:
- case ABS_PRESSURE:
- case ABS_TOOL_WIDTH:
- case ABS_DISTANCE:
- case ABS_TILT_X:
- case ABS_TILT_Y:
- case ABS_MT_SLOT:
- case ABS_MT_TOUCH_MAJOR:
- case ABS_MT_TOUCH_MINOR:
- case ABS_MT_WIDTH_MAJOR:
- case ABS_MT_WIDTH_MINOR:
- case ABS_MT_ORIENTATION:
- case ABS_MT_POSITION_X:
- case ABS_MT_POSITION_Y:
- case ABS_MT_TOOL_TYPE:
- case ABS_MT_BLOB_ID:
- case ABS_MT_TRACKING_ID:
- case ABS_MT_PRESSURE:
- case ABS_MT_DISTANCE:
- return INPUT_DEVICE_CLASS_TOUCH;
- }
- }
-
- // Joystick devices get the rest.
- return deviceClasses & INPUT_DEVICE_CLASS_JOYSTICK;
-}
-
-// --- EventHub::Device ---
-
-EventHub::Device::Device(int fd, int32_t id, const String8& path,
- const InputDeviceIdentifier& identifier) :
- next(NULL),
- fd(fd), id(id), path(path), identifier(identifier),
- classes(0), configuration(NULL), virtualKeyMap(NULL),
- ffEffectPlaying(false), ffEffectId(-1), controllerNumber(0),
- timestampOverrideSec(0), timestampOverrideUsec(0) {
- memset(keyBitmask, 0, sizeof(keyBitmask));
- memset(absBitmask, 0, sizeof(absBitmask));
- memset(relBitmask, 0, sizeof(relBitmask));
- memset(swBitmask, 0, sizeof(swBitmask));
- memset(ledBitmask, 0, sizeof(ledBitmask));
- memset(ffBitmask, 0, sizeof(ffBitmask));
- memset(propBitmask, 0, sizeof(propBitmask));
-}
-
-EventHub::Device::~Device() {
- close();
- delete configuration;
- delete virtualKeyMap;
-}
-
-void EventHub::Device::close() {
- if (fd >= 0) {
- ::close(fd);
- fd = -1;
- }
-}
-
-
-// --- EventHub ---
-
-const uint32_t EventHub::EPOLL_ID_INOTIFY;
-const uint32_t EventHub::EPOLL_ID_WAKE;
-const int EventHub::EPOLL_SIZE_HINT;
-const int EventHub::EPOLL_MAX_EVENTS;
-
-EventHub::EventHub(void) :
- mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),
- mOpeningDevices(0), mClosingDevices(0),
- mNeedToSendFinishedDeviceScan(false),
- mNeedToReopenDevices(false), mNeedToScanDevices(true),
- mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
- acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
-
- mEpollFd = epoll_create(EPOLL_SIZE_HINT);
- LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno);
-
- mINotifyFd = inotify_init();
- int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
- LOG_ALWAYS_FATAL_IF(result < 0, "Could not register INotify for %s. errno=%d",
- DEVICE_PATH, errno);
-
- struct epoll_event eventItem;
- memset(&eventItem, 0, sizeof(eventItem));
- eventItem.events = EPOLLIN;
- eventItem.data.u32 = EPOLL_ID_INOTIFY;
- result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance. errno=%d", errno);
-
- int wakeFds[2];
- result = pipe(wakeFds);
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno);
-
- mWakeReadPipeFd = wakeFds[0];
- mWakeWritePipeFd = wakeFds[1];
-
- result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d",
- errno);
-
- result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d",
- errno);
-
- eventItem.data.u32 = EPOLL_ID_WAKE;
- result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
- LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d",
- errno);
-
- int major, minor;
- getLinuxRelease(&major, &minor);
- // EPOLLWAKEUP was introduced in kernel 3.5
- mUsingEpollWakeup = major > 3 || (major == 3 && minor >= 5);
-}
-
-EventHub::~EventHub(void) {
- closeAllDevicesLocked();
-
- while (mClosingDevices) {
- Device* device = mClosingDevices;
- mClosingDevices = device->next;
- delete device;
- }
-
- ::close(mEpollFd);
- ::close(mINotifyFd);
- ::close(mWakeReadPipeFd);
- ::close(mWakeWritePipeFd);
-
- release_wake_lock(WAKE_LOCK_ID);
-}
-
-InputDeviceIdentifier EventHub::getDeviceIdentifier(int32_t deviceId) const {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device == NULL) return InputDeviceIdentifier();
- return device->identifier;
-}
-
-uint32_t EventHub::getDeviceClasses(int32_t deviceId) const {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device == NULL) return 0;
- return device->classes;
-}
-
-int32_t EventHub::getDeviceControllerNumber(int32_t deviceId) const {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device == NULL) return 0;
- return device->controllerNumber;
-}
-
-void EventHub::getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device && device->configuration) {
- *outConfiguration = *device->configuration;
- } else {
- outConfiguration->clear();
- }
-}
-
-status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,
- RawAbsoluteAxisInfo* outAxisInfo) const {
- outAxisInfo->clear();
-
- if (axis >= 0 && axis <= ABS_MAX) {
- AutoMutex _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual() && test_bit(axis, device->absBitmask)) {
- struct input_absinfo info;
- if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
- ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
- axis, device->identifier.name.string(), device->fd, errno);
- return -errno;
- }
-
- if (info.minimum != info.maximum) {
- outAxisInfo->valid = true;
- outAxisInfo->minValue = info.minimum;
- outAxisInfo->maxValue = info.maximum;
- outAxisInfo->flat = info.flat;
- outAxisInfo->fuzz = info.fuzz;
- outAxisInfo->resolution = info.resolution;
- }
- return OK;
- }
- }
- return -1;
-}
-
-bool EventHub::hasRelativeAxis(int32_t deviceId, int axis) const {
- if (axis >= 0 && axis <= REL_MAX) {
- AutoMutex _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device) {
- return test_bit(axis, device->relBitmask);
- }
- }
- return false;
-}
-
-bool EventHub::hasInputProperty(int32_t deviceId, int property) const {
- if (property >= 0 && property <= INPUT_PROP_MAX) {
- AutoMutex _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device) {
- return test_bit(property, device->propBitmask);
- }
- }
- return false;
-}
-
-int32_t EventHub::getScanCodeState(int32_t deviceId, int32_t scanCode) const {
- if (scanCode >= 0 && scanCode <= KEY_MAX) {
- AutoMutex _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual() && test_bit(scanCode, device->keyBitmask)) {
- uint8_t keyState[sizeof_bit_array(KEY_MAX + 1)];
- memset(keyState, 0, sizeof(keyState));
- if (ioctl(device->fd, EVIOCGKEY(sizeof(keyState)), keyState) >= 0) {
- return test_bit(scanCode, keyState) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
- }
- }
- }
- return AKEY_STATE_UNKNOWN;
-}
-
-int32_t EventHub::getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
- AutoMutex _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual() && device->keyMap.haveKeyLayout()) {
- Vector<int32_t> scanCodes;
- device->keyMap.keyLayoutMap->findScanCodesForKey(keyCode, &scanCodes);
- if (scanCodes.size() != 0) {
- uint8_t keyState[sizeof_bit_array(KEY_MAX + 1)];
- memset(keyState, 0, sizeof(keyState));
- if (ioctl(device->fd, EVIOCGKEY(sizeof(keyState)), keyState) >= 0) {
- for (size_t i = 0; i < scanCodes.size(); i++) {
- int32_t sc = scanCodes.itemAt(i);
- if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, keyState)) {
- return AKEY_STATE_DOWN;
- }
- }
- return AKEY_STATE_UP;
- }
- }
- }
- return AKEY_STATE_UNKNOWN;
-}
-
-int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const {
- if (sw >= 0 && sw <= SW_MAX) {
- AutoMutex _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual() && test_bit(sw, device->swBitmask)) {
- uint8_t swState[sizeof_bit_array(SW_MAX + 1)];
- memset(swState, 0, sizeof(swState));
- if (ioctl(device->fd, EVIOCGSW(sizeof(swState)), swState) >= 0) {
- return test_bit(sw, swState) ? AKEY_STATE_DOWN : AKEY_STATE_UP;
- }
- }
- }
- return AKEY_STATE_UNKNOWN;
-}
-
-status_t EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* outValue) const {
- *outValue = 0;
-
- if (axis >= 0 && axis <= ABS_MAX) {
- AutoMutex _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual() && test_bit(axis, device->absBitmask)) {
- struct input_absinfo info;
- if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
- ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
- axis, device->identifier.name.string(), device->fd, errno);
- return -errno;
- }
-
- *outValue = info.value;
- return OK;
- }
- }
- return -1;
-}
-
-bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) const {
- AutoMutex _l(mLock);
-
- Device* device = getDeviceLocked(deviceId);
- if (device && device->keyMap.haveKeyLayout()) {
- Vector<int32_t> scanCodes;
- for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
- scanCodes.clear();
-
- status_t err = device->keyMap.keyLayoutMap->findScanCodesForKey(
- keyCodes[codeIndex], &scanCodes);
- if (! err) {
- // check the possible scan codes identified by the layout map against the
- // map of codes actually emitted by the driver
- for (size_t sc = 0; sc < scanCodes.size(); sc++) {
- if (test_bit(scanCodes[sc], device->keyBitmask)) {
- outFlags[codeIndex] = 1;
- break;
- }
- }
- }
- }
- return true;
- }
- return false;
-}
-
-status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,
- int32_t* outKeycode, uint32_t* outFlags) const {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
-
- if (device) {
- // Check the key character map first.
- sp<KeyCharacterMap> kcm = device->getKeyCharacterMap();
- if (kcm != NULL) {
- if (!kcm->mapKey(scanCode, usageCode, outKeycode)) {
- *outFlags = 0;
- return NO_ERROR;
- }
- }
-
- // Check the key layout next.
- if (device->keyMap.haveKeyLayout()) {
- if (!device->keyMap.keyLayoutMap->mapKey(
- scanCode, usageCode, outKeycode, outFlags)) {
- return NO_ERROR;
- }
- }
- }
-
- *outKeycode = 0;
- *outFlags = 0;
- return NAME_NOT_FOUND;
-}
-
-status_t EventHub::mapAxis(int32_t deviceId, int32_t scanCode, AxisInfo* outAxisInfo) const {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
-
- if (device && device->keyMap.haveKeyLayout()) {
- status_t err = device->keyMap.keyLayoutMap->mapAxis(scanCode, outAxisInfo);
- if (err == NO_ERROR) {
- return NO_ERROR;
- }
- }
-
- return NAME_NOT_FOUND;
-}
-
-void EventHub::setExcludedDevices(const Vector<String8>& devices) {
- AutoMutex _l(mLock);
-
- mExcludedDevices = devices;
-}
-
-bool EventHub::hasScanCode(int32_t deviceId, int32_t scanCode) const {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device && scanCode >= 0 && scanCode <= KEY_MAX) {
- if (test_bit(scanCode, device->keyBitmask)) {
- return true;
- }
- }
- return false;
-}
-
-bool EventHub::hasLed(int32_t deviceId, int32_t led) const {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- int32_t sc;
- if (device && mapLed(device, led, &sc) == NO_ERROR) {
- if (test_bit(sc, device->ledBitmask)) {
- return true;
- }
- }
- return false;
-}
-
-void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- setLedStateLocked(device, led, on);
-}
-
-void EventHub::setLedStateLocked(Device* device, int32_t led, bool on) {
- int32_t sc;
- if (device && !device->isVirtual() && mapLed(device, led, &sc) != NAME_NOT_FOUND) {
- struct input_event ev;
- ev.time.tv_sec = 0;
- ev.time.tv_usec = 0;
- ev.type = EV_LED;
- ev.code = sc;
- ev.value = on ? 1 : 0;
-
- ssize_t nWrite;
- do {
- nWrite = write(device->fd, &ev, sizeof(struct input_event));
- } while (nWrite == -1 && errno == EINTR);
- }
-}
-
-void EventHub::getVirtualKeyDefinitions(int32_t deviceId,
- Vector<VirtualKeyDefinition>& outVirtualKeys) const {
- outVirtualKeys.clear();
-
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device && device->virtualKeyMap) {
- outVirtualKeys.appendVector(device->virtualKeyMap->getVirtualKeys());
- }
-}
-
-sp<KeyCharacterMap> EventHub::getKeyCharacterMap(int32_t deviceId) const {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device) {
- return device->getKeyCharacterMap();
- }
- return NULL;
-}
-
-bool EventHub::setKeyboardLayoutOverlay(int32_t deviceId,
- const sp<KeyCharacterMap>& map) {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device) {
- if (map != device->overlayKeyMap) {
- device->overlayKeyMap = map;
- device->combinedKeyMap = KeyCharacterMap::combine(
- device->keyMap.keyCharacterMap, map);
- return true;
- }
- }
- return false;
-}
-
-static String8 generateDescriptor(InputDeviceIdentifier& identifier) {
- String8 rawDescriptor;
- rawDescriptor.appendFormat(":%04x:%04x:", identifier.vendor,
- identifier.product);
- // TODO add handling for USB devices to not uniqueify kbs that show up twice
- if (!identifier.uniqueId.isEmpty()) {
- rawDescriptor.append("uniqueId:");
- rawDescriptor.append(identifier.uniqueId);
- } else if (identifier.nonce != 0) {
- rawDescriptor.appendFormat("nonce:%04x", identifier.nonce);
- }
-
- if (identifier.vendor == 0 && identifier.product == 0) {
- // If we don't know the vendor and product id, then the device is probably
- // built-in so we need to rely on other information to uniquely identify
- // the input device. Usually we try to avoid relying on the device name or
- // location but for built-in input device, they are unlikely to ever change.
- if (!identifier.name.isEmpty()) {
- rawDescriptor.append("name:");
- rawDescriptor.append(identifier.name);
- } else if (!identifier.location.isEmpty()) {
- rawDescriptor.append("location:");
- rawDescriptor.append(identifier.location);
- }
- }
- identifier.descriptor = sha1(rawDescriptor);
- return rawDescriptor;
-}
-
-void EventHub::assignDescriptorLocked(InputDeviceIdentifier& identifier) {
- // Compute a device descriptor that uniquely identifies the device.
- // The descriptor is assumed to be a stable identifier. Its value should not
- // change between reboots, reconnections, firmware updates or new releases
- // of Android. In practice we sometimes get devices that cannot be uniquely
- // identified. In this case we enforce uniqueness between connected devices.
- // Ideally, we also want the descriptor to be short and relatively opaque.
-
- identifier.nonce = 0;
- String8 rawDescriptor = generateDescriptor(identifier);
- if (identifier.uniqueId.isEmpty()) {
- // If it didn't have a unique id check for conflicts and enforce
- // uniqueness if necessary.
- while(getDeviceByDescriptorLocked(identifier.descriptor) != NULL) {
- identifier.nonce++;
- rawDescriptor = generateDescriptor(identifier);
- }
- }
- ALOGV("Created descriptor: raw=%s, cooked=%s", rawDescriptor.string(),
- identifier.descriptor.string());
-}
-
-void EventHub::vibrate(int32_t deviceId, nsecs_t duration) {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual()) {
- ff_effect effect;
- memset(&effect, 0, sizeof(effect));
- effect.type = FF_RUMBLE;
- effect.id = device->ffEffectId;
- effect.u.rumble.strong_magnitude = 0xc000;
- effect.u.rumble.weak_magnitude = 0xc000;
- effect.replay.length = (duration + 999999LL) / 1000000LL;
- effect.replay.delay = 0;
- if (ioctl(device->fd, EVIOCSFF, &effect)) {
- ALOGW("Could not upload force feedback effect to device %s due to error %d.",
- device->identifier.name.string(), errno);
- return;
- }
- device->ffEffectId = effect.id;
-
- struct input_event ev;
- ev.time.tv_sec = 0;
- ev.time.tv_usec = 0;
- ev.type = EV_FF;
- ev.code = device->ffEffectId;
- ev.value = 1;
- if (write(device->fd, &ev, sizeof(ev)) != sizeof(ev)) {
- ALOGW("Could not start force feedback effect on device %s due to error %d.",
- device->identifier.name.string(), errno);
- return;
- }
- device->ffEffectPlaying = true;
- }
-}
-
-void EventHub::cancelVibrate(int32_t deviceId) {
- AutoMutex _l(mLock);
- Device* device = getDeviceLocked(deviceId);
- if (device && !device->isVirtual()) {
- if (device->ffEffectPlaying) {
- device->ffEffectPlaying = false;
-
- struct input_event ev;
- ev.time.tv_sec = 0;
- ev.time.tv_usec = 0;
- ev.type = EV_FF;
- ev.code = device->ffEffectId;
- ev.value = 0;
- if (write(device->fd, &ev, sizeof(ev)) != sizeof(ev)) {
- ALOGW("Could not stop force feedback effect on device %s due to error %d.",
- device->identifier.name.string(), errno);
- return;
- }
- }
- }
-}
-
-EventHub::Device* EventHub::getDeviceByDescriptorLocked(String8& descriptor) const {
- size_t size = mDevices.size();
- for (size_t i = 0; i < size; i++) {
- Device* device = mDevices.valueAt(i);
- if (descriptor.compare(device->identifier.descriptor) == 0) {
- return device;
- }
- }
- return NULL;
-}
-
-EventHub::Device* EventHub::getDeviceLocked(int32_t deviceId) const {
- if (deviceId == BUILT_IN_KEYBOARD_ID) {
- deviceId = mBuiltInKeyboardId;
- }
- ssize_t index = mDevices.indexOfKey(deviceId);
- return index >= 0 ? mDevices.valueAt(index) : NULL;
-}
-
-EventHub::Device* EventHub::getDeviceByPathLocked(const char* devicePath) const {
- for (size_t i = 0; i < mDevices.size(); i++) {
- Device* device = mDevices.valueAt(i);
- if (device->path == devicePath) {
- return device;
- }
- }
- return NULL;
-}
-
-size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
- ALOG_ASSERT(bufferSize >= 1);
-
- AutoMutex _l(mLock);
-
- struct input_event readBuffer[bufferSize];
-
- RawEvent* event = buffer;
- size_t capacity = bufferSize;
- bool awoken = false;
- for (;;) {
- nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-
- // Reopen input devices if needed.
- if (mNeedToReopenDevices) {
- mNeedToReopenDevices = false;
-
- ALOGI("Reopening all input devices due to a configuration change.");
-
- closeAllDevicesLocked();
- mNeedToScanDevices = true;
- break; // return to the caller before we actually rescan
- }
-
- // Report any devices that had last been added/removed.
- while (mClosingDevices) {
- Device* device = mClosingDevices;
- ALOGV("Reporting device closed: id=%d, name=%s\n",
- device->id, device->path.string());
- mClosingDevices = device->next;
- event->when = now;
- event->deviceId = device->id == mBuiltInKeyboardId ? BUILT_IN_KEYBOARD_ID : device->id;
- event->type = DEVICE_REMOVED;
- event += 1;
- delete device;
- mNeedToSendFinishedDeviceScan = true;
- if (--capacity == 0) {
- break;
- }
- }
-
- if (mNeedToScanDevices) {
- mNeedToScanDevices = false;
- scanDevicesLocked();
- mNeedToSendFinishedDeviceScan = true;
- }
-
- while (mOpeningDevices != NULL) {
- Device* device = mOpeningDevices;
- ALOGV("Reporting device opened: id=%d, name=%s\n",
- device->id, device->path.string());
- mOpeningDevices = device->next;
- event->when = now;
- event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
- event->type = DEVICE_ADDED;
- event += 1;
- mNeedToSendFinishedDeviceScan = true;
- if (--capacity == 0) {
- break;
- }
- }
-
- if (mNeedToSendFinishedDeviceScan) {
- mNeedToSendFinishedDeviceScan = false;
- event->when = now;
- event->type = FINISHED_DEVICE_SCAN;
- event += 1;
- if (--capacity == 0) {
- break;
- }
- }
-
- // Grab the next input event.
- bool deviceChanged = false;
- while (mPendingEventIndex < mPendingEventCount) {
- const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
- if (eventItem.data.u32 == EPOLL_ID_INOTIFY) {
- if (eventItem.events & EPOLLIN) {
- mPendingINotify = true;
- } else {
- ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
- }
- continue;
- }
-
- if (eventItem.data.u32 == EPOLL_ID_WAKE) {
- if (eventItem.events & EPOLLIN) {
- ALOGV("awoken after wake()");
- awoken = true;
- char buffer[16];
- ssize_t nRead;
- do {
- nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
- } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
- } else {
- ALOGW("Received unexpected epoll event 0x%08x for wake read pipe.",
- eventItem.events);
- }
- continue;
- }
-
- ssize_t deviceIndex = mDevices.indexOfKey(eventItem.data.u32);
- if (deviceIndex < 0) {
- ALOGW("Received unexpected epoll event 0x%08x for unknown device id %d.",
- eventItem.events, eventItem.data.u32);
- continue;
- }
-
- Device* device = mDevices.valueAt(deviceIndex);
- if (eventItem.events & EPOLLIN) {
- int32_t readSize = read(device->fd, readBuffer,
- sizeof(struct input_event) * capacity);
- if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
- // Device was removed before INotify noticed.
- ALOGW("could not get event, removed? (fd: %d size: %d bufferSize: %d "
- "capacity: %d errno: %d)\n",
- device->fd, readSize, bufferSize, capacity, errno);
- deviceChanged = true;
- closeDeviceLocked(device);
- } else if (readSize < 0) {
- if (errno != EAGAIN && errno != EINTR) {
- ALOGW("could not get event (errno=%d)", errno);
- }
- } else if ((readSize % sizeof(struct input_event)) != 0) {
- ALOGE("could not get event (wrong size: %d)", readSize);
- } else {
- int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
-
- size_t count = size_t(readSize) / sizeof(struct input_event);
- for (size_t i = 0; i < count; i++) {
- struct input_event& iev = readBuffer[i];
- ALOGV("%s got: time=%d.%06d, type=%d, code=%d, value=%d",
- device->path.string(),
- (int) iev.time.tv_sec, (int) iev.time.tv_usec,
- iev.type, iev.code, iev.value);
-
- // Some input devices may have a better concept of the time
- // when an input event was actually generated than the kernel
- // which simply timestamps all events on entry to evdev.
- // This is a custom Android extension of the input protocol
- // mainly intended for use with uinput based device drivers.
- if (iev.type == EV_MSC) {
- if (iev.code == MSC_ANDROID_TIME_SEC) {
- device->timestampOverrideSec = iev.value;
- continue;
- } else if (iev.code == MSC_ANDROID_TIME_USEC) {
- device->timestampOverrideUsec = iev.value;
- continue;
- }
- }
- if (device->timestampOverrideSec || device->timestampOverrideUsec) {
- iev.time.tv_sec = device->timestampOverrideSec;
- iev.time.tv_usec = device->timestampOverrideUsec;
- if (iev.type == EV_SYN && iev.code == SYN_REPORT) {
- device->timestampOverrideSec = 0;
- device->timestampOverrideUsec = 0;
- }
- ALOGV("applied override time %d.%06d",
- int(iev.time.tv_sec), int(iev.time.tv_usec));
- }
-
-#ifdef HAVE_POSIX_CLOCKS
- // Use the time specified in the event instead of the current time
- // so that downstream code can get more accurate estimates of
- // event dispatch latency from the time the event is enqueued onto
- // the evdev client buffer.
- //
- // The event's timestamp fortuitously uses the same monotonic clock
- // time base as the rest of Android. The kernel event device driver
- // (drivers/input/evdev.c) obtains timestamps using ktime_get_ts().
- // The systemTime(SYSTEM_TIME_MONOTONIC) function we use everywhere
- // calls clock_gettime(CLOCK_MONOTONIC) which is implemented as a
- // system call that also queries ktime_get_ts().
- event->when = nsecs_t(iev.time.tv_sec) * 1000000000LL
- + nsecs_t(iev.time.tv_usec) * 1000LL;
- ALOGV("event time %lld, now %lld", event->when, now);
-
- // Bug 7291243: Add a guard in case the kernel generates timestamps
- // that appear to be far into the future because they were generated
- // using the wrong clock source.
- //
- // This can happen because when the input device is initially opened
- // it has a default clock source of CLOCK_REALTIME. Any input events
- // enqueued right after the device is opened will have timestamps
- // generated using CLOCK_REALTIME. We later set the clock source
- // to CLOCK_MONOTONIC but it is already too late.
- //
- // Invalid input event timestamps can result in ANRs, crashes and
- // and other issues that are hard to track down. We must not let them
- // propagate through the system.
- //
- // Log a warning so that we notice the problem and recover gracefully.
- if (event->when >= now + 10 * 1000000000LL) {
- // Double-check. Time may have moved on.
- nsecs_t time = systemTime(SYSTEM_TIME_MONOTONIC);
- if (event->when > time) {
- ALOGW("An input event from %s has a timestamp that appears to "
- "have been generated using the wrong clock source "
- "(expected CLOCK_MONOTONIC): "
- "event time %lld, current time %lld, call time %lld. "
- "Using current time instead.",
- device->path.string(), event->when, time, now);
- event->when = time;
- } else {
- ALOGV("Event time is ok but failed the fast path and required "
- "an extra call to systemTime: "
- "event time %lld, current time %lld, call time %lld.",
- event->when, time, now);
- }
- }
-#else
- event->when = now;
-#endif
- event->deviceId = deviceId;
- event->type = iev.type;
- event->code = iev.code;
- event->value = iev.value;
- event += 1;
- capacity -= 1;
- }
- if (capacity == 0) {
- // The result buffer is full. Reset the pending event index
- // so we will try to read the device again on the next iteration.
- mPendingEventIndex -= 1;
- break;
- }
- }
- } else if (eventItem.events & EPOLLHUP) {
- ALOGI("Removing device %s due to epoll hang-up event.",
- device->identifier.name.string());
- deviceChanged = true;
- closeDeviceLocked(device);
- } else {
- ALOGW("Received unexpected epoll event 0x%08x for device %s.",
- eventItem.events, device->identifier.name.string());
- }
- }
-
- // readNotify() will modify the list of devices so this must be done after
- // processing all other events to ensure that we read all remaining events
- // before closing the devices.
- if (mPendingINotify && mPendingEventIndex >= mPendingEventCount) {
- mPendingINotify = false;
- readNotifyLocked();
- deviceChanged = true;
- }
-
- // Report added or removed devices immediately.
- if (deviceChanged) {
- continue;
- }
-
- // Return now if we have collected any events or if we were explicitly awoken.
- if (event != buffer || awoken) {
- break;
- }
-
- // Poll for events. Mind the wake lock dance!
- // We hold a wake lock at all times except during epoll_wait(). This works due to some
- // subtle choreography. When a device driver has pending (unread) events, it acquires
- // a kernel wake lock. However, once the last pending event has been read, the device
- // driver will release the kernel wake lock. To prevent the system from going to sleep
- // when this happens, the EventHub holds onto its own user wake lock while the client
- // is processing events. Thus the system can only sleep if there are no events
- // pending or currently being processed.
- //
- // The timeout is advisory only. If the device is asleep, it will not wake just to
- // service the timeout.
- mPendingEventIndex = 0;
-
- mLock.unlock(); // release lock before poll, must be before release_wake_lock
- release_wake_lock(WAKE_LOCK_ID);
-
- int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);
-
- acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
- mLock.lock(); // reacquire lock after poll, must be after acquire_wake_lock
-
- if (pollResult == 0) {
- // Timed out.
- mPendingEventCount = 0;
- break;
- }
-
- if (pollResult < 0) {
- // An error occurred.
- mPendingEventCount = 0;
-
- // Sleep after errors to avoid locking up the system.
- // Hopefully the error is transient.
- if (errno != EINTR) {
- ALOGW("poll failed (errno=%d)\n", errno);
- usleep(100000);
- }
- } else {
- // Some events occurred.
- mPendingEventCount = size_t(pollResult);
- }
- }
-
- // All done, return the number of events we read.
- return event - buffer;
-}
-
-void EventHub::wake() {
- ALOGV("wake() called");
-
- ssize_t nWrite;
- do {
- nWrite = write(mWakeWritePipeFd, "W", 1);
- } while (nWrite == -1 && errno == EINTR);
-
- if (nWrite != 1 && errno != EAGAIN) {
- ALOGW("Could not write wake signal, errno=%d", errno);
- }
-}
-
-void EventHub::scanDevicesLocked() {
- status_t res = scanDirLocked(DEVICE_PATH);
- if(res < 0) {
- ALOGE("scan dir failed for %s\n", DEVICE_PATH);
- }
- if (mDevices.indexOfKey(VIRTUAL_KEYBOARD_ID) < 0) {
- createVirtualKeyboardLocked();
- }
-}
-
-// ----------------------------------------------------------------------------
-
-static bool containsNonZeroByte(const uint8_t* array, uint32_t startIndex, uint32_t endIndex) {
- const uint8_t* end = array + endIndex;
- array += startIndex;
- while (array != end) {
- if (*(array++) != 0) {
- return true;
- }
- }
- return false;
-}
-
-static const int32_t GAMEPAD_KEYCODES[] = {
- AKEYCODE_BUTTON_A, AKEYCODE_BUTTON_B, AKEYCODE_BUTTON_C,
- AKEYCODE_BUTTON_X, AKEYCODE_BUTTON_Y, AKEYCODE_BUTTON_Z,
- AKEYCODE_BUTTON_L1, AKEYCODE_BUTTON_R1,
- AKEYCODE_BUTTON_L2, AKEYCODE_BUTTON_R2,
- AKEYCODE_BUTTON_THUMBL, AKEYCODE_BUTTON_THUMBR,
- AKEYCODE_BUTTON_START, AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE,
- AKEYCODE_BUTTON_1, AKEYCODE_BUTTON_2, AKEYCODE_BUTTON_3, AKEYCODE_BUTTON_4,
- AKEYCODE_BUTTON_5, AKEYCODE_BUTTON_6, AKEYCODE_BUTTON_7, AKEYCODE_BUTTON_8,
- AKEYCODE_BUTTON_9, AKEYCODE_BUTTON_10, AKEYCODE_BUTTON_11, AKEYCODE_BUTTON_12,
- AKEYCODE_BUTTON_13, AKEYCODE_BUTTON_14, AKEYCODE_BUTTON_15, AKEYCODE_BUTTON_16,
-};
-
-status_t EventHub::openDeviceLocked(const char *devicePath) {
- char buffer[80];
-
- ALOGV("Opening device: %s", devicePath);
-
- int fd = open(devicePath, O_RDWR | O_CLOEXEC);
- if(fd < 0) {
- ALOGE("could not open %s, %s\n", devicePath, strerror(errno));
- return -1;
- }
-
- InputDeviceIdentifier identifier;
-
- // Get device name.
- if(ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
- //fprintf(stderr, "could not get device name for %s, %s\n", devicePath, strerror(errno));
- } else {
- buffer[sizeof(buffer) - 1] = '\0';
- identifier.name.setTo(buffer);
- }
-
- // Check to see if the device is on our excluded list
- for (size_t i = 0; i < mExcludedDevices.size(); i++) {
- const String8& item = mExcludedDevices.itemAt(i);
- if (identifier.name == item) {
- ALOGI("ignoring event id %s driver %s\n", devicePath, item.string());
- close(fd);
- return -1;
- }
- }
-
- // Get device driver version.
- int driverVersion;
- if(ioctl(fd, EVIOCGVERSION, &driverVersion)) {
- ALOGE("could not get driver version for %s, %s\n", devicePath, strerror(errno));
- close(fd);
- return -1;
- }
-
- // Get device identifier.
- struct input_id inputId;
- if(ioctl(fd, EVIOCGID, &inputId)) {
- ALOGE("could not get device input id for %s, %s\n", devicePath, strerror(errno));
- close(fd);
- return -1;
- }
- identifier.bus = inputId.bustype;
- identifier.product = inputId.product;
- identifier.vendor = inputId.vendor;
- identifier.version = inputId.version;
-
- // Get device physical location.
- if(ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
- //fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
- } else {
- buffer[sizeof(buffer) - 1] = '\0';
- identifier.location.setTo(buffer);
- }
-
- // Get device unique id.
- if(ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
- //fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
- } else {
- buffer[sizeof(buffer) - 1] = '\0';
- identifier.uniqueId.setTo(buffer);
- }
-
- // Fill in the descriptor.
- assignDescriptorLocked(identifier);
-
- // Make file descriptor non-blocking for use with poll().
- if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
- ALOGE("Error %d making device file descriptor non-blocking.", errno);
- close(fd);
- return -1;
- }
-
- // Allocate device. (The device object takes ownership of the fd at this point.)
- int32_t deviceId = mNextDeviceId++;
- Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
-
- ALOGV("add device %d: %s\n", deviceId, devicePath);
- ALOGV(" bus: %04x\n"
- " vendor %04x\n"
- " product %04x\n"
- " version %04x\n",
- identifier.bus, identifier.vendor, identifier.product, identifier.version);
- ALOGV(" name: \"%s\"\n", identifier.name.string());
- ALOGV(" location: \"%s\"\n", identifier.location.string());
- ALOGV(" unique id: \"%s\"\n", identifier.uniqueId.string());
- ALOGV(" descriptor: \"%s\"\n", identifier.descriptor.string());
- ALOGV(" driver: v%d.%d.%d\n",
- driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff);
-
- // Load the configuration file for the device.
- loadConfigurationLocked(device);
-
- // Figure out the kinds of events the device reports.
- ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask);
- ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(device->absBitmask)), device->absBitmask);
- ioctl(fd, EVIOCGBIT(EV_REL, sizeof(device->relBitmask)), device->relBitmask);
- ioctl(fd, EVIOCGBIT(EV_SW, sizeof(device->swBitmask)), device->swBitmask);
- ioctl(fd, EVIOCGBIT(EV_LED, sizeof(device->ledBitmask)), device->ledBitmask);
- ioctl(fd, EVIOCGBIT(EV_FF, sizeof(device->ffBitmask)), device->ffBitmask);
- ioctl(fd, EVIOCGPROP(sizeof(device->propBitmask)), device->propBitmask);
-
- // See if this is a keyboard. Ignore everything in the button range except for
- // joystick and gamepad buttons which are handled like keyboards for the most part.
- bool haveKeyboardKeys = containsNonZeroByte(device->keyBitmask, 0, sizeof_bit_array(BTN_MISC))
- || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(KEY_OK),
- sizeof_bit_array(KEY_MAX + 1));
- bool haveGamepadButtons = containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_MISC),
- sizeof_bit_array(BTN_MOUSE))
- || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_JOYSTICK),
- sizeof_bit_array(BTN_DIGI));
- if (haveKeyboardKeys || haveGamepadButtons) {
- device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
- }
-
- // See if this is a cursor device such as a trackball or mouse.
- if (test_bit(BTN_MOUSE, device->keyBitmask)
- && test_bit(REL_X, device->relBitmask)
- && test_bit(REL_Y, device->relBitmask)) {
- device->classes |= INPUT_DEVICE_CLASS_CURSOR;
- }
-
- // See if this is a touch pad.
- // Is this a new modern multi-touch driver?
- if (test_bit(ABS_MT_POSITION_X, device->absBitmask)
- && test_bit(ABS_MT_POSITION_Y, device->absBitmask)) {
- // Some joysticks such as the PS3 controller report axes that conflict
- // with the ABS_MT range. Try to confirm that the device really is
- // a touch screen.
- if (test_bit(BTN_TOUCH, device->keyBitmask) || !haveGamepadButtons) {
- device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
- }
- // Is this an old style single-touch driver?
- } else if (test_bit(BTN_TOUCH, device->keyBitmask)
- && test_bit(ABS_X, device->absBitmask)
- && test_bit(ABS_Y, device->absBitmask)) {
- device->classes |= INPUT_DEVICE_CLASS_TOUCH;
- }
-
- // See if this device is a joystick.
- // Assumes that joysticks always have gamepad buttons in order to distinguish them
- // from other devices such as accelerometers that also have absolute axes.
- if (haveGamepadButtons) {
- uint32_t assumedClasses = device->classes | INPUT_DEVICE_CLASS_JOYSTICK;
- for (int i = 0; i <= ABS_MAX; i++) {
- if (test_bit(i, device->absBitmask)
- && (getAbsAxisUsage(i, assumedClasses) & INPUT_DEVICE_CLASS_JOYSTICK)) {
- device->classes = assumedClasses;
- break;
- }
- }
- }
-
- // Check whether this device has switches.
- for (int i = 0; i <= SW_MAX; i++) {
- if (test_bit(i, device->swBitmask)) {
- device->classes |= INPUT_DEVICE_CLASS_SWITCH;
- break;
- }
- }
-
- // Check whether this device supports the vibrator.
- if (test_bit(FF_RUMBLE, device->ffBitmask)) {
- device->classes |= INPUT_DEVICE_CLASS_VIBRATOR;
- }
-
- // Configure virtual keys.
- if ((device->classes & INPUT_DEVICE_CLASS_TOUCH)) {
- // Load the virtual keys for the touch screen, if any.
- // We do this now so that we can make sure to load the keymap if necessary.
- status_t status = loadVirtualKeyMapLocked(device);
- if (!status) {
- device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
- }
- }
-
- // Load the key map.
- // We need to do this for joysticks too because the key layout may specify axes.
- status_t keyMapStatus = NAME_NOT_FOUND;
- if (device->classes & (INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_JOYSTICK)) {
- // Load the keymap for the device.
- keyMapStatus = loadKeyMapLocked(device);
- }
-
- // Configure the keyboard, gamepad or virtual keyboard.
- if (device->classes & INPUT_DEVICE_CLASS_KEYBOARD) {
- // Register the keyboard as a built-in keyboard if it is eligible.
- if (!keyMapStatus
- && mBuiltInKeyboardId == NO_BUILT_IN_KEYBOARD
- && isEligibleBuiltInKeyboard(device->identifier,
- device->configuration, &device->keyMap)) {
- mBuiltInKeyboardId = device->id;
- }
-
- // 'Q' key support = cheap test of whether this is an alpha-capable kbd
- if (hasKeycodeLocked(device, AKEYCODE_Q)) {
- device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;
- }
-
- // See if this device has a DPAD.
- if (hasKeycodeLocked(device, AKEYCODE_DPAD_UP) &&
- hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) &&
- hasKeycodeLocked(device, AKEYCODE_DPAD_LEFT) &&
- hasKeycodeLocked(device, AKEYCODE_DPAD_RIGHT) &&
- hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) {
- device->classes |= INPUT_DEVICE_CLASS_DPAD;
- }
-
- // See if this device has a gamepad.
- for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES)/sizeof(GAMEPAD_KEYCODES[0]); i++) {
- if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) {
- device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;
- break;
- }
- }
-
- // Disable kernel key repeat since we handle it ourselves
- unsigned int repeatRate[] = {0,0};
- if (ioctl(fd, EVIOCSREP, repeatRate)) {
- ALOGW("Unable to disable kernel key repeat for %s: %s", devicePath, strerror(errno));
- }
- }
-
- // If the device isn't recognized as something we handle, don't monitor it.
- if (device->classes == 0) {
- ALOGV("Dropping device: id=%d, path='%s', name='%s'",
- deviceId, devicePath, device->identifier.name.string());
- delete device;
- return -1;
- }
-
- // Determine whether the device is external or internal.
- if (isExternalDeviceLocked(device)) {
- device->classes |= INPUT_DEVICE_CLASS_EXTERNAL;
- }
-
- if (device->classes & (INPUT_DEVICE_CLASS_JOYSTICK | INPUT_DEVICE_CLASS_GAMEPAD)) {
- device->controllerNumber = getNextControllerNumberLocked(device);
- setLedForController(device);
- }
-
- // Register with epoll.
- struct epoll_event eventItem;
- memset(&eventItem, 0, sizeof(eventItem));
- eventItem.events = mUsingEpollWakeup ? EPOLLIN : EPOLLIN | EPOLLWAKEUP;
- eventItem.data.u32 = deviceId;
- if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {
- ALOGE("Could not add device fd to epoll instance. errno=%d", errno);
- delete device;
- return -1;
- }
-
- String8 wakeMechanism("EPOLLWAKEUP");
- if (!mUsingEpollWakeup) {
-#ifndef EVIOCSSUSPENDBLOCK
- // uapi headers don't include EVIOCSSUSPENDBLOCK, and future kernels
- // will use an epoll flag instead, so as long as we want to support
- // this feature, we need to be prepared to define the ioctl ourselves.
-#define EVIOCSSUSPENDBLOCK _IOW('E', 0x91, int)
-#endif
- if (ioctl(fd, EVIOCSSUSPENDBLOCK, 1)) {
- wakeMechanism = "<none>";
- } else {
- wakeMechanism = "EVIOCSSUSPENDBLOCK";
- }
- }
-
- // Tell the kernel that we want to use the monotonic clock for reporting timestamps
- // associated with input events. This is important because the input system
- // uses the timestamps extensively and assumes they were recorded using the monotonic
- // clock.
- //
- // In older kernel, before Linux 3.4, there was no way to tell the kernel which
- // clock to use to input event timestamps. The standard kernel behavior was to
- // record a real time timestamp, which isn't what we want. Android kernels therefore
- // contained a patch to the evdev_event() function in drivers/input/evdev.c to
- // replace the call to do_gettimeofday() with ktime_get_ts() to cause the monotonic
- // clock to be used instead of the real time clock.
- //
- // As of Linux 3.4, there is a new EVIOCSCLOCKID ioctl to set the desired clock.
- // Therefore, we no longer require the Android-specific kernel patch described above
- // as long as we make sure to set select the monotonic clock. We do that here.
- int clockId = CLOCK_MONOTONIC;
- bool usingClockIoctl = !ioctl(fd, EVIOCSCLOCKID, &clockId);
-
- ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
- "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, "
- "wakeMechanism=%s, usingClockIoctl=%s",
- deviceId, fd, devicePath, device->identifier.name.string(),
- device->classes,
- device->configurationFile.string(),
- device->keyMap.keyLayoutFile.string(),
- device->keyMap.keyCharacterMapFile.string(),
- toString(mBuiltInKeyboardId == deviceId),
- wakeMechanism.string(), toString(usingClockIoctl));
-
- addDeviceLocked(device);
- return 0;
-}
-
-void EventHub::createVirtualKeyboardLocked() {
- InputDeviceIdentifier identifier;
- identifier.name = "Virtual";
- identifier.uniqueId = "<virtual>";
- assignDescriptorLocked(identifier);
-
- Device* device = new Device(-1, VIRTUAL_KEYBOARD_ID, String8("<virtual>"), identifier);
- device->classes = INPUT_DEVICE_CLASS_KEYBOARD
- | INPUT_DEVICE_CLASS_ALPHAKEY
- | INPUT_DEVICE_CLASS_DPAD
- | INPUT_DEVICE_CLASS_VIRTUAL;
- loadKeyMapLocked(device);
- addDeviceLocked(device);
-}
-
-void EventHub::addDeviceLocked(Device* device) {
- mDevices.add(device->id, device);
- device->next = mOpeningDevices;
- mOpeningDevices = device;
-}
-
-void EventHub::loadConfigurationLocked(Device* device) {
- device->configurationFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
- device->identifier, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
- if (device->configurationFile.isEmpty()) {
- ALOGD("No input device configuration file found for device '%s'.",
- device->identifier.name.string());
- } else {
- status_t status = PropertyMap::load(device->configurationFile,
- &device->configuration);
- if (status) {
- ALOGE("Error loading input device configuration file for device '%s'. "
- "Using default configuration.",
- device->identifier.name.string());
- }
- }
-}
-
-status_t EventHub::loadVirtualKeyMapLocked(Device* device) {
- // The virtual key map is supplied by the kernel as a system board property file.
- String8 path;
- path.append("/sys/board_properties/virtualkeys.");
- path.append(device->identifier.name);
- if (access(path.string(), R_OK)) {
- return NAME_NOT_FOUND;
- }
- return VirtualKeyMap::load(path, &device->virtualKeyMap);
-}
-
-status_t EventHub::loadKeyMapLocked(Device* device) {
- return device->keyMap.load(device->identifier, device->configuration);
-}
-
-bool EventHub::isExternalDeviceLocked(Device* device) {
- if (device->configuration) {
- bool value;
- if (device->configuration->tryGetProperty(String8("device.internal"), value)) {
- return !value;
- }
- }
- return device->identifier.bus == BUS_USB || device->identifier.bus == BUS_BLUETOOTH;
-}
-
-int32_t EventHub::getNextControllerNumberLocked(Device* device) {
- if (mControllerNumbers.isFull()) {
- ALOGI("Maximum number of controllers reached, assigning controller number 0 to device %s",
- device->identifier.name.string());
- return 0;
- }
- // Since the controller number 0 is reserved for non-controllers, translate all numbers up by
- // one
- return static_cast<int32_t>(mControllerNumbers.markFirstUnmarkedBit() + 1);
-}
-
-void EventHub::releaseControllerNumberLocked(Device* device) {
- int32_t num = device->controllerNumber;
- device->controllerNumber= 0;
- if (num == 0) {
- return;
- }
- mControllerNumbers.clearBit(static_cast<uint32_t>(num - 1));
-}
-
-void EventHub::setLedForController(Device* device) {
- for (int i = 0; i < MAX_CONTROLLER_LEDS; i++) {
- setLedStateLocked(device, ALED_CONTROLLER_1 + i, device->controllerNumber == i + 1);
- }
-}
-
-bool EventHub::hasKeycodeLocked(Device* device, int keycode) const {
- if (!device->keyMap.haveKeyLayout() || !device->keyBitmask) {
- return false;
- }
-
- Vector<int32_t> scanCodes;
- device->keyMap.keyLayoutMap->findScanCodesForKey(keycode, &scanCodes);
- const size_t N = scanCodes.size();
- for (size_t i=0; i<N && i<=KEY_MAX; i++) {
- int32_t sc = scanCodes.itemAt(i);
- if (sc >= 0 && sc <= KEY_MAX && test_bit(sc, device->keyBitmask)) {
- return true;
- }
- }
-
- return false;
-}
-
-status_t EventHub::mapLed(Device* device, int32_t led, int32_t* outScanCode) const {
- if (!device->keyMap.haveKeyLayout() || !device->ledBitmask) {
- return NAME_NOT_FOUND;
- }
-
- int32_t scanCode;
- if(device->keyMap.keyLayoutMap->findScanCodeForLed(led, &scanCode) != NAME_NOT_FOUND) {
- if(scanCode >= 0 && scanCode <= LED_MAX && test_bit(scanCode, device->ledBitmask)) {
- *outScanCode = scanCode;
- return NO_ERROR;
- }
- }
- return NAME_NOT_FOUND;
-}
-
-status_t EventHub::closeDeviceByPathLocked(const char *devicePath) {
- Device* device = getDeviceByPathLocked(devicePath);
- if (device) {
- closeDeviceLocked(device);
- return 0;
- }
- ALOGV("Remove device: %s not found, device may already have been removed.", devicePath);
- return -1;
-}
-
-void EventHub::closeAllDevicesLocked() {
- while (mDevices.size() > 0) {
- closeDeviceLocked(mDevices.valueAt(mDevices.size() - 1));
- }
-}
-
-void EventHub::closeDeviceLocked(Device* device) {
- ALOGI("Removed device: path=%s name=%s id=%d fd=%d classes=0x%x\n",
- device->path.string(), device->identifier.name.string(), device->id,
- device->fd, device->classes);
-
- if (device->id == mBuiltInKeyboardId) {
- ALOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
- device->path.string(), mBuiltInKeyboardId);
- mBuiltInKeyboardId = NO_BUILT_IN_KEYBOARD;
- }
-
- if (!device->isVirtual()) {
- if (epoll_ctl(mEpollFd, EPOLL_CTL_DEL, device->fd, NULL)) {
- ALOGW("Could not remove device fd from epoll instance. errno=%d", errno);
- }
- }
-
- releaseControllerNumberLocked(device);
-
- mDevices.removeItem(device->id);
- device->close();
-
- // Unlink for opening devices list if it is present.
- Device* pred = NULL;
- bool found = false;
- for (Device* entry = mOpeningDevices; entry != NULL; ) {
- if (entry == device) {
- found = true;
- break;
- }
- pred = entry;
- entry = entry->next;
- }
- if (found) {
- // Unlink the device from the opening devices list then delete it.
- // We don't need to tell the client that the device was closed because
- // it does not even know it was opened in the first place.
- ALOGI("Device %s was immediately closed after opening.", device->path.string());
- if (pred) {
- pred->next = device->next;
- } else {
- mOpeningDevices = device->next;
- }
- delete device;
- } else {
- // Link into closing devices list.
- // The device will be deleted later after we have informed the client.
- device->next = mClosingDevices;
- mClosingDevices = device;
- }
-}
-
-status_t EventHub::readNotifyLocked() {
- int res;
- char devname[PATH_MAX];
- char *filename;
- char event_buf[512];
- int event_size;
- int event_pos = 0;
- struct inotify_event *event;
-
- ALOGV("EventHub::readNotify nfd: %d\n", mINotifyFd);
- res = read(mINotifyFd, event_buf, sizeof(event_buf));
- if(res < (int)sizeof(*event)) {
- if(errno == EINTR)
- return 0;
- ALOGW("could not get event, %s\n", strerror(errno));
- return -1;
- }
- //printf("got %d bytes of event information\n", res);
-
- strcpy(devname, DEVICE_PATH);
- filename = devname + strlen(devname);
- *filename++ = '/';
-
- while(res >= (int)sizeof(*event)) {
- event = (struct inotify_event *)(event_buf + event_pos);
- //printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : "");
- if(event->len) {
- strcpy(filename, event->name);
- if(event->mask & IN_CREATE) {
- openDeviceLocked(devname);
- } else {
- ALOGI("Removing device '%s' due to inotify event\n", devname);
- closeDeviceByPathLocked(devname);
- }
- }
- event_size = sizeof(*event) + event->len;
- res -= event_size;
- event_pos += event_size;
- }
- return 0;
-}
-
-status_t EventHub::scanDirLocked(const char *dirname)
-{
- char devname[PATH_MAX];
- char *filename;
- DIR *dir;
- struct dirent *de;
- dir = opendir(dirname);
- if(dir == NULL)
- return -1;
- strcpy(devname, dirname);
- filename = devname + strlen(devname);
- *filename++ = '/';
- while((de = readdir(dir))) {
- if(de->d_name[0] == '.' &&
- (de->d_name[1] == '\0' ||
- (de->d_name[1] == '.' && de->d_name[2] == '\0')))
- continue;
- strcpy(filename, de->d_name);
- openDeviceLocked(devname);
- }
- closedir(dir);
- return 0;
-}
-
-void EventHub::requestReopenDevices() {
- ALOGV("requestReopenDevices() called");
-
- AutoMutex _l(mLock);
- mNeedToReopenDevices = true;
-}
-
-void EventHub::dump(String8& dump) {
- dump.append("Event Hub State:\n");
-
- { // acquire lock
- AutoMutex _l(mLock);
-
- dump.appendFormat(INDENT "BuiltInKeyboardId: %d\n", mBuiltInKeyboardId);
-
- dump.append(INDENT "Devices:\n");
-
- for (size_t i = 0; i < mDevices.size(); i++) {
- const Device* device = mDevices.valueAt(i);
- if (mBuiltInKeyboardId == device->id) {
- dump.appendFormat(INDENT2 "%d: %s (aka device 0 - built-in keyboard)\n",
- device->id, device->identifier.name.string());
- } else {
- dump.appendFormat(INDENT2 "%d: %s\n", device->id,
- device->identifier.name.string());
- }
- dump.appendFormat(INDENT3 "Classes: 0x%08x\n", device->classes);
- dump.appendFormat(INDENT3 "Path: %s\n", device->path.string());
- dump.appendFormat(INDENT3 "Descriptor: %s\n", device->identifier.descriptor.string());
- dump.appendFormat(INDENT3 "Location: %s\n", device->identifier.location.string());
- dump.appendFormat(INDENT3 "ControllerNumber: %d\n", device->controllerNumber);
- dump.appendFormat(INDENT3 "UniqueId: %s\n", device->identifier.uniqueId.string());
- dump.appendFormat(INDENT3 "Identifier: bus=0x%04x, vendor=0x%04x, "
- "product=0x%04x, version=0x%04x\n",
- device->identifier.bus, device->identifier.vendor,
- device->identifier.product, device->identifier.version);
- dump.appendFormat(INDENT3 "KeyLayoutFile: %s\n",
- device->keyMap.keyLayoutFile.string());
- dump.appendFormat(INDENT3 "KeyCharacterMapFile: %s\n",
- device->keyMap.keyCharacterMapFile.string());
- dump.appendFormat(INDENT3 "ConfigurationFile: %s\n",
- device->configurationFile.string());
- dump.appendFormat(INDENT3 "HaveKeyboardLayoutOverlay: %s\n",
- toString(device->overlayKeyMap != NULL));
- }
- } // release lock
-}
-
-void EventHub::monitor() {
- // Acquire and release the lock to ensure that the event hub has not deadlocked.
- mLock.lock();
- mLock.unlock();
-}
-
-
-}; // namespace android
diff --git a/libs/input/EventHub.h b/libs/input/EventHub.h
deleted file mode 100644
index 20179ae..0000000
--- a/libs/input/EventHub.h
+++ /dev/null
@@ -1,457 +0,0 @@
-/*
- * Copyright (C) 2005 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//
-#ifndef _RUNTIME_EVENT_HUB_H
-#define _RUNTIME_EVENT_HUB_H
-
-#include <input/Input.h>
-#include <input/InputDevice.h>
-#include <input/Keyboard.h>
-#include <input/KeyLayoutMap.h>
-#include <input/KeyCharacterMap.h>
-#include <input/VirtualKeyMap.h>
-#include <utils/String8.h>
-#include <utils/threads.h>
-#include <utils/Log.h>
-#include <utils/threads.h>
-#include <utils/List.h>
-#include <utils/Errors.h>
-#include <utils/PropertyMap.h>
-#include <utils/Vector.h>
-#include <utils/KeyedVector.h>
-#include <utils/BitSet.h>
-
-#include <linux/input.h>
-#include <sys/epoll.h>
-
-/* Convenience constants. */
-
-#define BTN_FIRST 0x100 // first button code
-#define BTN_LAST 0x15f // last button code
-
-/*
- * These constants are used privately in Android to pass raw timestamps
- * through evdev from uinput device drivers because there is currently no
- * other way to transfer this information. The evdev driver automatically
- * timestamps all input events with the time they were posted and clobbers
- * whatever information was passed in.
- *
- * For the purposes of this hack, the timestamp is specified in the
- * CLOCK_MONOTONIC timebase and is split into two EV_MSC events specifying
- * seconds and microseconds.
- */
-#define MSC_ANDROID_TIME_SEC 0x6
-#define MSC_ANDROID_TIME_USEC 0x7
-
-namespace android {
-
-enum {
- // Device id of a special "virtual" keyboard that is always present.
- VIRTUAL_KEYBOARD_ID = -1,
- // Device id of the "built-in" keyboard if there is one.
- BUILT_IN_KEYBOARD_ID = 0,
-};
-
-/*
- * A raw event as retrieved from the EventHub.
- */
-struct RawEvent {
- nsecs_t when;
- int32_t deviceId;
- int32_t type;
- int32_t code;
- int32_t value;
-};
-
-/* Describes an absolute axis. */
-struct RawAbsoluteAxisInfo {
- bool valid; // true if the information is valid, false otherwise
-
- int32_t minValue; // minimum value
- int32_t maxValue; // maximum value
- int32_t flat; // center flat position, eg. flat == 8 means center is between -8 and 8
- int32_t fuzz; // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise
- int32_t resolution; // resolution in units per mm or radians per mm
-
- inline void clear() {
- valid = false;
- minValue = 0;
- maxValue = 0;
- flat = 0;
- fuzz = 0;
- resolution = 0;
- }
-};
-
-/*
- * Input device classes.
- */
-enum {
- /* The input device is a keyboard or has buttons. */
- INPUT_DEVICE_CLASS_KEYBOARD = 0x00000001,
-
- /* The input device is an alpha-numeric keyboard (not just a dial pad). */
- INPUT_DEVICE_CLASS_ALPHAKEY = 0x00000002,
-
- /* The input device is a touchscreen or a touchpad (either single-touch or multi-touch). */
- INPUT_DEVICE_CLASS_TOUCH = 0x00000004,
-
- /* The input device is a cursor device such as a trackball or mouse. */
- INPUT_DEVICE_CLASS_CURSOR = 0x00000008,
-
- /* The input device is a multi-touch touchscreen. */
- INPUT_DEVICE_CLASS_TOUCH_MT = 0x00000010,
-
- /* The input device is a directional pad (implies keyboard, has DPAD keys). */
- INPUT_DEVICE_CLASS_DPAD = 0x00000020,
-
- /* The input device is a gamepad (implies keyboard, has BUTTON keys). */
- INPUT_DEVICE_CLASS_GAMEPAD = 0x00000040,
-
- /* The input device has switches. */
- INPUT_DEVICE_CLASS_SWITCH = 0x00000080,
-
- /* The input device is a joystick (implies gamepad, has joystick absolute axes). */
- INPUT_DEVICE_CLASS_JOYSTICK = 0x00000100,
-
- /* The input device has a vibrator (supports FF_RUMBLE). */
- INPUT_DEVICE_CLASS_VIBRATOR = 0x00000200,
-
- /* The input device is virtual (not a real device, not part of UI configuration). */
- INPUT_DEVICE_CLASS_VIRTUAL = 0x40000000,
-
- /* The input device is external (not built-in). */
- INPUT_DEVICE_CLASS_EXTERNAL = 0x80000000,
-};
-
-/*
- * Gets the class that owns an axis, in cases where multiple classes might claim
- * the same axis for different purposes.
- */
-extern uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses);
-
-/*
- * Grand Central Station for events.
- *
- * The event hub aggregates input events received across all known input
- * devices on the system, including devices that may be emulated by the simulator
- * environment. In addition, the event hub generates fake input events to indicate
- * when devices are added or removed.
- *
- * The event hub provides a stream of input events (via the getEvent function).
- * It also supports querying the current actual state of input devices such as identifying
- * which keys are currently down. Finally, the event hub keeps track of the capabilities of
- * individual input devices, such as their class and the set of key codes that they support.
- */
-class EventHubInterface : public virtual RefBase {
-protected:
- EventHubInterface() { }
- virtual ~EventHubInterface() { }
-
-public:
- // Synthetic raw event type codes produced when devices are added or removed.
- enum {
- // Sent when a device is added.
- DEVICE_ADDED = 0x10000000,
- // Sent when a device is removed.
- DEVICE_REMOVED = 0x20000000,
- // Sent when all added/removed devices from the most recent scan have been reported.
- // This event is always sent at least once.
- FINISHED_DEVICE_SCAN = 0x30000000,
-
- FIRST_SYNTHETIC_EVENT = DEVICE_ADDED,
- };
-
- virtual uint32_t getDeviceClasses(int32_t deviceId) const = 0;
-
- virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const = 0;
-
- virtual int32_t getDeviceControllerNumber(int32_t deviceId) const = 0;
-
- virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const = 0;
-
- virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
- RawAbsoluteAxisInfo* outAxisInfo) const = 0;
-
- virtual bool hasRelativeAxis(int32_t deviceId, int axis) const = 0;
-
- virtual bool hasInputProperty(int32_t deviceId, int property) const = 0;
-
- virtual status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,
- int32_t* outKeycode, uint32_t* outFlags) const = 0;
-
- virtual status_t mapAxis(int32_t deviceId, int32_t scanCode,
- AxisInfo* outAxisInfo) const = 0;
-
- // Sets devices that are excluded from opening.
- // This can be used to ignore input devices for sensors.
- virtual void setExcludedDevices(const Vector<String8>& devices) = 0;
-
- /*
- * Wait for events to become available and returns them.
- * After returning, the EventHub holds onto a wake lock until the next call to getEvent.
- * This ensures that the device will not go to sleep while the event is being processed.
- * If the device needs to remain awake longer than that, then the caller is responsible
- * for taking care of it (say, by poking the power manager user activity timer).
- *
- * The timeout is advisory only. If the device is asleep, it will not wake just to
- * service the timeout.
- *
- * Returns the number of events obtained, or 0 if the timeout expired.
- */
- virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) = 0;
-
- /*
- * Query current input state.
- */
- virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const = 0;
- virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const = 0;
- virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const = 0;
- virtual status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
- int32_t* outValue) const = 0;
-
- /*
- * Examine key input devices for specific framework keycode support
- */
- virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
- uint8_t* outFlags) const = 0;
-
- virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const = 0;
-
- /* LED related functions expect Android LED constants, not scan codes or HID usages */
- virtual bool hasLed(int32_t deviceId, int32_t led) const = 0;
- virtual void setLedState(int32_t deviceId, int32_t led, bool on) = 0;
-
- virtual void getVirtualKeyDefinitions(int32_t deviceId,
- Vector<VirtualKeyDefinition>& outVirtualKeys) const = 0;
-
- virtual sp<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const = 0;
- virtual bool setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map) = 0;
-
- /* Control the vibrator. */
- virtual void vibrate(int32_t deviceId, nsecs_t duration) = 0;
- virtual void cancelVibrate(int32_t deviceId) = 0;
-
- /* Requests the EventHub to reopen all input devices on the next call to getEvents(). */
- virtual void requestReopenDevices() = 0;
-
- /* Wakes up getEvents() if it is blocked on a read. */
- virtual void wake() = 0;
-
- /* Dump EventHub state to a string. */
- virtual void dump(String8& dump) = 0;
-
- /* Called by the heatbeat to ensures that the reader has not deadlocked. */
- virtual void monitor() = 0;
-};
-
-class EventHub : public EventHubInterface
-{
-public:
- EventHub();
-
- virtual uint32_t getDeviceClasses(int32_t deviceId) const;
-
- virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const;
-
- virtual int32_t getDeviceControllerNumber(int32_t deviceId) const;
-
- virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const;
-
- virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
- RawAbsoluteAxisInfo* outAxisInfo) const;
-
- virtual bool hasRelativeAxis(int32_t deviceId, int axis) const;
-
- virtual bool hasInputProperty(int32_t deviceId, int property) const;
-
- virtual status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,
- int32_t* outKeycode, uint32_t* outFlags) const;
-
- virtual status_t mapAxis(int32_t deviceId, int32_t scanCode,
- AxisInfo* outAxisInfo) const;
-
- virtual void setExcludedDevices(const Vector<String8>& devices);
-
- virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const;
- virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const;
- virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const;
- virtual status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* outValue) const;
-
- virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) const;
-
- virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize);
-
- virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const;
- virtual bool hasLed(int32_t deviceId, int32_t led) const;
- virtual void setLedState(int32_t deviceId, int32_t led, bool on);
-
- virtual void getVirtualKeyDefinitions(int32_t deviceId,
- Vector<VirtualKeyDefinition>& outVirtualKeys) const;
-
- virtual sp<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const;
- virtual bool setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map);
-
- virtual void vibrate(int32_t deviceId, nsecs_t duration);
- virtual void cancelVibrate(int32_t deviceId);
-
- virtual void requestReopenDevices();
-
- virtual void wake();
-
- virtual void dump(String8& dump);
- virtual void monitor();
-
-protected:
- virtual ~EventHub();
-
-private:
- struct Device {
- Device* next;
-
- int fd; // may be -1 if device is virtual
- const int32_t id;
- const String8 path;
- const InputDeviceIdentifier identifier;
-
- uint32_t classes;
-
- uint8_t keyBitmask[(KEY_MAX + 1) / 8];
- uint8_t absBitmask[(ABS_MAX + 1) / 8];
- uint8_t relBitmask[(REL_MAX + 1) / 8];
- uint8_t swBitmask[(SW_MAX + 1) / 8];
- uint8_t ledBitmask[(LED_MAX + 1) / 8];
- uint8_t ffBitmask[(FF_MAX + 1) / 8];
- uint8_t propBitmask[(INPUT_PROP_MAX + 1) / 8];
-
- String8 configurationFile;
- PropertyMap* configuration;
- VirtualKeyMap* virtualKeyMap;
- KeyMap keyMap;
-
- sp<KeyCharacterMap> overlayKeyMap;
- sp<KeyCharacterMap> combinedKeyMap;
-
- bool ffEffectPlaying;
- int16_t ffEffectId; // initially -1
-
- int32_t controllerNumber;
-
- int32_t timestampOverrideSec;
- int32_t timestampOverrideUsec;
-
- Device(int fd, int32_t id, const String8& path, const InputDeviceIdentifier& identifier);
- ~Device();
-
- void close();
-
- inline bool isVirtual() const { return fd < 0; }
-
- const sp<KeyCharacterMap>& getKeyCharacterMap() const {
- if (combinedKeyMap != NULL) {
- return combinedKeyMap;
- }
- return keyMap.keyCharacterMap;
- }
- };
-
- status_t openDeviceLocked(const char *devicePath);
- void createVirtualKeyboardLocked();
- void addDeviceLocked(Device* device);
- void assignDescriptorLocked(InputDeviceIdentifier& identifier);
-
- status_t closeDeviceByPathLocked(const char *devicePath);
- void closeDeviceLocked(Device* device);
- void closeAllDevicesLocked();
-
- status_t scanDirLocked(const char *dirname);
- void scanDevicesLocked();
- status_t readNotifyLocked();
-
- Device* getDeviceByDescriptorLocked(String8& descriptor) const;
- Device* getDeviceLocked(int32_t deviceId) const;
- Device* getDeviceByPathLocked(const char* devicePath) const;
-
- bool hasKeycodeLocked(Device* device, int keycode) const;
-
- void loadConfigurationLocked(Device* device);
- status_t loadVirtualKeyMapLocked(Device* device);
- status_t loadKeyMapLocked(Device* device);
-
- bool isExternalDeviceLocked(Device* device);
-
- int32_t getNextControllerNumberLocked(Device* device);
- void releaseControllerNumberLocked(Device* device);
- void setLedForController(Device* device);
-
- status_t mapLed(Device* device, int32_t led, int32_t* outScanCode) const;
- void setLedStateLocked(Device* device, int32_t led, bool on);
-
- // Protect all internal state.
- mutable Mutex mLock;
-
- // The actual id of the built-in keyboard, or NO_BUILT_IN_KEYBOARD if none.
- // EventHub remaps the built-in keyboard to id 0 externally as required by the API.
- enum {
- // Must not conflict with any other assigned device ids, including
- // the virtual keyboard id (-1).
- NO_BUILT_IN_KEYBOARD = -2,
- };
- int32_t mBuiltInKeyboardId;
-
- int32_t mNextDeviceId;
-
- BitSet32 mControllerNumbers;
-
- KeyedVector<int32_t, Device*> mDevices;
-
- Device *mOpeningDevices;
- Device *mClosingDevices;
-
- bool mNeedToSendFinishedDeviceScan;
- bool mNeedToReopenDevices;
- bool mNeedToScanDevices;
- Vector<String8> mExcludedDevices;
-
- int mEpollFd;
- int mINotifyFd;
- int mWakeReadPipeFd;
- int mWakeWritePipeFd;
-
- // Ids used for epoll notifications not associated with devices.
- static const uint32_t EPOLL_ID_INOTIFY = 0x80000001;
- static const uint32_t EPOLL_ID_WAKE = 0x80000002;
-
- // Epoll FD list size hint.
- static const int EPOLL_SIZE_HINT = 8;
-
- // Maximum number of signalled FDs to handle at a time.
- static const int EPOLL_MAX_EVENTS = 16;
-
- // The array of pending epoll events and the index of the next event to be handled.
- struct epoll_event mPendingEventItems[EPOLL_MAX_EVENTS];
- size_t mPendingEventCount;
- size_t mPendingEventIndex;
- bool mPendingINotify;
-
- bool mUsingEpollWakeup;
-};
-
-}; // namespace android
-
-#endif // _RUNTIME_EVENT_HUB_H
diff --git a/libs/input/InputApplication.cpp b/libs/input/InputApplication.cpp
deleted file mode 100644
index a99e637..0000000
--- a/libs/input/InputApplication.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "InputApplication"
-
-#include "InputApplication.h"
-
-#include <cutils/log.h>
-
-namespace android {
-
-// --- InputApplicationHandle ---
-
-InputApplicationHandle::InputApplicationHandle() :
- mInfo(NULL) {
-}
-
-InputApplicationHandle::~InputApplicationHandle() {
- delete mInfo;
-}
-
-void InputApplicationHandle::releaseInfo() {
- if (mInfo) {
- delete mInfo;
- mInfo = NULL;
- }
-}
-
-} // namespace android
diff --git a/libs/input/InputApplication.h b/libs/input/InputApplication.h
deleted file mode 100644
index 1f5504c..0000000
--- a/libs/input/InputApplication.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_APPLICATION_H
-#define _UI_INPUT_APPLICATION_H
-
-#include <input/Input.h>
-
-#include <utils/RefBase.h>
-#include <utils/Timers.h>
-#include <utils/String8.h>
-
-namespace android {
-
-/*
- * Describes the properties of an application that can receive input.
- */
-struct InputApplicationInfo {
- String8 name;
- nsecs_t dispatchingTimeout;
-};
-
-
-/*
- * Handle for an application that can receive input.
- *
- * Used by the native input dispatcher as a handle for the window manager objects
- * that describe an application.
- */
-class InputApplicationHandle : public RefBase {
-public:
- inline const InputApplicationInfo* getInfo() const {
- return mInfo;
- }
-
- inline String8 getName() const {
- return mInfo ? mInfo->name : String8("<invalid>");
- }
-
- inline nsecs_t getDispatchingTimeout(nsecs_t defaultValue) const {
- return mInfo ? mInfo->dispatchingTimeout : defaultValue;
- }
-
- /**
- * Requests that the state of this object be updated to reflect
- * the most current available information about the application.
- *
- * This method should only be called from within the input dispatcher's
- * critical section.
- *
- * Returns true on success, or false if the handle is no longer valid.
- */
- virtual bool updateInfo() = 0;
-
- /**
- * Releases the storage used by the associated information when it is
- * no longer needed.
- */
- void releaseInfo();
-
-protected:
- InputApplicationHandle();
- virtual ~InputApplicationHandle();
-
- InputApplicationInfo* mInfo;
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_APPLICATION_H
diff --git a/libs/input/InputDispatcher.cpp b/libs/input/InputDispatcher.cpp
deleted file mode 100644
index 10a639e..0000000
--- a/libs/input/InputDispatcher.cpp
+++ /dev/null
@@ -1,4470 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "InputDispatcher"
-#define ATRACE_TAG ATRACE_TAG_INPUT
-
-//#define LOG_NDEBUG 0
-
-// Log detailed debug messages about each inbound event notification to the dispatcher.
-#define DEBUG_INBOUND_EVENT_DETAILS 0
-
-// Log detailed debug messages about each outbound event processed by the dispatcher.
-#define DEBUG_OUTBOUND_EVENT_DETAILS 0
-
-// Log debug messages about the dispatch cycle.
-#define DEBUG_DISPATCH_CYCLE 0
-
-// Log debug messages about registrations.
-#define DEBUG_REGISTRATION 0
-
-// Log debug messages about input event injection.
-#define DEBUG_INJECTION 0
-
-// Log debug messages about input focus tracking.
-#define DEBUG_FOCUS 0
-
-// Log debug messages about the app switch latency optimization.
-#define DEBUG_APP_SWITCH 0
-
-// Log debug messages about hover events.
-#define DEBUG_HOVER 0
-
-#include "InputDispatcher.h"
-
-#include <utils/Trace.h>
-#include <cutils/log.h>
-#include <androidfw/PowerManager.h>
-
-#include <stddef.h>
-#include <unistd.h>
-#include <errno.h>
-#include <limits.h>
-#include <time.h>
-
-#define INDENT " "
-#define INDENT2 " "
-#define INDENT3 " "
-#define INDENT4 " "
-
-namespace android {
-
-// Default input dispatching timeout if there is no focused application or paused window
-// from which to determine an appropriate dispatching timeout.
-const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
-
-// Amount of time to allow for all pending events to be processed when an app switch
-// key is on the way. This is used to preempt input dispatch and drop input events
-// when an application takes too long to respond and the user has pressed an app switch key.
-const nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec
-
-// Amount of time to allow for an event to be dispatched (measured since its eventTime)
-// before considering it stale and dropping it.
-const nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL; // 10sec
-
-// Amount of time to allow touch events to be streamed out to a connection before requiring
-// that the first event be finished. This value extends the ANR timeout by the specified
-// amount. For example, if streaming is allowed to get ahead by one second relative to the
-// queue of waiting unfinished events, then ANRs will similarly be delayed by one second.
-const nsecs_t STREAM_AHEAD_EVENT_TIMEOUT = 500 * 1000000LL; // 0.5sec
-
-// Log a warning when an event takes longer than this to process, even if an ANR does not occur.
-const nsecs_t SLOW_EVENT_PROCESSING_WARNING_TIMEOUT = 2000 * 1000000LL; // 2sec
-
-// Number of recent events to keep for debugging purposes.
-const size_t RECENT_QUEUE_MAX_SIZE = 10;
-
-static inline nsecs_t now() {
- return systemTime(SYSTEM_TIME_MONOTONIC);
-}
-
-static inline const char* toString(bool value) {
- return value ? "true" : "false";
-}
-
-static inline int32_t getMotionEventActionPointerIndex(int32_t action) {
- return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
- >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
-}
-
-static bool isValidKeyAction(int32_t action) {
- switch (action) {
- case AKEY_EVENT_ACTION_DOWN:
- case AKEY_EVENT_ACTION_UP:
- return true;
- default:
- return false;
- }
-}
-
-static bool validateKeyEvent(int32_t action) {
- if (! isValidKeyAction(action)) {
- ALOGE("Key event has invalid action code 0x%x", action);
- return false;
- }
- return true;
-}
-
-static bool isValidMotionAction(int32_t action, size_t pointerCount) {
- switch (action & AMOTION_EVENT_ACTION_MASK) {
- case AMOTION_EVENT_ACTION_DOWN:
- case AMOTION_EVENT_ACTION_UP:
- case AMOTION_EVENT_ACTION_CANCEL:
- case AMOTION_EVENT_ACTION_MOVE:
- case AMOTION_EVENT_ACTION_OUTSIDE:
- case AMOTION_EVENT_ACTION_HOVER_ENTER:
- case AMOTION_EVENT_ACTION_HOVER_MOVE:
- case AMOTION_EVENT_ACTION_HOVER_EXIT:
- case AMOTION_EVENT_ACTION_SCROLL:
- return true;
- case AMOTION_EVENT_ACTION_POINTER_DOWN:
- case AMOTION_EVENT_ACTION_POINTER_UP: {
- int32_t index = getMotionEventActionPointerIndex(action);
- return index >= 0 && size_t(index) < pointerCount;
- }
- default:
- return false;
- }
-}
-
-static bool validateMotionEvent(int32_t action, size_t pointerCount,
- const PointerProperties* pointerProperties) {
- if (! isValidMotionAction(action, pointerCount)) {
- ALOGE("Motion event has invalid action code 0x%x", action);
- return false;
- }
- if (pointerCount < 1 || pointerCount > MAX_POINTERS) {
- ALOGE("Motion event has invalid pointer count %d; value must be between 1 and %d.",
- pointerCount, MAX_POINTERS);
- return false;
- }
- BitSet32 pointerIdBits;
- for (size_t i = 0; i < pointerCount; i++) {
- int32_t id = pointerProperties[i].id;
- if (id < 0 || id > MAX_POINTER_ID) {
- ALOGE("Motion event has invalid pointer id %d; value must be between 0 and %d",
- id, MAX_POINTER_ID);
- return false;
- }
- if (pointerIdBits.hasBit(id)) {
- ALOGE("Motion event has duplicate pointer id %d", id);
- return false;
- }
- pointerIdBits.markBit(id);
- }
- return true;
-}
-
-static bool isMainDisplay(int32_t displayId) {
- return displayId == ADISPLAY_ID_DEFAULT || displayId == ADISPLAY_ID_NONE;
-}
-
-static void dumpRegion(String8& dump, const SkRegion& region) {
- if (region.isEmpty()) {
- dump.append("<empty>");
- return;
- }
-
- bool first = true;
- for (SkRegion::Iterator it(region); !it.done(); it.next()) {
- if (first) {
- first = false;
- } else {
- dump.append("|");
- }
- const SkIRect& rect = it.rect();
- dump.appendFormat("[%d,%d][%d,%d]", rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
- }
-}
-
-
-// --- InputDispatcher ---
-
-InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
- mPolicy(policy),
- mPendingEvent(NULL), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
- mNextUnblockedEvent(NULL),
- mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
- mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
- mLooper = new Looper(false);
-
- mKeyRepeatState.lastKeyEntry = NULL;
-
- policy->getDispatcherConfiguration(&mConfig);
-}
-
-InputDispatcher::~InputDispatcher() {
- { // acquire lock
- AutoMutex _l(mLock);
-
- resetKeyRepeatLocked();
- releasePendingEventLocked();
- drainInboundQueueLocked();
- }
-
- while (mConnectionsByFd.size() != 0) {
- unregisterInputChannel(mConnectionsByFd.valueAt(0)->inputChannel);
- }
-}
-
-void InputDispatcher::dispatchOnce() {
- nsecs_t nextWakeupTime = LONG_LONG_MAX;
- { // acquire lock
- AutoMutex _l(mLock);
- mDispatcherIsAliveCondition.broadcast();
-
- // Run a dispatch loop if there are no pending commands.
- // The dispatch loop might enqueue commands to run afterwards.
- if (!haveCommandsLocked()) {
- dispatchOnceInnerLocked(&nextWakeupTime);
- }
-
- // Run all pending commands if there are any.
- // If any commands were run then force the next poll to wake up immediately.
- if (runCommandsLockedInterruptible()) {
- nextWakeupTime = LONG_LONG_MIN;
- }
- } // release lock
-
- // Wait for callback or timeout or wake. (make sure we round up, not down)
- nsecs_t currentTime = now();
- int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
- mLooper->pollOnce(timeoutMillis);
-}
-
-void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
- nsecs_t currentTime = now();
-
- // Reset the key repeat timer whenever we disallow key events, even if the next event
- // is not a key. This is to ensure that we abort a key repeat if the device is just coming
- // out of sleep.
- if (!mPolicy->isKeyRepeatEnabled()) {
- resetKeyRepeatLocked();
- }
-
- // If dispatching is frozen, do not process timeouts or try to deliver any new events.
- if (mDispatchFrozen) {
-#if DEBUG_FOCUS
- ALOGD("Dispatch frozen. Waiting some more.");
-#endif
- return;
- }
-
- // Optimize latency of app switches.
- // Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has
- // been pressed. When it expires, we preempt dispatch and drop all other pending events.
- bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
- if (mAppSwitchDueTime < *nextWakeupTime) {
- *nextWakeupTime = mAppSwitchDueTime;
- }
-
- // Ready to start a new event.
- // If we don't already have a pending event, go grab one.
- if (! mPendingEvent) {
- if (mInboundQueue.isEmpty()) {
- if (isAppSwitchDue) {
- // The inbound queue is empty so the app switch key we were waiting
- // for will never arrive. Stop waiting for it.
- resetPendingAppSwitchLocked(false);
- isAppSwitchDue = false;
- }
-
- // Synthesize a key repeat if appropriate.
- if (mKeyRepeatState.lastKeyEntry) {
- if (currentTime >= mKeyRepeatState.nextRepeatTime) {
- mPendingEvent = synthesizeKeyRepeatLocked(currentTime);
- } else {
- if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
- *nextWakeupTime = mKeyRepeatState.nextRepeatTime;
- }
- }
- }
-
- // Nothing to do if there is no pending event.
- if (!mPendingEvent) {
- return;
- }
- } else {
- // Inbound queue has at least one entry.
- mPendingEvent = mInboundQueue.dequeueAtHead();
- traceInboundQueueLengthLocked();
- }
-
- // Poke user activity for this event.
- if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
- pokeUserActivityLocked(mPendingEvent);
- }
-
- // Get ready to dispatch the event.
- resetANRTimeoutsLocked();
- }
-
- // Now we have an event to dispatch.
- // All events are eventually dequeued and processed this way, even if we intend to drop them.
- ALOG_ASSERT(mPendingEvent != NULL);
- bool done = false;
- DropReason dropReason = DROP_REASON_NOT_DROPPED;
- if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
- dropReason = DROP_REASON_POLICY;
- } else if (!mDispatchEnabled) {
- dropReason = DROP_REASON_DISABLED;
- }
-
- if (mNextUnblockedEvent == mPendingEvent) {
- mNextUnblockedEvent = NULL;
- }
-
- switch (mPendingEvent->type) {
- case EventEntry::TYPE_CONFIGURATION_CHANGED: {
- ConfigurationChangedEntry* typedEntry =
- static_cast<ConfigurationChangedEntry*>(mPendingEvent);
- done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
- dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
- break;
- }
-
- case EventEntry::TYPE_DEVICE_RESET: {
- DeviceResetEntry* typedEntry =
- static_cast<DeviceResetEntry*>(mPendingEvent);
- done = dispatchDeviceResetLocked(currentTime, typedEntry);
- dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped
- break;
- }
-
- case EventEntry::TYPE_KEY: {
- KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
- if (isAppSwitchDue) {
- if (isAppSwitchKeyEventLocked(typedEntry)) {
- resetPendingAppSwitchLocked(true);
- isAppSwitchDue = false;
- } else if (dropReason == DROP_REASON_NOT_DROPPED) {
- dropReason = DROP_REASON_APP_SWITCH;
- }
- }
- if (dropReason == DROP_REASON_NOT_DROPPED
- && isStaleEventLocked(currentTime, typedEntry)) {
- dropReason = DROP_REASON_STALE;
- }
- if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
- dropReason = DROP_REASON_BLOCKED;
- }
- done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
- break;
- }
-
- case EventEntry::TYPE_MOTION: {
- MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
- if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
- dropReason = DROP_REASON_APP_SWITCH;
- }
- if (dropReason == DROP_REASON_NOT_DROPPED
- && isStaleEventLocked(currentTime, typedEntry)) {
- dropReason = DROP_REASON_STALE;
- }
- if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
- dropReason = DROP_REASON_BLOCKED;
- }
- done = dispatchMotionLocked(currentTime, typedEntry,
- &dropReason, nextWakeupTime);
- break;
- }
-
- default:
- ALOG_ASSERT(false);
- break;
- }
-
- if (done) {
- if (dropReason != DROP_REASON_NOT_DROPPED) {
- dropInboundEventLocked(mPendingEvent, dropReason);
- }
-
- releasePendingEventLocked();
- *nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
- }
-}
-
-bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
- bool needWake = mInboundQueue.isEmpty();
- mInboundQueue.enqueueAtTail(entry);
- traceInboundQueueLengthLocked();
-
- switch (entry->type) {
- case EventEntry::TYPE_KEY: {
- // Optimize app switch latency.
- // If the application takes too long to catch up then we drop all events preceding
- // the app switch key.
- KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
- if (isAppSwitchKeyEventLocked(keyEntry)) {
- if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {
- mAppSwitchSawKeyDown = true;
- } else if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
- if (mAppSwitchSawKeyDown) {
-#if DEBUG_APP_SWITCH
- ALOGD("App switch is pending!");
-#endif
- mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;
- mAppSwitchSawKeyDown = false;
- needWake = true;
- }
- }
- }
- break;
- }
-
- case EventEntry::TYPE_MOTION: {
- // Optimize case where the current application is unresponsive and the user
- // decides to touch a window in a different application.
- // If the application takes too long to catch up then we drop all events preceding
- // the touch into the other window.
- MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
- if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN
- && (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
- && mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY
- && mInputTargetWaitApplicationHandle != NULL) {
- int32_t displayId = motionEntry->displayId;
- int32_t x = int32_t(motionEntry->pointerCoords[0].
- getAxisValue(AMOTION_EVENT_AXIS_X));
- int32_t y = int32_t(motionEntry->pointerCoords[0].
- getAxisValue(AMOTION_EVENT_AXIS_Y));
- sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y);
- if (touchedWindowHandle != NULL
- && touchedWindowHandle->inputApplicationHandle
- != mInputTargetWaitApplicationHandle) {
- // User touched a different application than the one we are waiting on.
- // Flag the event, and start pruning the input queue.
- mNextUnblockedEvent = motionEntry;
- needWake = true;
- }
- }
- break;
- }
- }
-
- return needWake;
-}
-
-void InputDispatcher::addRecentEventLocked(EventEntry* entry) {
- entry->refCount += 1;
- mRecentQueue.enqueueAtTail(entry);
- if (mRecentQueue.count() > RECENT_QUEUE_MAX_SIZE) {
- mRecentQueue.dequeueAtHead()->release();
- }
-}
-
-sp<InputWindowHandle> InputDispatcher::findTouchedWindowAtLocked(int32_t displayId,
- int32_t x, int32_t y) {
- // Traverse windows from front to back to find touched window.
- size_t numWindows = mWindowHandles.size();
- for (size_t i = 0; i < numWindows; i++) {
- sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
- const InputWindowInfo* windowInfo = windowHandle->getInfo();
- if (windowInfo->displayId == displayId) {
- int32_t flags = windowInfo->layoutParamsFlags;
- int32_t privateFlags = windowInfo->layoutParamsPrivateFlags;
-
- if (windowInfo->visible) {
- if (!(flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
- bool isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE
- | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
- if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
- // Found window.
- return windowHandle;
- }
- }
- }
-
- if (privateFlags & InputWindowInfo::PRIVATE_FLAG_SYSTEM_ERROR) {
- // Error window is on top but not visible, so touch is dropped.
- return NULL;
- }
- }
- }
- return NULL;
-}
-
-void InputDispatcher::dropInboundEventLocked(EventEntry* entry, DropReason dropReason) {
- const char* reason;
- switch (dropReason) {
- case DROP_REASON_POLICY:
-#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("Dropped event because policy consumed it.");
-#endif
- reason = "inbound event was dropped because the policy consumed it";
- break;
- case DROP_REASON_DISABLED:
- ALOGI("Dropped event because input dispatch is disabled.");
- reason = "inbound event was dropped because input dispatch is disabled";
- break;
- case DROP_REASON_APP_SWITCH:
- ALOGI("Dropped event because of pending overdue app switch.");
- reason = "inbound event was dropped because of pending overdue app switch";
- break;
- case DROP_REASON_BLOCKED:
- ALOGI("Dropped event because the current application is not responding and the user "
- "has started interacting with a different application.");
- reason = "inbound event was dropped because the current application is not responding "
- "and the user has started interacting with a different application";
- break;
- case DROP_REASON_STALE:
- ALOGI("Dropped event because it is stale.");
- reason = "inbound event was dropped because it is stale";
- break;
- default:
- ALOG_ASSERT(false);
- return;
- }
-
- switch (entry->type) {
- case EventEntry::TYPE_KEY: {
- CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, reason);
- synthesizeCancelationEventsForAllConnectionsLocked(options);
- break;
- }
- case EventEntry::TYPE_MOTION: {
- MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
- if (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER) {
- CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, reason);
- synthesizeCancelationEventsForAllConnectionsLocked(options);
- } else {
- CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, reason);
- synthesizeCancelationEventsForAllConnectionsLocked(options);
- }
- break;
- }
- }
-}
-
-bool InputDispatcher::isAppSwitchKeyCode(int32_t keyCode) {
- return keyCode == AKEYCODE_HOME
- || keyCode == AKEYCODE_ENDCALL
- || keyCode == AKEYCODE_APP_SWITCH;
-}
-
-bool InputDispatcher::isAppSwitchKeyEventLocked(KeyEntry* keyEntry) {
- return ! (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED)
- && isAppSwitchKeyCode(keyEntry->keyCode)
- && (keyEntry->policyFlags & POLICY_FLAG_TRUSTED)
- && (keyEntry->policyFlags & POLICY_FLAG_PASS_TO_USER);
-}
-
-bool InputDispatcher::isAppSwitchPendingLocked() {
- return mAppSwitchDueTime != LONG_LONG_MAX;
-}
-
-void InputDispatcher::resetPendingAppSwitchLocked(bool handled) {
- mAppSwitchDueTime = LONG_LONG_MAX;
-
-#if DEBUG_APP_SWITCH
- if (handled) {
- ALOGD("App switch has arrived.");
- } else {
- ALOGD("App switch was abandoned.");
- }
-#endif
-}
-
-bool InputDispatcher::isStaleEventLocked(nsecs_t currentTime, EventEntry* entry) {
- return currentTime - entry->eventTime >= STALE_EVENT_TIMEOUT;
-}
-
-bool InputDispatcher::haveCommandsLocked() const {
- return !mCommandQueue.isEmpty();
-}
-
-bool InputDispatcher::runCommandsLockedInterruptible() {
- if (mCommandQueue.isEmpty()) {
- return false;
- }
-
- do {
- CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
-
- Command command = commandEntry->command;
- (this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
-
- commandEntry->connection.clear();
- delete commandEntry;
- } while (! mCommandQueue.isEmpty());
- return true;
-}
-
-InputDispatcher::CommandEntry* InputDispatcher::postCommandLocked(Command command) {
- CommandEntry* commandEntry = new CommandEntry(command);
- mCommandQueue.enqueueAtTail(commandEntry);
- return commandEntry;
-}
-
-void InputDispatcher::drainInboundQueueLocked() {
- while (! mInboundQueue.isEmpty()) {
- EventEntry* entry = mInboundQueue.dequeueAtHead();
- releaseInboundEventLocked(entry);
- }
- traceInboundQueueLengthLocked();
-}
-
-void InputDispatcher::releasePendingEventLocked() {
- if (mPendingEvent) {
- resetANRTimeoutsLocked();
- releaseInboundEventLocked(mPendingEvent);
- mPendingEvent = NULL;
- }
-}
-
-void InputDispatcher::releaseInboundEventLocked(EventEntry* entry) {
- InjectionState* injectionState = entry->injectionState;
- if (injectionState && injectionState->injectionResult == INPUT_EVENT_INJECTION_PENDING) {
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("Injected inbound event was dropped.");
-#endif
- setInjectionResultLocked(entry, INPUT_EVENT_INJECTION_FAILED);
- }
- if (entry == mNextUnblockedEvent) {
- mNextUnblockedEvent = NULL;
- }
- addRecentEventLocked(entry);
- entry->release();
-}
-
-void InputDispatcher::resetKeyRepeatLocked() {
- if (mKeyRepeatState.lastKeyEntry) {
- mKeyRepeatState.lastKeyEntry->release();
- mKeyRepeatState.lastKeyEntry = NULL;
- }
-}
-
-InputDispatcher::KeyEntry* InputDispatcher::synthesizeKeyRepeatLocked(nsecs_t currentTime) {
- KeyEntry* entry = mKeyRepeatState.lastKeyEntry;
-
- // Reuse the repeated key entry if it is otherwise unreferenced.
- uint32_t policyFlags = (entry->policyFlags & POLICY_FLAG_RAW_MASK)
- | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED;
- if (entry->refCount == 1) {
- entry->recycle();
- entry->eventTime = currentTime;
- entry->policyFlags = policyFlags;
- entry->repeatCount += 1;
- } else {
- KeyEntry* newEntry = new KeyEntry(currentTime,
- entry->deviceId, entry->source, policyFlags,
- entry->action, entry->flags, entry->keyCode, entry->scanCode,
- entry->metaState, entry->repeatCount + 1, entry->downTime);
-
- mKeyRepeatState.lastKeyEntry = newEntry;
- entry->release();
-
- entry = newEntry;
- }
- entry->syntheticRepeat = true;
-
- // Increment reference count since we keep a reference to the event in
- // mKeyRepeatState.lastKeyEntry in addition to the one we return.
- entry->refCount += 1;
-
- mKeyRepeatState.nextRepeatTime = currentTime + mConfig.keyRepeatDelay;
- return entry;
-}
-
-bool InputDispatcher::dispatchConfigurationChangedLocked(
- nsecs_t currentTime, ConfigurationChangedEntry* entry) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("dispatchConfigurationChanged - eventTime=%lld", entry->eventTime);
-#endif
-
- // Reset key repeating in case a keyboard device was added or removed or something.
- resetKeyRepeatLocked();
-
- // Enqueue a command to run outside the lock to tell the policy that the configuration changed.
- CommandEntry* commandEntry = postCommandLocked(
- & InputDispatcher::doNotifyConfigurationChangedInterruptible);
- commandEntry->eventTime = entry->eventTime;
- return true;
-}
-
-bool InputDispatcher::dispatchDeviceResetLocked(
- nsecs_t currentTime, DeviceResetEntry* entry) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("dispatchDeviceReset - eventTime=%lld, deviceId=%d", entry->eventTime, entry->deviceId);
-#endif
-
- CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS,
- "device was reset");
- options.deviceId = entry->deviceId;
- synthesizeCancelationEventsForAllConnectionsLocked(options);
- return true;
-}
-
-bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
- DropReason* dropReason, nsecs_t* nextWakeupTime) {
- // Preprocessing.
- if (! entry->dispatchInProgress) {
- if (entry->repeatCount == 0
- && entry->action == AKEY_EVENT_ACTION_DOWN
- && (entry->policyFlags & POLICY_FLAG_TRUSTED)
- && (!(entry->policyFlags & POLICY_FLAG_DISABLE_KEY_REPEAT))) {
- if (mKeyRepeatState.lastKeyEntry
- && mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
- // We have seen two identical key downs in a row which indicates that the device
- // driver is automatically generating key repeats itself. We take note of the
- // repeat here, but we disable our own next key repeat timer since it is clear that
- // we will not need to synthesize key repeats ourselves.
- entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
- resetKeyRepeatLocked();
- mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
- } else {
- // Not a repeat. Save key down state in case we do see a repeat later.
- resetKeyRepeatLocked();
- mKeyRepeatState.nextRepeatTime = entry->eventTime + mConfig.keyRepeatTimeout;
- }
- mKeyRepeatState.lastKeyEntry = entry;
- entry->refCount += 1;
- } else if (! entry->syntheticRepeat) {
- resetKeyRepeatLocked();
- }
-
- if (entry->repeatCount == 1) {
- entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
- } else {
- entry->flags &= ~AKEY_EVENT_FLAG_LONG_PRESS;
- }
-
- entry->dispatchInProgress = true;
-
- logOutboundKeyDetailsLocked("dispatchKey - ", entry);
- }
-
- // Handle case where the policy asked us to try again later last time.
- if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) {
- if (currentTime < entry->interceptKeyWakeupTime) {
- if (entry->interceptKeyWakeupTime < *nextWakeupTime) {
- *nextWakeupTime = entry->interceptKeyWakeupTime;
- }
- return false; // wait until next wakeup
- }
- entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
- entry->interceptKeyWakeupTime = 0;
- }
-
- // Give the policy a chance to intercept the key.
- if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
- if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
- CommandEntry* commandEntry = postCommandLocked(
- & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
- if (mFocusedWindowHandle != NULL) {
- commandEntry->inputWindowHandle = mFocusedWindowHandle;
- }
- commandEntry->keyEntry = entry;
- entry->refCount += 1;
- return false; // wait for the command to run
- } else {
- entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
- }
- } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
- if (*dropReason == DROP_REASON_NOT_DROPPED) {
- *dropReason = DROP_REASON_POLICY;
- }
- }
-
- // Clean up if dropping the event.
- if (*dropReason != DROP_REASON_NOT_DROPPED) {
- setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
- ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
- return true;
- }
-
- // Identify targets.
- Vector<InputTarget> inputTargets;
- int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
- entry, inputTargets, nextWakeupTime);
- if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
- return false;
- }
-
- setInjectionResultLocked(entry, injectionResult);
- if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
- return true;
- }
-
- addMonitoringTargetsLocked(inputTargets);
-
- // Dispatch the key.
- dispatchEventLocked(currentTime, entry, inputTargets);
- return true;
-}
-
-void InputDispatcher::logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
- "action=0x%x, flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, "
- "repeatCount=%d, downTime=%lld",
- prefix,
- entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
- entry->action, entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
- entry->repeatCount, entry->downTime);
-#endif
-}
-
-bool InputDispatcher::dispatchMotionLocked(
- nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
- // Preprocessing.
- if (! entry->dispatchInProgress) {
- entry->dispatchInProgress = true;
-
- logOutboundMotionDetailsLocked("dispatchMotion - ", entry);
- }
-
- // Clean up if dropping the event.
- if (*dropReason != DROP_REASON_NOT_DROPPED) {
- setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
- ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
- return true;
- }
-
- bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
-
- // Identify targets.
- Vector<InputTarget> inputTargets;
-
- bool conflictingPointerActions = false;
- int32_t injectionResult;
- if (isPointerEvent) {
- // Pointer event. (eg. touchscreen)
- injectionResult = findTouchedWindowTargetsLocked(currentTime,
- entry, inputTargets, nextWakeupTime, &conflictingPointerActions);
- } else {
- // Non touch event. (eg. trackball)
- injectionResult = findFocusedWindowTargetsLocked(currentTime,
- entry, inputTargets, nextWakeupTime);
- }
- if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
- return false;
- }
-
- setInjectionResultLocked(entry, injectionResult);
- if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
- return true;
- }
-
- // TODO: support sending secondary display events to input monitors
- if (isMainDisplay(entry->displayId)) {
- addMonitoringTargetsLocked(inputTargets);
- }
-
- // Dispatch the motion.
- if (conflictingPointerActions) {
- CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
- "conflicting pointer actions");
- synthesizeCancelationEventsForAllConnectionsLocked(options);
- }
- dispatchEventLocked(currentTime, entry, inputTargets);
- return true;
-}
-
-
-void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("%seventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
- "action=0x%x, flags=0x%x, "
- "metaState=0x%x, buttonState=0x%x, "
- "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%lld",
- prefix,
- entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
- entry->action, entry->flags,
- entry->metaState, entry->buttonState,
- entry->edgeFlags, entry->xPrecision, entry->yPrecision,
- entry->downTime);
-
- for (uint32_t i = 0; i < entry->pointerCount; i++) {
- ALOGD(" Pointer %d: id=%d, toolType=%d, "
- "x=%f, y=%f, pressure=%f, size=%f, "
- "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
- "orientation=%f",
- i, entry->pointerProperties[i].id,
- entry->pointerProperties[i].toolType,
- entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
- entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
- entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
- entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),
- entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
- entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
- entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
- entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
- entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
- }
-#endif
-}
-
-void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
- EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) {
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("dispatchEventToCurrentInputTargets");
-#endif
-
- ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true
-
- pokeUserActivityLocked(eventEntry);
-
- for (size_t i = 0; i < inputTargets.size(); i++) {
- const InputTarget& inputTarget = inputTargets.itemAt(i);
-
- ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
- if (connectionIndex >= 0) {
- sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
- prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
- } else {
-#if DEBUG_FOCUS
- ALOGD("Dropping event delivery to target with channel '%s' because it "
- "is no longer registered with the input dispatcher.",
- inputTarget.inputChannel->getName().string());
-#endif
- }
- }
-}
-
-int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
- const EventEntry* entry,
- const sp<InputApplicationHandle>& applicationHandle,
- const sp<InputWindowHandle>& windowHandle,
- nsecs_t* nextWakeupTime, const char* reason) {
- if (applicationHandle == NULL && windowHandle == NULL) {
- if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
-#if DEBUG_FOCUS
- ALOGD("Waiting for system to become ready for input. Reason: %s", reason);
-#endif
- mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;
- mInputTargetWaitStartTime = currentTime;
- mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
- mInputTargetWaitTimeoutExpired = false;
- mInputTargetWaitApplicationHandle.clear();
- }
- } else {
- if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
-#if DEBUG_FOCUS
- ALOGD("Waiting for application to become ready for input: %s. Reason: %s",
- getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(),
- reason);
-#endif
- nsecs_t timeout;
- if (windowHandle != NULL) {
- timeout = windowHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
- } else if (applicationHandle != NULL) {
- timeout = applicationHandle->getDispatchingTimeout(
- DEFAULT_INPUT_DISPATCHING_TIMEOUT);
- } else {
- timeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
- }
-
- mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
- mInputTargetWaitStartTime = currentTime;
- mInputTargetWaitTimeoutTime = currentTime + timeout;
- mInputTargetWaitTimeoutExpired = false;
- mInputTargetWaitApplicationHandle.clear();
-
- if (windowHandle != NULL) {
- mInputTargetWaitApplicationHandle = windowHandle->inputApplicationHandle;
- }
- if (mInputTargetWaitApplicationHandle == NULL && applicationHandle != NULL) {
- mInputTargetWaitApplicationHandle = applicationHandle;
- }
- }
- }
-
- if (mInputTargetWaitTimeoutExpired) {
- return INPUT_EVENT_INJECTION_TIMED_OUT;
- }
-
- if (currentTime >= mInputTargetWaitTimeoutTime) {
- onANRLocked(currentTime, applicationHandle, windowHandle,
- entry->eventTime, mInputTargetWaitStartTime, reason);
-
- // Force poll loop to wake up immediately on next iteration once we get the
- // ANR response back from the policy.
- *nextWakeupTime = LONG_LONG_MIN;
- return INPUT_EVENT_INJECTION_PENDING;
- } else {
- // Force poll loop to wake up when timeout is due.
- if (mInputTargetWaitTimeoutTime < *nextWakeupTime) {
- *nextWakeupTime = mInputTargetWaitTimeoutTime;
- }
- return INPUT_EVENT_INJECTION_PENDING;
- }
-}
-
-void InputDispatcher::resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
- const sp<InputChannel>& inputChannel) {
- if (newTimeout > 0) {
- // Extend the timeout.
- mInputTargetWaitTimeoutTime = now() + newTimeout;
- } else {
- // Give up.
- mInputTargetWaitTimeoutExpired = true;
-
- // Input state will not be realistic. Mark it out of sync.
- if (inputChannel.get()) {
- ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
- if (connectionIndex >= 0) {
- sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
- sp<InputWindowHandle> windowHandle = connection->inputWindowHandle;
-
- if (windowHandle != NULL) {
- mTouchState.removeWindow(windowHandle);
- }
-
- if (connection->status == Connection::STATUS_NORMAL) {
- CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS,
- "application not responding");
- synthesizeCancelationEventsForConnectionLocked(connection, options);
- }
- }
- }
- }
-}
-
-nsecs_t InputDispatcher::getTimeSpentWaitingForApplicationLocked(
- nsecs_t currentTime) {
- if (mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
- return currentTime - mInputTargetWaitStartTime;
- }
- return 0;
-}
-
-void InputDispatcher::resetANRTimeoutsLocked() {
-#if DEBUG_FOCUS
- ALOGD("Resetting ANR timeouts.");
-#endif
-
- // Reset input target wait timeout.
- mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_NONE;
- mInputTargetWaitApplicationHandle.clear();
-}
-
-int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
- const EventEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime) {
- int32_t injectionResult;
-
- // If there is no currently focused window and no focused application
- // then drop the event.
- if (mFocusedWindowHandle == NULL) {
- if (mFocusedApplicationHandle != NULL) {
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- mFocusedApplicationHandle, NULL, nextWakeupTime,
- "Waiting because no window has focus but there is a "
- "focused application that may eventually add a window "
- "when it finishes starting up.");
- goto Unresponsive;
- }
-
- ALOGI("Dropping event because there is no focused window or focused application.");
- injectionResult = INPUT_EVENT_INJECTION_FAILED;
- goto Failed;
- }
-
- // Check permissions.
- if (! checkInjectionPermission(mFocusedWindowHandle, entry->injectionState)) {
- injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
- goto Failed;
- }
-
- // If the currently focused window is paused then keep waiting.
- if (mFocusedWindowHandle->getInfo()->paused) {
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime,
- "Waiting because the focused window is paused.");
- goto Unresponsive;
- }
-
- // If the currently focused window is still working on previous events then keep waiting.
- if (!isWindowReadyForMoreInputLocked(currentTime, mFocusedWindowHandle, entry)) {
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime,
- "Waiting because the focused window has not finished "
- "processing the input events that were previously delivered to it.");
- goto Unresponsive;
- }
-
- // Success! Output targets.
- injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
- addWindowTargetLocked(mFocusedWindowHandle,
- InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0),
- inputTargets);
-
- // Done.
-Failed:
-Unresponsive:
- nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
- updateDispatchStatisticsLocked(currentTime, entry,
- injectionResult, timeSpentWaitingForApplication);
-#if DEBUG_FOCUS
- ALOGD("findFocusedWindow finished: injectionResult=%d, "
- "timeSpentWaitingForApplication=%0.1fms",
- injectionResult, timeSpentWaitingForApplication / 1000000.0);
-#endif
- return injectionResult;
-}
-
-int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
- const MotionEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime,
- bool* outConflictingPointerActions) {
- enum InjectionPermission {
- INJECTION_PERMISSION_UNKNOWN,
- INJECTION_PERMISSION_GRANTED,
- INJECTION_PERMISSION_DENIED
- };
-
- nsecs_t startTime = now();
-
- // For security reasons, we defer updating the touch state until we are sure that
- // event injection will be allowed.
- //
- // FIXME In the original code, screenWasOff could never be set to true.
- // The reason is that the POLICY_FLAG_WOKE_HERE
- // and POLICY_FLAG_BRIGHT_HERE flags were set only when preprocessing raw
- // EV_KEY, EV_REL and EV_ABS events. As it happens, the touch event was
- // actually enqueued using the policyFlags that appeared in the final EV_SYN
- // events upon which no preprocessing took place. So policyFlags was always 0.
- // In the new native input dispatcher we're a bit more careful about event
- // preprocessing so the touches we receive can actually have non-zero policyFlags.
- // Unfortunately we obtain undesirable behavior.
- //
- // Here's what happens:
- //
- // When the device dims in anticipation of going to sleep, touches
- // in windows which have FLAG_TOUCHABLE_WHEN_WAKING cause
- // the device to brighten and reset the user activity timer.
- // Touches on other windows (such as the launcher window)
- // are dropped. Then after a moment, the device goes to sleep. Oops.
- //
- // Also notice how screenWasOff was being initialized using POLICY_FLAG_BRIGHT_HERE
- // instead of POLICY_FLAG_WOKE_HERE...
- //
- bool screenWasOff = false; // original policy: policyFlags & POLICY_FLAG_BRIGHT_HERE;
-
- int32_t displayId = entry->displayId;
- int32_t action = entry->action;
- int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
-
- // Update the touch state as needed based on the properties of the touch event.
- int32_t injectionResult = INPUT_EVENT_INJECTION_PENDING;
- InjectionPermission injectionPermission = INJECTION_PERMISSION_UNKNOWN;
- sp<InputWindowHandle> newHoverWindowHandle;
-
- bool isSplit = mTouchState.split;
- bool switchedDevice = mTouchState.deviceId >= 0 && mTouchState.displayId >= 0
- && (mTouchState.deviceId != entry->deviceId
- || mTouchState.source != entry->source
- || mTouchState.displayId != displayId);
- bool isHoverAction = (maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
- || maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER
- || maskedAction == AMOTION_EVENT_ACTION_HOVER_EXIT);
- bool newGesture = (maskedAction == AMOTION_EVENT_ACTION_DOWN
- || maskedAction == AMOTION_EVENT_ACTION_SCROLL
- || isHoverAction);
- bool wrongDevice = false;
- if (newGesture) {
- bool down = maskedAction == AMOTION_EVENT_ACTION_DOWN;
- if (switchedDevice && mTouchState.down && !down) {
-#if DEBUG_FOCUS
- ALOGD("Dropping event because a pointer for a different device is already down.");
-#endif
- mTempTouchState.copyFrom(mTouchState);
- injectionResult = INPUT_EVENT_INJECTION_FAILED;
- switchedDevice = false;
- wrongDevice = true;
- goto Failed;
- }
- mTempTouchState.reset();
- mTempTouchState.down = down;
- mTempTouchState.deviceId = entry->deviceId;
- mTempTouchState.source = entry->source;
- mTempTouchState.displayId = displayId;
- isSplit = false;
- } else {
- mTempTouchState.copyFrom(mTouchState);
- }
-
- if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
- /* Case 1: New splittable pointer going down, or need target for hover or scroll. */
-
- int32_t pointerIndex = getMotionEventActionPointerIndex(action);
- int32_t x = int32_t(entry->pointerCoords[pointerIndex].
- getAxisValue(AMOTION_EVENT_AXIS_X));
- int32_t y = int32_t(entry->pointerCoords[pointerIndex].
- getAxisValue(AMOTION_EVENT_AXIS_Y));
- sp<InputWindowHandle> newTouchedWindowHandle;
- sp<InputWindowHandle> topErrorWindowHandle;
- bool isTouchModal = false;
-
- // Traverse windows from front to back to find touched window and outside targets.
- size_t numWindows = mWindowHandles.size();
- for (size_t i = 0; i < numWindows; i++) {
- sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
- const InputWindowInfo* windowInfo = windowHandle->getInfo();
- if (windowInfo->displayId != displayId) {
- continue; // wrong display
- }
-
- int32_t privateFlags = windowInfo->layoutParamsPrivateFlags;
- if (privateFlags & InputWindowInfo::PRIVATE_FLAG_SYSTEM_ERROR) {
- if (topErrorWindowHandle == NULL) {
- topErrorWindowHandle = windowHandle;
- }
- }
-
- int32_t flags = windowInfo->layoutParamsFlags;
- if (windowInfo->visible) {
- if (! (flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
- isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE
- | InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
- if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
- if (! screenWasOff
- || (flags & InputWindowInfo::FLAG_TOUCHABLE_WHEN_WAKING)) {
- newTouchedWindowHandle = windowHandle;
- }
- break; // found touched window, exit window loop
- }
- }
-
- if (maskedAction == AMOTION_EVENT_ACTION_DOWN
- && (flags & InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH)) {
- int32_t outsideTargetFlags = InputTarget::FLAG_DISPATCH_AS_OUTSIDE;
- if (isWindowObscuredAtPointLocked(windowHandle, x, y)) {
- outsideTargetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
- }
-
- mTempTouchState.addOrUpdateWindow(
- windowHandle, outsideTargetFlags, BitSet32(0));
- }
- }
- }
-
- // If there is an error window but it is not taking focus (typically because
- // it is invisible) then wait for it. Any other focused window may in
- // fact be in ANR state.
- if (topErrorWindowHandle != NULL && newTouchedWindowHandle != topErrorWindowHandle) {
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- NULL, NULL, nextWakeupTime,
- "Waiting because a system error window is about to be displayed.");
- injectionPermission = INJECTION_PERMISSION_UNKNOWN;
- goto Unresponsive;
- }
-
- // Figure out whether splitting will be allowed for this window.
- if (newTouchedWindowHandle != NULL
- && newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
- // New window supports splitting.
- isSplit = true;
- } else if (isSplit) {
- // New window does not support splitting but we have already split events.
- // Ignore the new window.
- newTouchedWindowHandle = NULL;
- }
-
- // Handle the case where we did not find a window.
- if (newTouchedWindowHandle == NULL) {
- // Try to assign the pointer to the first foreground window we find, if there is one.
- newTouchedWindowHandle = mTempTouchState.getFirstForegroundWindowHandle();
- if (newTouchedWindowHandle == NULL) {
- ALOGI("Dropping event because there is no touchable window at (%d, %d).", x, y);
- injectionResult = INPUT_EVENT_INJECTION_FAILED;
- goto Failed;
- }
- }
-
- // Set target flags.
- int32_t targetFlags = InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS;
- if (isSplit) {
- targetFlags |= InputTarget::FLAG_SPLIT;
- }
- if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
- targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
- }
-
- // Update hover state.
- if (isHoverAction) {
- newHoverWindowHandle = newTouchedWindowHandle;
- } else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) {
- newHoverWindowHandle = mLastHoverWindowHandle;
- }
-
- // Update the temporary touch state.
- BitSet32 pointerIds;
- if (isSplit) {
- uint32_t pointerId = entry->pointerProperties[pointerIndex].id;
- pointerIds.markBit(pointerId);
- }
- mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
- } else {
- /* Case 2: Pointer move, up, cancel or non-splittable pointer down. */
-
- // If the pointer is not currently down, then ignore the event.
- if (! mTempTouchState.down) {
-#if DEBUG_FOCUS
- ALOGD("Dropping event because the pointer is not down or we previously "
- "dropped the pointer down event.");
-#endif
- injectionResult = INPUT_EVENT_INJECTION_FAILED;
- goto Failed;
- }
-
- // Check whether touches should slip outside of the current foreground window.
- if (maskedAction == AMOTION_EVENT_ACTION_MOVE
- && entry->pointerCount == 1
- && mTempTouchState.isSlippery()) {
- int32_t x = int32_t(entry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));
- int32_t y = int32_t(entry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));
-
- sp<InputWindowHandle> oldTouchedWindowHandle =
- mTempTouchState.getFirstForegroundWindowHandle();
- sp<InputWindowHandle> newTouchedWindowHandle =
- findTouchedWindowAtLocked(displayId, x, y);
- if (oldTouchedWindowHandle != newTouchedWindowHandle
- && newTouchedWindowHandle != NULL) {
-#if DEBUG_FOCUS
- ALOGD("Touch is slipping out of window %s into window %s.",
- oldTouchedWindowHandle->getName().string(),
- newTouchedWindowHandle->getName().string());
-#endif
- // Make a slippery exit from the old window.
- mTempTouchState.addOrUpdateWindow(oldTouchedWindowHandle,
- InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT, BitSet32(0));
-
- // Make a slippery entrance into the new window.
- if (newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
- isSplit = true;
- }
-
- int32_t targetFlags = InputTarget::FLAG_FOREGROUND
- | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER;
- if (isSplit) {
- targetFlags |= InputTarget::FLAG_SPLIT;
- }
- if (isWindowObscuredAtPointLocked(newTouchedWindowHandle, x, y)) {
- targetFlags |= InputTarget::FLAG_WINDOW_IS_OBSCURED;
- }
-
- BitSet32 pointerIds;
- if (isSplit) {
- pointerIds.markBit(entry->pointerProperties[0].id);
- }
- mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
- }
- }
- }
-
- if (newHoverWindowHandle != mLastHoverWindowHandle) {
- // Let the previous window know that the hover sequence is over.
- if (mLastHoverWindowHandle != NULL) {
-#if DEBUG_HOVER
- ALOGD("Sending hover exit event to window %s.",
- mLastHoverWindowHandle->getName().string());
-#endif
- mTempTouchState.addOrUpdateWindow(mLastHoverWindowHandle,
- InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT, BitSet32(0));
- }
-
- // Let the new window know that the hover sequence is starting.
- if (newHoverWindowHandle != NULL) {
-#if DEBUG_HOVER
- ALOGD("Sending hover enter event to window %s.",
- newHoverWindowHandle->getName().string());
-#endif
- mTempTouchState.addOrUpdateWindow(newHoverWindowHandle,
- InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER, BitSet32(0));
- }
- }
-
- // Check permission to inject into all touched foreground windows and ensure there
- // is at least one touched foreground window.
- {
- bool haveForegroundWindow = false;
- for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
- const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
- if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
- haveForegroundWindow = true;
- if (! checkInjectionPermission(touchedWindow.windowHandle,
- entry->injectionState)) {
- injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
- injectionPermission = INJECTION_PERMISSION_DENIED;
- goto Failed;
- }
- }
- }
- if (! haveForegroundWindow) {
-#if DEBUG_FOCUS
- ALOGD("Dropping event because there is no touched foreground window to receive it.");
-#endif
- injectionResult = INPUT_EVENT_INJECTION_FAILED;
- goto Failed;
- }
-
- // Permission granted to injection into all touched foreground windows.
- injectionPermission = INJECTION_PERMISSION_GRANTED;
- }
-
- // Check whether windows listening for outside touches are owned by the same UID. If it is
- // set the policy flag that we will not reveal coordinate information to this window.
- if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
- sp<InputWindowHandle> foregroundWindowHandle =
- mTempTouchState.getFirstForegroundWindowHandle();
- const int32_t foregroundWindowUid = foregroundWindowHandle->getInfo()->ownerUid;
- for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
- const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
- if (touchedWindow.targetFlags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
- sp<InputWindowHandle> inputWindowHandle = touchedWindow.windowHandle;
- if (inputWindowHandle->getInfo()->ownerUid != foregroundWindowUid) {
- mTempTouchState.addOrUpdateWindow(inputWindowHandle,
- InputTarget::FLAG_ZERO_COORDS, BitSet32(0));
- }
- }
- }
- }
-
- // Ensure all touched foreground windows are ready for new input.
- for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
- const TouchedWindow& touchedWindow = mTempTouchState.windows[i];
- if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
- // If the touched window is paused then keep waiting.
- if (touchedWindow.windowHandle->getInfo()->paused) {
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- NULL, touchedWindow.windowHandle, nextWakeupTime,
- "Waiting because the touched window is paused.");
- goto Unresponsive;
- }
-
- // If the touched window is still working on previous events then keep waiting.
- if (!isWindowReadyForMoreInputLocked(currentTime, touchedWindow.windowHandle, entry)) {
- injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
- NULL, touchedWindow.windowHandle, nextWakeupTime,
- "Waiting because the touched window has not finished "
- "processing the input events that were previously delivered to it.");
- goto Unresponsive;
- }
- }
- }
-
- // If this is the first pointer going down and the touched window has a wallpaper
- // then also add the touched wallpaper windows so they are locked in for the duration
- // of the touch gesture.
- // We do not collect wallpapers during HOVER_MOVE or SCROLL because the wallpaper
- // engine only supports touch events. We would need to add a mechanism similar
- // to View.onGenericMotionEvent to enable wallpapers to handle these events.
- if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
- sp<InputWindowHandle> foregroundWindowHandle =
- mTempTouchState.getFirstForegroundWindowHandle();
- if (foregroundWindowHandle->getInfo()->hasWallpaper) {
- for (size_t i = 0; i < mWindowHandles.size(); i++) {
- sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
- const InputWindowInfo* info = windowHandle->getInfo();
- if (info->displayId == displayId
- && windowHandle->getInfo()->layoutParamsType
- == InputWindowInfo::TYPE_WALLPAPER) {
- mTempTouchState.addOrUpdateWindow(windowHandle,
- InputTarget::FLAG_WINDOW_IS_OBSCURED
- | InputTarget::FLAG_DISPATCH_AS_IS,
- BitSet32(0));
- }
- }
- }
- }
-
- // Success! Output targets.
- injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
-
- for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
- const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);
- addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
- touchedWindow.pointerIds, inputTargets);
- }
-
- // Drop the outside or hover touch windows since we will not care about them
- // in the next iteration.
- mTempTouchState.filterNonAsIsTouchWindows();
-
-Failed:
- // Check injection permission once and for all.
- if (injectionPermission == INJECTION_PERMISSION_UNKNOWN) {
- if (checkInjectionPermission(NULL, entry->injectionState)) {
- injectionPermission = INJECTION_PERMISSION_GRANTED;
- } else {
- injectionPermission = INJECTION_PERMISSION_DENIED;
- }
- }
-
- // Update final pieces of touch state if the injector had permission.
- if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
- if (!wrongDevice) {
- if (switchedDevice) {
-#if DEBUG_FOCUS
- ALOGD("Conflicting pointer actions: Switched to a different device.");
-#endif
- *outConflictingPointerActions = true;
- }
-
- if (isHoverAction) {
- // Started hovering, therefore no longer down.
- if (mTouchState.down) {
-#if DEBUG_FOCUS
- ALOGD("Conflicting pointer actions: Hover received while pointer was down.");
-#endif
- *outConflictingPointerActions = true;
- }
- mTouchState.reset();
- if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER
- || maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
- mTouchState.deviceId = entry->deviceId;
- mTouchState.source = entry->source;
- mTouchState.displayId = displayId;
- }
- } else if (maskedAction == AMOTION_EVENT_ACTION_UP
- || maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
- // All pointers up or canceled.
- mTouchState.reset();
- } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
- // First pointer went down.
- if (mTouchState.down) {
-#if DEBUG_FOCUS
- ALOGD("Conflicting pointer actions: Down received while already down.");
-#endif
- *outConflictingPointerActions = true;
- }
- mTouchState.copyFrom(mTempTouchState);
- } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
- // One pointer went up.
- if (isSplit) {
- int32_t pointerIndex = getMotionEventActionPointerIndex(action);
- uint32_t pointerId = entry->pointerProperties[pointerIndex].id;
-
- for (size_t i = 0; i < mTempTouchState.windows.size(); ) {
- TouchedWindow& touchedWindow = mTempTouchState.windows.editItemAt(i);
- if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) {
- touchedWindow.pointerIds.clearBit(pointerId);
- if (touchedWindow.pointerIds.isEmpty()) {
- mTempTouchState.windows.removeAt(i);
- continue;
- }
- }
- i += 1;
- }
- }
- mTouchState.copyFrom(mTempTouchState);
- } else if (maskedAction == AMOTION_EVENT_ACTION_SCROLL) {
- // Discard temporary touch state since it was only valid for this action.
- } else {
- // Save changes to touch state as-is for all other actions.
- mTouchState.copyFrom(mTempTouchState);
- }
-
- // Update hover state.
- mLastHoverWindowHandle = newHoverWindowHandle;
- }
- } else {
-#if DEBUG_FOCUS
- ALOGD("Not updating touch focus because injection was denied.");
-#endif
- }
-
-Unresponsive:
- // Reset temporary touch state to ensure we release unnecessary references to input channels.
- mTempTouchState.reset();
-
- nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
- updateDispatchStatisticsLocked(currentTime, entry,
- injectionResult, timeSpentWaitingForApplication);
-#if DEBUG_FOCUS
- ALOGD("findTouchedWindow finished: injectionResult=%d, injectionPermission=%d, "
- "timeSpentWaitingForApplication=%0.1fms",
- injectionResult, injectionPermission, timeSpentWaitingForApplication / 1000000.0);
-#endif
- return injectionResult;
-}
-
-void InputDispatcher::addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
- int32_t targetFlags, BitSet32 pointerIds, Vector<InputTarget>& inputTargets) {
- inputTargets.push();
-
- const InputWindowInfo* windowInfo = windowHandle->getInfo();
- InputTarget& target = inputTargets.editTop();
- target.inputChannel = windowInfo->inputChannel;
- target.flags = targetFlags;
- target.xOffset = - windowInfo->frameLeft;
- target.yOffset = - windowInfo->frameTop;
- target.scaleFactor = windowInfo->scaleFactor;
- target.pointerIds = pointerIds;
-}
-
-void InputDispatcher::addMonitoringTargetsLocked(Vector<InputTarget>& inputTargets) {
- for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
- inputTargets.push();
-
- InputTarget& target = inputTargets.editTop();
- target.inputChannel = mMonitoringChannels[i];
- target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
- target.xOffset = 0;
- target.yOffset = 0;
- target.pointerIds.clear();
- target.scaleFactor = 1.0f;
- }
-}
-
-bool InputDispatcher::checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
- const InjectionState* injectionState) {
- if (injectionState
- && (windowHandle == NULL
- || windowHandle->getInfo()->ownerUid != injectionState->injectorUid)
- && !hasInjectionPermission(injectionState->injectorPid, injectionState->injectorUid)) {
- if (windowHandle != NULL) {
- ALOGW("Permission denied: injecting event from pid %d uid %d to window %s "
- "owned by uid %d",
- injectionState->injectorPid, injectionState->injectorUid,
- windowHandle->getName().string(),
- windowHandle->getInfo()->ownerUid);
- } else {
- ALOGW("Permission denied: injecting event from pid %d uid %d",
- injectionState->injectorPid, injectionState->injectorUid);
- }
- return false;
- }
- return true;
-}
-
-bool InputDispatcher::isWindowObscuredAtPointLocked(
- const sp<InputWindowHandle>& windowHandle, int32_t x, int32_t y) const {
- int32_t displayId = windowHandle->getInfo()->displayId;
- size_t numWindows = mWindowHandles.size();
- for (size_t i = 0; i < numWindows; i++) {
- sp<InputWindowHandle> otherHandle = mWindowHandles.itemAt(i);
- if (otherHandle == windowHandle) {
- break;
- }
-
- const InputWindowInfo* otherInfo = otherHandle->getInfo();
- if (otherInfo->displayId == displayId
- && otherInfo->visible && !otherInfo->isTrustedOverlay()
- && otherInfo->frameContainsPoint(x, y)) {
- return true;
- }
- }
- return false;
-}
-
-bool InputDispatcher::isWindowReadyForMoreInputLocked(nsecs_t currentTime,
- const sp<InputWindowHandle>& windowHandle, const EventEntry* eventEntry) {
- ssize_t connectionIndex = getConnectionIndexLocked(windowHandle->getInputChannel());
- if (connectionIndex >= 0) {
- sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
- if (connection->inputPublisherBlocked) {
- return false;
- }
- if (eventEntry->type == EventEntry::TYPE_KEY) {
- // If the event is a key event, then we must wait for all previous events to
- // complete before delivering it because previous events may have the
- // side-effect of transferring focus to a different window and we want to
- // ensure that the following keys are sent to the new window.
- //
- // Suppose the user touches a button in a window then immediately presses "A".
- // If the button causes a pop-up window to appear then we want to ensure that
- // the "A" key is delivered to the new pop-up window. This is because users
- // often anticipate pending UI changes when typing on a keyboard.
- // To obtain this behavior, we must serialize key events with respect to all
- // prior input events.
- return connection->outboundQueue.isEmpty()
- && connection->waitQueue.isEmpty();
- }
- // Touch events can always be sent to a window immediately because the user intended
- // to touch whatever was visible at the time. Even if focus changes or a new
- // window appears moments later, the touch event was meant to be delivered to
- // whatever window happened to be on screen at the time.
- //
- // Generic motion events, such as trackball or joystick events are a little trickier.
- // Like key events, generic motion events are delivered to the focused window.
- // Unlike key events, generic motion events don't tend to transfer focus to other
- // windows and it is not important for them to be serialized. So we prefer to deliver
- // generic motion events as soon as possible to improve efficiency and reduce lag
- // through batching.
- //
- // The one case where we pause input event delivery is when the wait queue is piling
- // up with lots of events because the application is not responding.
- // This condition ensures that ANRs are detected reliably.
- if (!connection->waitQueue.isEmpty()
- && currentTime >= connection->waitQueue.head->deliveryTime
- + STREAM_AHEAD_EVENT_TIMEOUT) {
- return false;
- }
- }
- return true;
-}
-
-String8 InputDispatcher::getApplicationWindowLabelLocked(
- const sp<InputApplicationHandle>& applicationHandle,
- const sp<InputWindowHandle>& windowHandle) {
- if (applicationHandle != NULL) {
- if (windowHandle != NULL) {
- String8 label(applicationHandle->getName());
- label.append(" - ");
- label.append(windowHandle->getName());
- return label;
- } else {
- return applicationHandle->getName();
- }
- } else if (windowHandle != NULL) {
- return windowHandle->getName();
- } else {
- return String8("<unknown application or window>");
- }
-}
-
-void InputDispatcher::pokeUserActivityLocked(const EventEntry* eventEntry) {
- if (mFocusedWindowHandle != NULL) {
- const InputWindowInfo* info = mFocusedWindowHandle->getInfo();
- if (info->inputFeatures & InputWindowInfo::INPUT_FEATURE_DISABLE_USER_ACTIVITY) {
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("Not poking user activity: disabled by window '%s'.", info->name.string());
-#endif
- return;
- }
- }
-
- int32_t eventType = USER_ACTIVITY_EVENT_OTHER;
- switch (eventEntry->type) {
- case EventEntry::TYPE_MOTION: {
- const MotionEntry* motionEntry = static_cast<const MotionEntry*>(eventEntry);
- if (motionEntry->action == AMOTION_EVENT_ACTION_CANCEL) {
- return;
- }
-
- if (MotionEvent::isTouchEvent(motionEntry->source, motionEntry->action)) {
- eventType = USER_ACTIVITY_EVENT_TOUCH;
- }
- break;
- }
- case EventEntry::TYPE_KEY: {
- const KeyEntry* keyEntry = static_cast<const KeyEntry*>(eventEntry);
- if (keyEntry->flags & AKEY_EVENT_FLAG_CANCELED) {
- return;
- }
- eventType = USER_ACTIVITY_EVENT_BUTTON;
- break;
- }
- }
-
- CommandEntry* commandEntry = postCommandLocked(
- & InputDispatcher::doPokeUserActivityLockedInterruptible);
- commandEntry->eventTime = eventEntry->eventTime;
- commandEntry->userActivityEventType = eventType;
-}
-
-void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ prepareDispatchCycle - flags=0x%08x, "
- "xOffset=%f, yOffset=%f, scaleFactor=%f, "
- "pointerIds=0x%x",
- connection->getInputChannelName(), inputTarget->flags,
- inputTarget->xOffset, inputTarget->yOffset,
- inputTarget->scaleFactor, inputTarget->pointerIds.value);
-#endif
-
- // Skip this event if the connection status is not normal.
- // We don't want to enqueue additional outbound events if the connection is broken.
- if (connection->status != Connection::STATUS_NORMAL) {
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ Dropping event because the channel status is %s",
- connection->getInputChannelName(), connection->getStatusLabel());
-#endif
- return;
- }
-
- // Split a motion event if needed.
- if (inputTarget->flags & InputTarget::FLAG_SPLIT) {
- ALOG_ASSERT(eventEntry->type == EventEntry::TYPE_MOTION);
-
- MotionEntry* originalMotionEntry = static_cast<MotionEntry*>(eventEntry);
- if (inputTarget->pointerIds.count() != originalMotionEntry->pointerCount) {
- MotionEntry* splitMotionEntry = splitMotionEvent(
- originalMotionEntry, inputTarget->pointerIds);
- if (!splitMotionEntry) {
- return; // split event was dropped
- }
-#if DEBUG_FOCUS
- ALOGD("channel '%s' ~ Split motion event.",
- connection->getInputChannelName());
- logOutboundMotionDetailsLocked(" ", splitMotionEntry);
-#endif
- enqueueDispatchEntriesLocked(currentTime, connection,
- splitMotionEntry, inputTarget);
- splitMotionEntry->release();
- return;
- }
- }
-
- // Not splitting. Enqueue dispatch entries for the event as is.
- enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
-}
-
-void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
- const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
- bool wasEmpty = connection->outboundQueue.isEmpty();
-
- // Enqueue dispatch entries for the requested modes.
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::FLAG_DISPATCH_AS_OUTSIDE);
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::FLAG_DISPATCH_AS_IS);
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);
- enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
- InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);
-
- // If the outbound queue was previously empty, start the dispatch cycle going.
- if (wasEmpty && !connection->outboundQueue.isEmpty()) {
- startDispatchCycleLocked(currentTime, connection);
- }
-}
-
-void InputDispatcher::enqueueDispatchEntryLocked(
- const sp<Connection>& connection, EventEntry* eventEntry, const InputTarget* inputTarget,
- int32_t dispatchMode) {
- int32_t inputTargetFlags = inputTarget->flags;
- if (!(inputTargetFlags & dispatchMode)) {
- return;
- }
- inputTargetFlags = (inputTargetFlags & ~InputTarget::FLAG_DISPATCH_MASK) | dispatchMode;
-
- // This is a new event.
- // Enqueue a new dispatch entry onto the outbound queue for this connection.
- DispatchEntry* dispatchEntry = new DispatchEntry(eventEntry, // increments ref
- inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset,
- inputTarget->scaleFactor);
-
- // Apply target flags and update the connection's input state.
- switch (eventEntry->type) {
- case EventEntry::TYPE_KEY: {
- KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
- dispatchEntry->resolvedAction = keyEntry->action;
- dispatchEntry->resolvedFlags = keyEntry->flags;
-
- if (!connection->inputState.trackKey(keyEntry,
- dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent key event",
- connection->getInputChannelName());
-#endif
- delete dispatchEntry;
- return; // skip the inconsistent event
- }
- break;
- }
-
- case EventEntry::TYPE_MOTION: {
- MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
- if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
- dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE;
- } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT) {
- dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT;
- } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER) {
- dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
- } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
- dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_CANCEL;
- } else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER) {
- dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_DOWN;
- } else {
- dispatchEntry->resolvedAction = motionEntry->action;
- }
- if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE
- && !connection->inputState.isHovering(
- motionEntry->deviceId, motionEntry->source, motionEntry->displayId)) {
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: filling in missing hover enter event",
- connection->getInputChannelName());
-#endif
- dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
- }
-
- dispatchEntry->resolvedFlags = motionEntry->flags;
- if (dispatchEntry->targetFlags & InputTarget::FLAG_WINDOW_IS_OBSCURED) {
- dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
- }
-
- if (!connection->inputState.trackMotion(motionEntry,
- dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent motion event",
- connection->getInputChannelName());
-#endif
- delete dispatchEntry;
- return; // skip the inconsistent event
- }
- break;
- }
- }
-
- // Remember that we are waiting for this dispatch to complete.
- if (dispatchEntry->hasForegroundTarget()) {
- incrementPendingForegroundDispatchesLocked(eventEntry);
- }
-
- // Enqueue the dispatch entry.
- connection->outboundQueue.enqueueAtTail(dispatchEntry);
- traceOutboundQueueLengthLocked(connection);
-}
-
-void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection) {
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ startDispatchCycle",
- connection->getInputChannelName());
-#endif
-
- while (connection->status == Connection::STATUS_NORMAL
- && !connection->outboundQueue.isEmpty()) {
- DispatchEntry* dispatchEntry = connection->outboundQueue.head;
- dispatchEntry->deliveryTime = currentTime;
-
- // Publish the event.
- status_t status;
- EventEntry* eventEntry = dispatchEntry->eventEntry;
- switch (eventEntry->type) {
- case EventEntry::TYPE_KEY: {
- KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
-
- // Publish the key event.
- status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq,
- keyEntry->deviceId, keyEntry->source,
- dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
- keyEntry->keyCode, keyEntry->scanCode,
- keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
- keyEntry->eventTime);
- break;
- }
-
- case EventEntry::TYPE_MOTION: {
- MotionEntry* motionEntry = static_cast<MotionEntry*>(eventEntry);
-
- PointerCoords scaledCoords[MAX_POINTERS];
- const PointerCoords* usingCoords = motionEntry->pointerCoords;
-
- // Set the X and Y offset depending on the input source.
- float xOffset, yOffset, scaleFactor;
- if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
- && !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {
- scaleFactor = dispatchEntry->scaleFactor;
- xOffset = dispatchEntry->xOffset * scaleFactor;
- yOffset = dispatchEntry->yOffset * scaleFactor;
- if (scaleFactor != 1.0f) {
- for (size_t i = 0; i < motionEntry->pointerCount; i++) {
- scaledCoords[i] = motionEntry->pointerCoords[i];
- scaledCoords[i].scale(scaleFactor);
- }
- usingCoords = scaledCoords;
- }
- } else {
- xOffset = 0.0f;
- yOffset = 0.0f;
- scaleFactor = 1.0f;
-
- // We don't want the dispatch target to know.
- if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {
- for (size_t i = 0; i < motionEntry->pointerCount; i++) {
- scaledCoords[i].clear();
- }
- usingCoords = scaledCoords;
- }
- }
-
- // Publish the motion event.
- status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,
- motionEntry->deviceId, motionEntry->source,
- dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
- motionEntry->edgeFlags, motionEntry->metaState, motionEntry->buttonState,
- xOffset, yOffset,
- motionEntry->xPrecision, motionEntry->yPrecision,
- motionEntry->downTime, motionEntry->eventTime,
- motionEntry->pointerCount, motionEntry->pointerProperties,
- usingCoords);
- break;
- }
-
- default:
- ALOG_ASSERT(false);
- return;
- }
-
- // Check the result.
- if (status) {
- if (status == WOULD_BLOCK) {
- if (connection->waitQueue.isEmpty()) {
- ALOGE("channel '%s' ~ Could not publish event because the pipe is full. "
- "This is unexpected because the wait queue is empty, so the pipe "
- "should be empty and we shouldn't have any problems writing an "
- "event to it, status=%d", connection->getInputChannelName(), status);
- abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
- } else {
- // Pipe is full and we are waiting for the app to finish process some events
- // before sending more events to it.
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ Could not publish event because the pipe is full, "
- "waiting for the application to catch up",
- connection->getInputChannelName());
-#endif
- connection->inputPublisherBlocked = true;
- }
- } else {
- ALOGE("channel '%s' ~ Could not publish event due to an unexpected error, "
- "status=%d", connection->getInputChannelName(), status);
- abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
- }
- return;
- }
-
- // Re-enqueue the event on the wait queue.
- connection->outboundQueue.dequeue(dispatchEntry);
- traceOutboundQueueLengthLocked(connection);
- connection->waitQueue.enqueueAtTail(dispatchEntry);
- traceWaitQueueLengthLocked(connection);
- }
-}
-
-void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection, uint32_t seq, bool handled) {
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ finishDispatchCycle - seq=%u, handled=%s",
- connection->getInputChannelName(), seq, toString(handled));
-#endif
-
- connection->inputPublisherBlocked = false;
-
- if (connection->status == Connection::STATUS_BROKEN
- || connection->status == Connection::STATUS_ZOMBIE) {
- return;
- }
-
- // Notify other system components and prepare to start the next dispatch cycle.
- onDispatchCycleFinishedLocked(currentTime, connection, seq, handled);
-}
-
-void InputDispatcher::abortBrokenDispatchCycleLocked(nsecs_t currentTime,
- const sp<Connection>& connection, bool notify) {
-#if DEBUG_DISPATCH_CYCLE
- ALOGD("channel '%s' ~ abortBrokenDispatchCycle - notify=%s",
- connection->getInputChannelName(), toString(notify));
-#endif
-
- // Clear the dispatch queues.
- drainDispatchQueueLocked(&connection->outboundQueue);
- traceOutboundQueueLengthLocked(connection);
- drainDispatchQueueLocked(&connection->waitQueue);
- traceWaitQueueLengthLocked(connection);
-
- // The connection appears to be unrecoverably broken.
- // Ignore already broken or zombie connections.
- if (connection->status == Connection::STATUS_NORMAL) {
- connection->status = Connection::STATUS_BROKEN;
-
- if (notify) {
- // Notify other system components.
- onDispatchCycleBrokenLocked(currentTime, connection);
- }
- }
-}
-
-void InputDispatcher::drainDispatchQueueLocked(Queue<DispatchEntry>* queue) {
- while (!queue->isEmpty()) {
- DispatchEntry* dispatchEntry = queue->dequeueAtHead();
- releaseDispatchEntryLocked(dispatchEntry);
- }
-}
-
-void InputDispatcher::releaseDispatchEntryLocked(DispatchEntry* dispatchEntry) {
- if (dispatchEntry->hasForegroundTarget()) {
- decrementPendingForegroundDispatchesLocked(dispatchEntry->eventEntry);
- }
- delete dispatchEntry;
-}
-
-int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
- InputDispatcher* d = static_cast<InputDispatcher*>(data);
-
- { // acquire lock
- AutoMutex _l(d->mLock);
-
- ssize_t connectionIndex = d->mConnectionsByFd.indexOfKey(fd);
- if (connectionIndex < 0) {
- ALOGE("Received spurious receive callback for unknown input channel. "
- "fd=%d, events=0x%x", fd, events);
- return 0; // remove the callback
- }
-
- bool notify;
- sp<Connection> connection = d->mConnectionsByFd.valueAt(connectionIndex);
- if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {
- if (!(events & ALOOPER_EVENT_INPUT)) {
- ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
- "events=0x%x", connection->getInputChannelName(), events);
- return 1;
- }
-
- nsecs_t currentTime = now();
- bool gotOne = false;
- status_t status;
- for (;;) {
- uint32_t seq;
- bool handled;
- status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled);
- if (status) {
- break;
- }
- d->finishDispatchCycleLocked(currentTime, connection, seq, handled);
- gotOne = true;
- }
- if (gotOne) {
- d->runCommandsLockedInterruptible();
- if (status == WOULD_BLOCK) {
- return 1;
- }
- }
-
- notify = status != DEAD_OBJECT || !connection->monitor;
- if (notify) {
- ALOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
- connection->getInputChannelName(), status);
- }
- } else {
- // Monitor channels are never explicitly unregistered.
- // We do it automatically when the remote endpoint is closed so don't warn
- // about them.
- notify = !connection->monitor;
- if (notify) {
- ALOGW("channel '%s' ~ Consumer closed input channel or an error occurred. "
- "events=0x%x", connection->getInputChannelName(), events);
- }
- }
-
- // Unregister the channel.
- d->unregisterInputChannelLocked(connection->inputChannel, notify);
- return 0; // remove the callback
- } // release lock
-}
-
-void InputDispatcher::synthesizeCancelationEventsForAllConnectionsLocked(
- const CancelationOptions& options) {
- for (size_t i = 0; i < mConnectionsByFd.size(); i++) {
- synthesizeCancelationEventsForConnectionLocked(
- mConnectionsByFd.valueAt(i), options);
- }
-}
-
-void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked(
- const sp<InputChannel>& channel, const CancelationOptions& options) {
- ssize_t index = getConnectionIndexLocked(channel);
- if (index >= 0) {
- synthesizeCancelationEventsForConnectionLocked(
- mConnectionsByFd.valueAt(index), options);
- }
-}
-
-void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
- const sp<Connection>& connection, const CancelationOptions& options) {
- if (connection->status == Connection::STATUS_BROKEN) {
- return;
- }
-
- nsecs_t currentTime = now();
-
- Vector<EventEntry*> cancelationEvents;
- connection->inputState.synthesizeCancelationEvents(currentTime,
- cancelationEvents, options);
-
- if (!cancelationEvents.isEmpty()) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("channel '%s' ~ Synthesized %d cancelation events to bring channel back in sync "
- "with reality: %s, mode=%d.",
- connection->getInputChannelName(), cancelationEvents.size(),
- options.reason, options.mode);
-#endif
- for (size_t i = 0; i < cancelationEvents.size(); i++) {
- EventEntry* cancelationEventEntry = cancelationEvents.itemAt(i);
- switch (cancelationEventEntry->type) {
- case EventEntry::TYPE_KEY:
- logOutboundKeyDetailsLocked("cancel - ",
- static_cast<KeyEntry*>(cancelationEventEntry));
- break;
- case EventEntry::TYPE_MOTION:
- logOutboundMotionDetailsLocked("cancel - ",
- static_cast<MotionEntry*>(cancelationEventEntry));
- break;
- }
-
- InputTarget target;
- sp<InputWindowHandle> windowHandle = getWindowHandleLocked(connection->inputChannel);
- if (windowHandle != NULL) {
- const InputWindowInfo* windowInfo = windowHandle->getInfo();
- target.xOffset = -windowInfo->frameLeft;
- target.yOffset = -windowInfo->frameTop;
- target.scaleFactor = windowInfo->scaleFactor;
- } else {
- target.xOffset = 0;
- target.yOffset = 0;
- target.scaleFactor = 1.0f;
- }
- target.inputChannel = connection->inputChannel;
- target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
-
- enqueueDispatchEntryLocked(connection, cancelationEventEntry, // increments ref
- &target, InputTarget::FLAG_DISPATCH_AS_IS);
-
- cancelationEventEntry->release();
- }
-
- startDispatchCycleLocked(currentTime, connection);
- }
-}
-
-InputDispatcher::MotionEntry*
-InputDispatcher::splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds) {
- ALOG_ASSERT(pointerIds.value != 0);
-
- uint32_t splitPointerIndexMap[MAX_POINTERS];
- PointerProperties splitPointerProperties[MAX_POINTERS];
- PointerCoords splitPointerCoords[MAX_POINTERS];
-
- uint32_t originalPointerCount = originalMotionEntry->pointerCount;
- uint32_t splitPointerCount = 0;
-
- for (uint32_t originalPointerIndex = 0; originalPointerIndex < originalPointerCount;
- originalPointerIndex++) {
- const PointerProperties& pointerProperties =
- originalMotionEntry->pointerProperties[originalPointerIndex];
- uint32_t pointerId = uint32_t(pointerProperties.id);
- if (pointerIds.hasBit(pointerId)) {
- splitPointerIndexMap[splitPointerCount] = originalPointerIndex;
- splitPointerProperties[splitPointerCount].copyFrom(pointerProperties);
- splitPointerCoords[splitPointerCount].copyFrom(
- originalMotionEntry->pointerCoords[originalPointerIndex]);
- splitPointerCount += 1;
- }
- }
-
- if (splitPointerCount != pointerIds.count()) {
- // This is bad. We are missing some of the pointers that we expected to deliver.
- // Most likely this indicates that we received an ACTION_MOVE events that has
- // different pointer ids than we expected based on the previous ACTION_DOWN
- // or ACTION_POINTER_DOWN events that caused us to decide to split the pointers
- // in this way.
- ALOGW("Dropping split motion event because the pointer count is %d but "
- "we expected there to be %d pointers. This probably means we received "
- "a broken sequence of pointer ids from the input device.",
- splitPointerCount, pointerIds.count());
- return NULL;
- }
-
- int32_t action = originalMotionEntry->action;
- int32_t maskedAction = action & AMOTION_EVENT_ACTION_MASK;
- if (maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
- || maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
- int32_t originalPointerIndex = getMotionEventActionPointerIndex(action);
- const PointerProperties& pointerProperties =
- originalMotionEntry->pointerProperties[originalPointerIndex];
- uint32_t pointerId = uint32_t(pointerProperties.id);
- if (pointerIds.hasBit(pointerId)) {
- if (pointerIds.count() == 1) {
- // The first/last pointer went down/up.
- action = maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
- ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
- } else {
- // A secondary pointer went down/up.
- uint32_t splitPointerIndex = 0;
- while (pointerId != uint32_t(splitPointerProperties[splitPointerIndex].id)) {
- splitPointerIndex += 1;
- }
- action = maskedAction | (splitPointerIndex
- << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
- }
- } else {
- // An unrelated pointer changed.
- action = AMOTION_EVENT_ACTION_MOVE;
- }
- }
-
- MotionEntry* splitMotionEntry = new MotionEntry(
- originalMotionEntry->eventTime,
- originalMotionEntry->deviceId,
- originalMotionEntry->source,
- originalMotionEntry->policyFlags,
- action,
- originalMotionEntry->flags,
- originalMotionEntry->metaState,
- originalMotionEntry->buttonState,
- originalMotionEntry->edgeFlags,
- originalMotionEntry->xPrecision,
- originalMotionEntry->yPrecision,
- originalMotionEntry->downTime,
- originalMotionEntry->displayId,
- splitPointerCount, splitPointerProperties, splitPointerCoords);
-
- if (originalMotionEntry->injectionState) {
- splitMotionEntry->injectionState = originalMotionEntry->injectionState;
- splitMotionEntry->injectionState->refCount += 1;
- }
-
- return splitMotionEntry;
-}
-
-void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
-#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("notifyConfigurationChanged - eventTime=%lld", args->eventTime);
-#endif
-
- bool needWake;
- { // acquire lock
- AutoMutex _l(mLock);
-
- ConfigurationChangedEntry* newEntry = new ConfigurationChangedEntry(args->eventTime);
- needWake = enqueueInboundEventLocked(newEntry);
- } // release lock
-
- if (needWake) {
- mLooper->wake();
- }
-}
-
-void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
-#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("notifyKey - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, "
- "flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
- args->eventTime, args->deviceId, args->source, args->policyFlags,
- args->action, args->flags, args->keyCode, args->scanCode,
- args->metaState, args->downTime);
-#endif
- if (!validateKeyEvent(args->action)) {
- return;
- }
-
- uint32_t policyFlags = args->policyFlags;
- int32_t flags = args->flags;
- int32_t metaState = args->metaState;
- if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
- policyFlags |= POLICY_FLAG_VIRTUAL;
- flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
- }
- if (policyFlags & POLICY_FLAG_ALT) {
- metaState |= AMETA_ALT_ON | AMETA_ALT_LEFT_ON;
- }
- if (policyFlags & POLICY_FLAG_ALT_GR) {
- metaState |= AMETA_ALT_ON | AMETA_ALT_RIGHT_ON;
- }
- if (policyFlags & POLICY_FLAG_SHIFT) {
- metaState |= AMETA_SHIFT_ON | AMETA_SHIFT_LEFT_ON;
- }
- if (policyFlags & POLICY_FLAG_CAPS_LOCK) {
- metaState |= AMETA_CAPS_LOCK_ON;
- }
- if (policyFlags & POLICY_FLAG_FUNCTION) {
- metaState |= AMETA_FUNCTION_ON;
- }
-
- policyFlags |= POLICY_FLAG_TRUSTED;
-
- KeyEvent event;
- event.initialize(args->deviceId, args->source, args->action,
- flags, args->keyCode, args->scanCode, metaState, 0,
- args->downTime, args->eventTime);
-
- mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
-
- if (policyFlags & POLICY_FLAG_WOKE_HERE) {
- flags |= AKEY_EVENT_FLAG_WOKE_HERE;
- }
-
- bool needWake;
- { // acquire lock
- mLock.lock();
-
- if (shouldSendKeyToInputFilterLocked(args)) {
- mLock.unlock();
-
- policyFlags |= POLICY_FLAG_FILTERED;
- if (!mPolicy->filterInputEvent(&event, policyFlags)) {
- return; // event was consumed by the filter
- }
-
- mLock.lock();
- }
-
- int32_t repeatCount = 0;
- KeyEntry* newEntry = new KeyEntry(args->eventTime,
- args->deviceId, args->source, policyFlags,
- args->action, flags, args->keyCode, args->scanCode,
- metaState, repeatCount, args->downTime);
-
- needWake = enqueueInboundEventLocked(newEntry);
- mLock.unlock();
- } // release lock
-
- if (needWake) {
- mLooper->wake();
- }
-}
-
-bool InputDispatcher::shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args) {
- return mInputFilterEnabled;
-}
-
-void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
-#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("notifyMotion - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, "
- "action=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, edgeFlags=0x%x, "
- "xPrecision=%f, yPrecision=%f, downTime=%lld",
- args->eventTime, args->deviceId, args->source, args->policyFlags,
- args->action, args->flags, args->metaState, args->buttonState,
- args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime);
- for (uint32_t i = 0; i < args->pointerCount; i++) {
- ALOGD(" Pointer %d: id=%d, toolType=%d, "
- "x=%f, y=%f, pressure=%f, size=%f, "
- "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
- "orientation=%f",
- i, args->pointerProperties[i].id,
- args->pointerProperties[i].toolType,
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
- args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
- }
-#endif
- if (!validateMotionEvent(args->action, args->pointerCount, args->pointerProperties)) {
- return;
- }
-
- uint32_t policyFlags = args->policyFlags;
- policyFlags |= POLICY_FLAG_TRUSTED;
- mPolicy->interceptMotionBeforeQueueing(args->eventTime, /*byref*/ policyFlags);
-
- bool needWake;
- { // acquire lock
- mLock.lock();
-
- if (shouldSendMotionToInputFilterLocked(args)) {
- mLock.unlock();
-
- MotionEvent event;
- event.initialize(args->deviceId, args->source, args->action, args->flags,
- args->edgeFlags, args->metaState, args->buttonState, 0, 0,
- args->xPrecision, args->yPrecision,
- args->downTime, args->eventTime,
- args->pointerCount, args->pointerProperties, args->pointerCoords);
-
- policyFlags |= POLICY_FLAG_FILTERED;
- if (!mPolicy->filterInputEvent(&event, policyFlags)) {
- return; // event was consumed by the filter
- }
-
- mLock.lock();
- }
-
- // Just enqueue a new motion event.
- MotionEntry* newEntry = new MotionEntry(args->eventTime,
- args->deviceId, args->source, policyFlags,
- args->action, args->flags, args->metaState, args->buttonState,
- args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
- args->displayId,
- args->pointerCount, args->pointerProperties, args->pointerCoords);
-
- needWake = enqueueInboundEventLocked(newEntry);
- mLock.unlock();
- } // release lock
-
- if (needWake) {
- mLooper->wake();
- }
-}
-
-bool InputDispatcher::shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) {
- // TODO: support sending secondary display events to input filter
- return mInputFilterEnabled && isMainDisplay(args->displayId);
-}
-
-void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) {
-#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("notifySwitch - eventTime=%lld, policyFlags=0x%x, switchValues=0x%08x, switchMask=0x%08x",
- args->eventTime, args->policyFlags,
- args->switchValues, args->switchMask);
-#endif
-
- uint32_t policyFlags = args->policyFlags;
- policyFlags |= POLICY_FLAG_TRUSTED;
- mPolicy->notifySwitch(args->eventTime,
- args->switchValues, args->switchMask, policyFlags);
-}
-
-void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
-#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("notifyDeviceReset - eventTime=%lld, deviceId=%d",
- args->eventTime, args->deviceId);
-#endif
-
- bool needWake;
- { // acquire lock
- AutoMutex _l(mLock);
-
- DeviceResetEntry* newEntry = new DeviceResetEntry(args->eventTime, args->deviceId);
- needWake = enqueueInboundEventLocked(newEntry);
- } // release lock
-
- if (needWake) {
- mLooper->wake();
- }
-}
-
-int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
- int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
- uint32_t policyFlags) {
-#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
- "syncMode=%d, timeoutMillis=%d, policyFlags=0x%08x",
- event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis, policyFlags);
-#endif
-
- nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
-
- policyFlags |= POLICY_FLAG_INJECTED;
- if (hasInjectionPermission(injectorPid, injectorUid)) {
- policyFlags |= POLICY_FLAG_TRUSTED;
- }
-
- EventEntry* firstInjectedEntry;
- EventEntry* lastInjectedEntry;
- switch (event->getType()) {
- case AINPUT_EVENT_TYPE_KEY: {
- const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
- int32_t action = keyEvent->getAction();
- if (! validateKeyEvent(action)) {
- return INPUT_EVENT_INJECTION_FAILED;
- }
-
- int32_t flags = keyEvent->getFlags();
- if (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY) {
- policyFlags |= POLICY_FLAG_VIRTUAL;
- }
-
- if (!(policyFlags & POLICY_FLAG_FILTERED)) {
- mPolicy->interceptKeyBeforeQueueing(keyEvent, /*byref*/ policyFlags);
- }
-
- if (policyFlags & POLICY_FLAG_WOKE_HERE) {
- flags |= AKEY_EVENT_FLAG_WOKE_HERE;
- }
-
- mLock.lock();
- firstInjectedEntry = new KeyEntry(keyEvent->getEventTime(),
- keyEvent->getDeviceId(), keyEvent->getSource(),
- policyFlags, action, flags,
- keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
- keyEvent->getRepeatCount(), keyEvent->getDownTime());
- lastInjectedEntry = firstInjectedEntry;
- break;
- }
-
- case AINPUT_EVENT_TYPE_MOTION: {
- const MotionEvent* motionEvent = static_cast<const MotionEvent*>(event);
- int32_t displayId = ADISPLAY_ID_DEFAULT;
- int32_t action = motionEvent->getAction();
- size_t pointerCount = motionEvent->getPointerCount();
- const PointerProperties* pointerProperties = motionEvent->getPointerProperties();
- if (! validateMotionEvent(action, pointerCount, pointerProperties)) {
- return INPUT_EVENT_INJECTION_FAILED;
- }
-
- if (!(policyFlags & POLICY_FLAG_FILTERED)) {
- nsecs_t eventTime = motionEvent->getEventTime();
- mPolicy->interceptMotionBeforeQueueing(eventTime, /*byref*/ policyFlags);
- }
-
- mLock.lock();
- const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
- const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
- firstInjectedEntry = new MotionEntry(*sampleEventTimes,
- motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
- action, motionEvent->getFlags(),
- motionEvent->getMetaState(), motionEvent->getButtonState(),
- motionEvent->getEdgeFlags(),
- motionEvent->getXPrecision(), motionEvent->getYPrecision(),
- motionEvent->getDownTime(), displayId,
- uint32_t(pointerCount), pointerProperties, samplePointerCoords);
- lastInjectedEntry = firstInjectedEntry;
- for (size_t i = motionEvent->getHistorySize(); i > 0; i--) {
- sampleEventTimes += 1;
- samplePointerCoords += pointerCount;
- MotionEntry* nextInjectedEntry = new MotionEntry(*sampleEventTimes,
- motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
- action, motionEvent->getFlags(),
- motionEvent->getMetaState(), motionEvent->getButtonState(),
- motionEvent->getEdgeFlags(),
- motionEvent->getXPrecision(), motionEvent->getYPrecision(),
- motionEvent->getDownTime(), displayId,
- uint32_t(pointerCount), pointerProperties, samplePointerCoords);
- lastInjectedEntry->next = nextInjectedEntry;
- lastInjectedEntry = nextInjectedEntry;
- }
- break;
- }
-
- default:
- ALOGW("Cannot inject event of type %d", event->getType());
- return INPUT_EVENT_INJECTION_FAILED;
- }
-
- InjectionState* injectionState = new InjectionState(injectorPid, injectorUid);
- if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
- injectionState->injectionIsAsync = true;
- }
-
- injectionState->refCount += 1;
- lastInjectedEntry->injectionState = injectionState;
-
- bool needWake = false;
- for (EventEntry* entry = firstInjectedEntry; entry != NULL; ) {
- EventEntry* nextEntry = entry->next;
- needWake |= enqueueInboundEventLocked(entry);
- entry = nextEntry;
- }
-
- mLock.unlock();
-
- if (needWake) {
- mLooper->wake();
- }
-
- int32_t injectionResult;
- { // acquire lock
- AutoMutex _l(mLock);
-
- if (syncMode == INPUT_EVENT_INJECTION_SYNC_NONE) {
- injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
- } else {
- for (;;) {
- injectionResult = injectionState->injectionResult;
- if (injectionResult != INPUT_EVENT_INJECTION_PENDING) {
- break;
- }
-
- nsecs_t remainingTimeout = endTime - now();
- if (remainingTimeout <= 0) {
-#if DEBUG_INJECTION
- ALOGD("injectInputEvent - Timed out waiting for injection result "
- "to become available.");
-#endif
- injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
- break;
- }
-
- mInjectionResultAvailableCondition.waitRelative(mLock, remainingTimeout);
- }
-
- if (injectionResult == INPUT_EVENT_INJECTION_SUCCEEDED
- && syncMode == INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED) {
- while (injectionState->pendingForegroundDispatches != 0) {
-#if DEBUG_INJECTION
- ALOGD("injectInputEvent - Waiting for %d pending foreground dispatches.",
- injectionState->pendingForegroundDispatches);
-#endif
- nsecs_t remainingTimeout = endTime - now();
- if (remainingTimeout <= 0) {
-#if DEBUG_INJECTION
- ALOGD("injectInputEvent - Timed out waiting for pending foreground "
- "dispatches to finish.");
-#endif
- injectionResult = INPUT_EVENT_INJECTION_TIMED_OUT;
- break;
- }
-
- mInjectionSyncFinishedCondition.waitRelative(mLock, remainingTimeout);
- }
- }
- }
-
- injectionState->release();
- } // release lock
-
-#if DEBUG_INJECTION
- ALOGD("injectInputEvent - Finished with result %d. "
- "injectorPid=%d, injectorUid=%d",
- injectionResult, injectorPid, injectorUid);
-#endif
-
- return injectionResult;
-}
-
-bool InputDispatcher::hasInjectionPermission(int32_t injectorPid, int32_t injectorUid) {
- return injectorUid == 0
- || mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid);
-}
-
-void InputDispatcher::setInjectionResultLocked(EventEntry* entry, int32_t injectionResult) {
- InjectionState* injectionState = entry->injectionState;
- if (injectionState) {
-#if DEBUG_INJECTION
- ALOGD("Setting input event injection result to %d. "
- "injectorPid=%d, injectorUid=%d",
- injectionResult, injectionState->injectorPid, injectionState->injectorUid);
-#endif
-
- if (injectionState->injectionIsAsync
- && !(entry->policyFlags & POLICY_FLAG_FILTERED)) {
- // Log the outcome since the injector did not wait for the injection result.
- switch (injectionResult) {
- case INPUT_EVENT_INJECTION_SUCCEEDED:
- ALOGV("Asynchronous input event injection succeeded.");
- break;
- case INPUT_EVENT_INJECTION_FAILED:
- ALOGW("Asynchronous input event injection failed.");
- break;
- case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
- ALOGW("Asynchronous input event injection permission denied.");
- break;
- case INPUT_EVENT_INJECTION_TIMED_OUT:
- ALOGW("Asynchronous input event injection timed out.");
- break;
- }
- }
-
- injectionState->injectionResult = injectionResult;
- mInjectionResultAvailableCondition.broadcast();
- }
-}
-
-void InputDispatcher::incrementPendingForegroundDispatchesLocked(EventEntry* entry) {
- InjectionState* injectionState = entry->injectionState;
- if (injectionState) {
- injectionState->pendingForegroundDispatches += 1;
- }
-}
-
-void InputDispatcher::decrementPendingForegroundDispatchesLocked(EventEntry* entry) {
- InjectionState* injectionState = entry->injectionState;
- if (injectionState) {
- injectionState->pendingForegroundDispatches -= 1;
-
- if (injectionState->pendingForegroundDispatches == 0) {
- mInjectionSyncFinishedCondition.broadcast();
- }
- }
-}
-
-sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(
- const sp<InputChannel>& inputChannel) const {
- size_t numWindows = mWindowHandles.size();
- for (size_t i = 0; i < numWindows; i++) {
- const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
- if (windowHandle->getInputChannel() == inputChannel) {
- return windowHandle;
- }
- }
- return NULL;
-}
-
-bool InputDispatcher::hasWindowHandleLocked(
- const sp<InputWindowHandle>& windowHandle) const {
- size_t numWindows = mWindowHandles.size();
- for (size_t i = 0; i < numWindows; i++) {
- if (mWindowHandles.itemAt(i) == windowHandle) {
- return true;
- }
- }
- return false;
-}
-
-void InputDispatcher::setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) {
-#if DEBUG_FOCUS
- ALOGD("setInputWindows");
-#endif
- { // acquire lock
- AutoMutex _l(mLock);
-
- Vector<sp<InputWindowHandle> > oldWindowHandles = mWindowHandles;
- mWindowHandles = inputWindowHandles;
-
- sp<InputWindowHandle> newFocusedWindowHandle;
- bool foundHoveredWindow = false;
- for (size_t i = 0; i < mWindowHandles.size(); i++) {
- const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
- if (!windowHandle->updateInfo() || windowHandle->getInputChannel() == NULL) {
- mWindowHandles.removeAt(i--);
- continue;
- }
- if (windowHandle->getInfo()->hasFocus) {
- newFocusedWindowHandle = windowHandle;
- }
- if (windowHandle == mLastHoverWindowHandle) {
- foundHoveredWindow = true;
- }
- }
-
- if (!foundHoveredWindow) {
- mLastHoverWindowHandle = NULL;
- }
-
- if (mFocusedWindowHandle != newFocusedWindowHandle) {
- if (mFocusedWindowHandle != NULL) {
-#if DEBUG_FOCUS
- ALOGD("Focus left window: %s",
- mFocusedWindowHandle->getName().string());
-#endif
- sp<InputChannel> focusedInputChannel = mFocusedWindowHandle->getInputChannel();
- if (focusedInputChannel != NULL) {
- CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS,
- "focus left window");
- synthesizeCancelationEventsForInputChannelLocked(
- focusedInputChannel, options);
- }
- }
- if (newFocusedWindowHandle != NULL) {
-#if DEBUG_FOCUS
- ALOGD("Focus entered window: %s",
- newFocusedWindowHandle->getName().string());
-#endif
- }
- mFocusedWindowHandle = newFocusedWindowHandle;
- }
-
- for (size_t i = 0; i < mTouchState.windows.size(); i++) {
- TouchedWindow& touchedWindow = mTouchState.windows.editItemAt(i);
- if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
-#if DEBUG_FOCUS
- ALOGD("Touched window was removed: %s",
- touchedWindow.windowHandle->getName().string());
-#endif
- sp<InputChannel> touchedInputChannel =
- touchedWindow.windowHandle->getInputChannel();
- if (touchedInputChannel != NULL) {
- CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
- "touched window was removed");
- synthesizeCancelationEventsForInputChannelLocked(
- touchedInputChannel, options);
- }
- mTouchState.windows.removeAt(i--);
- }
- }
-
- // Release information for windows that are no longer present.
- // This ensures that unused input channels are released promptly.
- // Otherwise, they might stick around until the window handle is destroyed
- // which might not happen until the next GC.
- for (size_t i = 0; i < oldWindowHandles.size(); i++) {
- const sp<InputWindowHandle>& oldWindowHandle = oldWindowHandles.itemAt(i);
- if (!hasWindowHandleLocked(oldWindowHandle)) {
-#if DEBUG_FOCUS
- ALOGD("Window went away: %s", oldWindowHandle->getName().string());
-#endif
- oldWindowHandle->releaseInfo();
- }
- }
- } // release lock
-
- // Wake up poll loop since it may need to make new input dispatching choices.
- mLooper->wake();
-}
-
-void InputDispatcher::setFocusedApplication(
- const sp<InputApplicationHandle>& inputApplicationHandle) {
-#if DEBUG_FOCUS
- ALOGD("setFocusedApplication");
-#endif
- { // acquire lock
- AutoMutex _l(mLock);
-
- if (inputApplicationHandle != NULL && inputApplicationHandle->updateInfo()) {
- if (mFocusedApplicationHandle != inputApplicationHandle) {
- if (mFocusedApplicationHandle != NULL) {
- resetANRTimeoutsLocked();
- mFocusedApplicationHandle->releaseInfo();
- }
- mFocusedApplicationHandle = inputApplicationHandle;
- }
- } else if (mFocusedApplicationHandle != NULL) {
- resetANRTimeoutsLocked();
- mFocusedApplicationHandle->releaseInfo();
- mFocusedApplicationHandle.clear();
- }
-
-#if DEBUG_FOCUS
- //logDispatchStateLocked();
-#endif
- } // release lock
-
- // Wake up poll loop since it may need to make new input dispatching choices.
- mLooper->wake();
-}
-
-void InputDispatcher::setInputDispatchMode(bool enabled, bool frozen) {
-#if DEBUG_FOCUS
- ALOGD("setInputDispatchMode: enabled=%d, frozen=%d", enabled, frozen);
-#endif
-
- bool changed;
- { // acquire lock
- AutoMutex _l(mLock);
-
- if (mDispatchEnabled != enabled || mDispatchFrozen != frozen) {
- if (mDispatchFrozen && !frozen) {
- resetANRTimeoutsLocked();
- }
-
- if (mDispatchEnabled && !enabled) {
- resetAndDropEverythingLocked("dispatcher is being disabled");
- }
-
- mDispatchEnabled = enabled;
- mDispatchFrozen = frozen;
- changed = true;
- } else {
- changed = false;
- }
-
-#if DEBUG_FOCUS
- //logDispatchStateLocked();
-#endif
- } // release lock
-
- if (changed) {
- // Wake up poll loop since it may need to make new input dispatching choices.
- mLooper->wake();
- }
-}
-
-void InputDispatcher::setInputFilterEnabled(bool enabled) {
-#if DEBUG_FOCUS
- ALOGD("setInputFilterEnabled: enabled=%d", enabled);
-#endif
-
- { // acquire lock
- AutoMutex _l(mLock);
-
- if (mInputFilterEnabled == enabled) {
- return;
- }
-
- mInputFilterEnabled = enabled;
- resetAndDropEverythingLocked("input filter is being enabled or disabled");
- } // release lock
-
- // Wake up poll loop since there might be work to do to drop everything.
- mLooper->wake();
-}
-
-bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel,
- const sp<InputChannel>& toChannel) {
-#if DEBUG_FOCUS
- ALOGD("transferTouchFocus: fromChannel=%s, toChannel=%s",
- fromChannel->getName().string(), toChannel->getName().string());
-#endif
- { // acquire lock
- AutoMutex _l(mLock);
-
- sp<InputWindowHandle> fromWindowHandle = getWindowHandleLocked(fromChannel);
- sp<InputWindowHandle> toWindowHandle = getWindowHandleLocked(toChannel);
- if (fromWindowHandle == NULL || toWindowHandle == NULL) {
-#if DEBUG_FOCUS
- ALOGD("Cannot transfer focus because from or to window not found.");
-#endif
- return false;
- }
- if (fromWindowHandle == toWindowHandle) {
-#if DEBUG_FOCUS
- ALOGD("Trivial transfer to same window.");
-#endif
- return true;
- }
- if (fromWindowHandle->getInfo()->displayId != toWindowHandle->getInfo()->displayId) {
-#if DEBUG_FOCUS
- ALOGD("Cannot transfer focus because windows are on different displays.");
-#endif
- return false;
- }
-
- bool found = false;
- for (size_t i = 0; i < mTouchState.windows.size(); i++) {
- const TouchedWindow& touchedWindow = mTouchState.windows[i];
- if (touchedWindow.windowHandle == fromWindowHandle) {
- int32_t oldTargetFlags = touchedWindow.targetFlags;
- BitSet32 pointerIds = touchedWindow.pointerIds;
-
- mTouchState.windows.removeAt(i);
-
- int32_t newTargetFlags = oldTargetFlags
- & (InputTarget::FLAG_FOREGROUND
- | InputTarget::FLAG_SPLIT | InputTarget::FLAG_DISPATCH_AS_IS);
- mTouchState.addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds);
-
- found = true;
- break;
- }
- }
-
- if (! found) {
-#if DEBUG_FOCUS
- ALOGD("Focus transfer failed because from window did not have focus.");
-#endif
- return false;
- }
-
- ssize_t fromConnectionIndex = getConnectionIndexLocked(fromChannel);
- ssize_t toConnectionIndex = getConnectionIndexLocked(toChannel);
- if (fromConnectionIndex >= 0 && toConnectionIndex >= 0) {
- sp<Connection> fromConnection = mConnectionsByFd.valueAt(fromConnectionIndex);
- sp<Connection> toConnection = mConnectionsByFd.valueAt(toConnectionIndex);
-
- fromConnection->inputState.copyPointerStateTo(toConnection->inputState);
- CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
- "transferring touch focus from this window to another window");
- synthesizeCancelationEventsForConnectionLocked(fromConnection, options);
- }
-
-#if DEBUG_FOCUS
- logDispatchStateLocked();
-#endif
- } // release lock
-
- // Wake up poll loop since it may need to make new input dispatching choices.
- mLooper->wake();
- return true;
-}
-
-void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
-#if DEBUG_FOCUS
- ALOGD("Resetting and dropping all events (%s).", reason);
-#endif
-
- CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS, reason);
- synthesizeCancelationEventsForAllConnectionsLocked(options);
-
- resetKeyRepeatLocked();
- releasePendingEventLocked();
- drainInboundQueueLocked();
- resetANRTimeoutsLocked();
-
- mTouchState.reset();
- mLastHoverWindowHandle.clear();
-}
-
-void InputDispatcher::logDispatchStateLocked() {
- String8 dump;
- dumpDispatchStateLocked(dump);
-
- char* text = dump.lockBuffer(dump.size());
- char* start = text;
- while (*start != '\0') {
- char* end = strchr(start, '\n');
- if (*end == '\n') {
- *(end++) = '\0';
- }
- ALOGD("%s", start);
- start = end;
- }
-}
-
-void InputDispatcher::dumpDispatchStateLocked(String8& dump) {
- dump.appendFormat(INDENT "DispatchEnabled: %d\n", mDispatchEnabled);
- dump.appendFormat(INDENT "DispatchFrozen: %d\n", mDispatchFrozen);
-
- if (mFocusedApplicationHandle != NULL) {
- dump.appendFormat(INDENT "FocusedApplication: name='%s', dispatchingTimeout=%0.3fms\n",
- mFocusedApplicationHandle->getName().string(),
- mFocusedApplicationHandle->getDispatchingTimeout(
- DEFAULT_INPUT_DISPATCHING_TIMEOUT) / 1000000.0);
- } else {
- dump.append(INDENT "FocusedApplication: <null>\n");
- }
- dump.appendFormat(INDENT "FocusedWindow: name='%s'\n",
- mFocusedWindowHandle != NULL ? mFocusedWindowHandle->getName().string() : "<null>");
-
- dump.appendFormat(INDENT "TouchDown: %s\n", toString(mTouchState.down));
- dump.appendFormat(INDENT "TouchSplit: %s\n", toString(mTouchState.split));
- dump.appendFormat(INDENT "TouchDeviceId: %d\n", mTouchState.deviceId);
- dump.appendFormat(INDENT "TouchSource: 0x%08x\n", mTouchState.source);
- dump.appendFormat(INDENT "TouchDisplayId: %d\n", mTouchState.displayId);
- if (!mTouchState.windows.isEmpty()) {
- dump.append(INDENT "TouchedWindows:\n");
- for (size_t i = 0; i < mTouchState.windows.size(); i++) {
- const TouchedWindow& touchedWindow = mTouchState.windows[i];
- dump.appendFormat(INDENT2 "%d: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
- i, touchedWindow.windowHandle->getName().string(),
- touchedWindow.pointerIds.value,
- touchedWindow.targetFlags);
- }
- } else {
- dump.append(INDENT "TouchedWindows: <none>\n");
- }
-
- if (!mWindowHandles.isEmpty()) {
- dump.append(INDENT "Windows:\n");
- for (size_t i = 0; i < mWindowHandles.size(); i++) {
- const sp<InputWindowHandle>& windowHandle = mWindowHandles.itemAt(i);
- const InputWindowInfo* windowInfo = windowHandle->getInfo();
-
- dump.appendFormat(INDENT2 "%d: name='%s', displayId=%d, "
- "paused=%s, hasFocus=%s, hasWallpaper=%s, "
- "visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
- "frame=[%d,%d][%d,%d], scale=%f, "
- "touchableRegion=",
- i, windowInfo->name.string(), windowInfo->displayId,
- toString(windowInfo->paused),
- toString(windowInfo->hasFocus),
- toString(windowInfo->hasWallpaper),
- toString(windowInfo->visible),
- toString(windowInfo->canReceiveKeys),
- windowInfo->layoutParamsFlags, windowInfo->layoutParamsType,
- windowInfo->layer,
- windowInfo->frameLeft, windowInfo->frameTop,
- windowInfo->frameRight, windowInfo->frameBottom,
- windowInfo->scaleFactor);
- dumpRegion(dump, windowInfo->touchableRegion);
- dump.appendFormat(", inputFeatures=0x%08x", windowInfo->inputFeatures);
- dump.appendFormat(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
- windowInfo->ownerPid, windowInfo->ownerUid,
- windowInfo->dispatchingTimeout / 1000000.0);
- }
- } else {
- dump.append(INDENT "Windows: <none>\n");
- }
-
- if (!mMonitoringChannels.isEmpty()) {
- dump.append(INDENT "MonitoringChannels:\n");
- for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
- const sp<InputChannel>& channel = mMonitoringChannels[i];
- dump.appendFormat(INDENT2 "%d: '%s'\n", i, channel->getName().string());
- }
- } else {
- dump.append(INDENT "MonitoringChannels: <none>\n");
- }
-
- nsecs_t currentTime = now();
-
- // Dump recently dispatched or dropped events from oldest to newest.
- if (!mRecentQueue.isEmpty()) {
- dump.appendFormat(INDENT "RecentQueue: length=%u\n", mRecentQueue.count());
- for (EventEntry* entry = mRecentQueue.head; entry; entry = entry->next) {
- dump.append(INDENT2);
- entry->appendDescription(dump);
- dump.appendFormat(", age=%0.1fms\n",
- (currentTime - entry->eventTime) * 0.000001f);
- }
- } else {
- dump.append(INDENT "RecentQueue: <empty>\n");
- }
-
- // Dump event currently being dispatched.
- if (mPendingEvent) {
- dump.append(INDENT "PendingEvent:\n");
- dump.append(INDENT2);
- mPendingEvent->appendDescription(dump);
- dump.appendFormat(", age=%0.1fms\n",
- (currentTime - mPendingEvent->eventTime) * 0.000001f);
- } else {
- dump.append(INDENT "PendingEvent: <none>\n");
- }
-
- // Dump inbound events from oldest to newest.
- if (!mInboundQueue.isEmpty()) {
- dump.appendFormat(INDENT "InboundQueue: length=%u\n", mInboundQueue.count());
- for (EventEntry* entry = mInboundQueue.head; entry; entry = entry->next) {
- dump.append(INDENT2);
- entry->appendDescription(dump);
- dump.appendFormat(", age=%0.1fms\n",
- (currentTime - entry->eventTime) * 0.000001f);
- }
- } else {
- dump.append(INDENT "InboundQueue: <empty>\n");
- }
-
- if (!mConnectionsByFd.isEmpty()) {
- dump.append(INDENT "Connections:\n");
- for (size_t i = 0; i < mConnectionsByFd.size(); i++) {
- const sp<Connection>& connection = mConnectionsByFd.valueAt(i);
- dump.appendFormat(INDENT2 "%d: channelName='%s', windowName='%s', "
- "status=%s, monitor=%s, inputPublisherBlocked=%s\n",
- i, connection->getInputChannelName(), connection->getWindowName(),
- connection->getStatusLabel(), toString(connection->monitor),
- toString(connection->inputPublisherBlocked));
-
- if (!connection->outboundQueue.isEmpty()) {
- dump.appendFormat(INDENT3 "OutboundQueue: length=%u\n",
- connection->outboundQueue.count());
- for (DispatchEntry* entry = connection->outboundQueue.head; entry;
- entry = entry->next) {
- dump.append(INDENT4);
- entry->eventEntry->appendDescription(dump);
- dump.appendFormat(", targetFlags=0x%08x, resolvedAction=%d, age=%0.1fms\n",
- entry->targetFlags, entry->resolvedAction,
- (currentTime - entry->eventEntry->eventTime) * 0.000001f);
- }
- } else {
- dump.append(INDENT3 "OutboundQueue: <empty>\n");
- }
-
- if (!connection->waitQueue.isEmpty()) {
- dump.appendFormat(INDENT3 "WaitQueue: length=%u\n",
- connection->waitQueue.count());
- for (DispatchEntry* entry = connection->waitQueue.head; entry;
- entry = entry->next) {
- dump.append(INDENT4);
- entry->eventEntry->appendDescription(dump);
- dump.appendFormat(", targetFlags=0x%08x, resolvedAction=%d, "
- "age=%0.1fms, wait=%0.1fms\n",
- entry->targetFlags, entry->resolvedAction,
- (currentTime - entry->eventEntry->eventTime) * 0.000001f,
- (currentTime - entry->deliveryTime) * 0.000001f);
- }
- } else {
- dump.append(INDENT3 "WaitQueue: <empty>\n");
- }
- }
- } else {
- dump.append(INDENT "Connections: <none>\n");
- }
-
- if (isAppSwitchPendingLocked()) {
- dump.appendFormat(INDENT "AppSwitch: pending, due in %0.1fms\n",
- (mAppSwitchDueTime - now()) / 1000000.0);
- } else {
- dump.append(INDENT "AppSwitch: not pending\n");
- }
-
- dump.append(INDENT "Configuration:\n");
- dump.appendFormat(INDENT2 "KeyRepeatDelay: %0.1fms\n",
- mConfig.keyRepeatDelay * 0.000001f);
- dump.appendFormat(INDENT2 "KeyRepeatTimeout: %0.1fms\n",
- mConfig.keyRepeatTimeout * 0.000001f);
-}
-
-status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
- const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
-#if DEBUG_REGISTRATION
- ALOGD("channel '%s' ~ registerInputChannel - monitor=%s", inputChannel->getName().string(),
- toString(monitor));
-#endif
-
- { // acquire lock
- AutoMutex _l(mLock);
-
- if (getConnectionIndexLocked(inputChannel) >= 0) {
- ALOGW("Attempted to register already registered input channel '%s'",
- inputChannel->getName().string());
- return BAD_VALUE;
- }
-
- sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);
-
- int fd = inputChannel->getFd();
- mConnectionsByFd.add(fd, connection);
-
- if (monitor) {
- mMonitoringChannels.push(inputChannel);
- }
-
- mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
- } // release lock
-
- // Wake the looper because some connections have changed.
- mLooper->wake();
- return OK;
-}
-
-status_t InputDispatcher::unregisterInputChannel(const sp<InputChannel>& inputChannel) {
-#if DEBUG_REGISTRATION
- ALOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().string());
-#endif
-
- { // acquire lock
- AutoMutex _l(mLock);
-
- status_t status = unregisterInputChannelLocked(inputChannel, false /*notify*/);
- if (status) {
- return status;
- }
- } // release lock
-
- // Wake the poll loop because removing the connection may have changed the current
- // synchronization state.
- mLooper->wake();
- return OK;
-}
-
-status_t InputDispatcher::unregisterInputChannelLocked(const sp<InputChannel>& inputChannel,
- bool notify) {
- ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);
- if (connectionIndex < 0) {
- ALOGW("Attempted to unregister already unregistered input channel '%s'",
- inputChannel->getName().string());
- return BAD_VALUE;
- }
-
- sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
- mConnectionsByFd.removeItemsAt(connectionIndex);
-
- if (connection->monitor) {
- removeMonitorChannelLocked(inputChannel);
- }
-
- mLooper->removeFd(inputChannel->getFd());
-
- nsecs_t currentTime = now();
- abortBrokenDispatchCycleLocked(currentTime, connection, notify);
-
- connection->status = Connection::STATUS_ZOMBIE;
- return OK;
-}
-
-void InputDispatcher::removeMonitorChannelLocked(const sp<InputChannel>& inputChannel) {
- for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
- if (mMonitoringChannels[i] == inputChannel) {
- mMonitoringChannels.removeAt(i);
- break;
- }
- }
-}
-
-ssize_t InputDispatcher::getConnectionIndexLocked(const sp<InputChannel>& inputChannel) {
- ssize_t connectionIndex = mConnectionsByFd.indexOfKey(inputChannel->getFd());
- if (connectionIndex >= 0) {
- sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
- if (connection->inputChannel.get() == inputChannel.get()) {
- return connectionIndex;
- }
- }
-
- return -1;
-}
-
-void InputDispatcher::onDispatchCycleFinishedLocked(
- nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled) {
- CommandEntry* commandEntry = postCommandLocked(
- & InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
- commandEntry->connection = connection;
- commandEntry->eventTime = currentTime;
- commandEntry->seq = seq;
- commandEntry->handled = handled;
-}
-
-void InputDispatcher::onDispatchCycleBrokenLocked(
- nsecs_t currentTime, const sp<Connection>& connection) {
- ALOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
- connection->getInputChannelName());
-
- CommandEntry* commandEntry = postCommandLocked(
- & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
- commandEntry->connection = connection;
-}
-
-void InputDispatcher::onANRLocked(
- nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
- const sp<InputWindowHandle>& windowHandle,
- nsecs_t eventTime, nsecs_t waitStartTime, const char* reason) {
- float dispatchLatency = (currentTime - eventTime) * 0.000001f;
- float waitDuration = (currentTime - waitStartTime) * 0.000001f;
- ALOGI("Application is not responding: %s. "
- "It has been %0.1fms since event, %0.1fms since wait started. Reason: %s",
- getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(),
- dispatchLatency, waitDuration, reason);
-
- // Capture a record of the InputDispatcher state at the time of the ANR.
- time_t t = time(NULL);
- struct tm tm;
- localtime_r(&t, &tm);
- char timestr[64];
- strftime(timestr, sizeof(timestr), "%F %T", &tm);
- mLastANRState.clear();
- mLastANRState.append(INDENT "ANR:\n");
- mLastANRState.appendFormat(INDENT2 "Time: %s\n", timestr);
- mLastANRState.appendFormat(INDENT2 "Window: %s\n",
- getApplicationWindowLabelLocked(applicationHandle, windowHandle).string());
- mLastANRState.appendFormat(INDENT2 "DispatchLatency: %0.1fms\n", dispatchLatency);
- mLastANRState.appendFormat(INDENT2 "WaitDuration: %0.1fms\n", waitDuration);
- mLastANRState.appendFormat(INDENT2 "Reason: %s\n", reason);
- dumpDispatchStateLocked(mLastANRState);
-
- CommandEntry* commandEntry = postCommandLocked(
- & InputDispatcher::doNotifyANRLockedInterruptible);
- commandEntry->inputApplicationHandle = applicationHandle;
- commandEntry->inputWindowHandle = windowHandle;
- commandEntry->reason = reason;
-}
-
-void InputDispatcher::doNotifyConfigurationChangedInterruptible(
- CommandEntry* commandEntry) {
- mLock.unlock();
-
- mPolicy->notifyConfigurationChanged(commandEntry->eventTime);
-
- mLock.lock();
-}
-
-void InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible(
- CommandEntry* commandEntry) {
- sp<Connection> connection = commandEntry->connection;
-
- if (connection->status != Connection::STATUS_ZOMBIE) {
- mLock.unlock();
-
- mPolicy->notifyInputChannelBroken(connection->inputWindowHandle);
-
- mLock.lock();
- }
-}
-
-void InputDispatcher::doNotifyANRLockedInterruptible(
- CommandEntry* commandEntry) {
- mLock.unlock();
-
- nsecs_t newTimeout = mPolicy->notifyANR(
- commandEntry->inputApplicationHandle, commandEntry->inputWindowHandle,
- commandEntry->reason);
-
- mLock.lock();
-
- resumeAfterTargetsNotReadyTimeoutLocked(newTimeout,
- commandEntry->inputWindowHandle != NULL
- ? commandEntry->inputWindowHandle->getInputChannel() : NULL);
-}
-
-void InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
- CommandEntry* commandEntry) {
- KeyEntry* entry = commandEntry->keyEntry;
-
- KeyEvent event;
- initializeKeyEvent(&event, entry);
-
- mLock.unlock();
-
- nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
- &event, entry->policyFlags);
-
- mLock.lock();
-
- if (delay < 0) {
- entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP;
- } else if (!delay) {
- entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
- } else {
- entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER;
- entry->interceptKeyWakeupTime = now() + delay;
- }
- entry->release();
-}
-
-void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
- CommandEntry* commandEntry) {
- sp<Connection> connection = commandEntry->connection;
- nsecs_t finishTime = commandEntry->eventTime;
- uint32_t seq = commandEntry->seq;
- bool handled = commandEntry->handled;
-
- // Handle post-event policy actions.
- DispatchEntry* dispatchEntry = connection->findWaitQueueEntry(seq);
- if (dispatchEntry) {
- nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime;
- if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) {
- String8 msg;
- msg.appendFormat("Window '%s' spent %0.1fms processing the last input event: ",
- connection->getWindowName(), eventDuration * 0.000001f);
- dispatchEntry->eventEntry->appendDescription(msg);
- ALOGI("%s", msg.string());
- }
-
- bool restartEvent;
- if (dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
- KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
- restartEvent = afterKeyEventLockedInterruptible(connection,
- dispatchEntry, keyEntry, handled);
- } else if (dispatchEntry->eventEntry->type == EventEntry::TYPE_MOTION) {
- MotionEntry* motionEntry = static_cast<MotionEntry*>(dispatchEntry->eventEntry);
- restartEvent = afterMotionEventLockedInterruptible(connection,
- dispatchEntry, motionEntry, handled);
- } else {
- restartEvent = false;
- }
-
- // Dequeue the event and start the next cycle.
- // Note that because the lock might have been released, it is possible that the
- // contents of the wait queue to have been drained, so we need to double-check
- // a few things.
- if (dispatchEntry == connection->findWaitQueueEntry(seq)) {
- connection->waitQueue.dequeue(dispatchEntry);
- traceWaitQueueLengthLocked(connection);
- if (restartEvent && connection->status == Connection::STATUS_NORMAL) {
- connection->outboundQueue.enqueueAtHead(dispatchEntry);
- traceOutboundQueueLengthLocked(connection);
- } else {
- releaseDispatchEntryLocked(dispatchEntry);
- }
- }
-
- // Start the next dispatch cycle for this connection.
- startDispatchCycleLocked(now(), connection);
- }
-}
-
-bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& connection,
- DispatchEntry* dispatchEntry, KeyEntry* keyEntry, bool handled) {
- if (!(keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK)) {
- // Get the fallback key state.
- // Clear it out after dispatching the UP.
- int32_t originalKeyCode = keyEntry->keyCode;
- int32_t fallbackKeyCode = connection->inputState.getFallbackKey(originalKeyCode);
- if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
- connection->inputState.removeFallbackKey(originalKeyCode);
- }
-
- if (handled || !dispatchEntry->hasForegroundTarget()) {
- // If the application handles the original key for which we previously
- // generated a fallback or if the window is not a foreground window,
- // then cancel the associated fallback key, if any.
- if (fallbackKeyCode != -1) {
- // Dispatch the unhandled key to the policy with the cancel flag.
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("Unhandled key event: Asking policy to cancel fallback action. "
- "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
- keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount,
- keyEntry->policyFlags);
-#endif
- KeyEvent event;
- initializeKeyEvent(&event, keyEntry);
- event.setFlags(event.getFlags() | AKEY_EVENT_FLAG_CANCELED);
-
- mLock.unlock();
-
- mPolicy->dispatchUnhandledKey(connection->inputWindowHandle,
- &event, keyEntry->policyFlags, &event);
-
- mLock.lock();
-
- // Cancel the fallback key.
- if (fallbackKeyCode != AKEYCODE_UNKNOWN) {
- CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS,
- "application handled the original non-fallback key "
- "or is no longer a foreground target, "
- "canceling previously dispatched fallback key");
- options.keyCode = fallbackKeyCode;
- synthesizeCancelationEventsForConnectionLocked(connection, options);
- }
- connection->inputState.removeFallbackKey(originalKeyCode);
- }
- } else {
- // If the application did not handle a non-fallback key, first check
- // that we are in a good state to perform unhandled key event processing
- // Then ask the policy what to do with it.
- bool initialDown = keyEntry->action == AKEY_EVENT_ACTION_DOWN
- && keyEntry->repeatCount == 0;
- if (fallbackKeyCode == -1 && !initialDown) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("Unhandled key event: Skipping unhandled key event processing "
- "since this is not an initial down. "
- "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
- originalKeyCode, keyEntry->action, keyEntry->repeatCount,
- keyEntry->policyFlags);
-#endif
- return false;
- }
-
- // Dispatch the unhandled key to the policy.
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("Unhandled key event: Asking policy to perform fallback action. "
- "keyCode=%d, action=%d, repeatCount=%d, policyFlags=0x%08x",
- keyEntry->keyCode, keyEntry->action, keyEntry->repeatCount,
- keyEntry->policyFlags);
-#endif
- KeyEvent event;
- initializeKeyEvent(&event, keyEntry);
-
- mLock.unlock();
-
- bool fallback = mPolicy->dispatchUnhandledKey(connection->inputWindowHandle,
- &event, keyEntry->policyFlags, &event);
-
- mLock.lock();
-
- if (connection->status != Connection::STATUS_NORMAL) {
- connection->inputState.removeFallbackKey(originalKeyCode);
- return false;
- }
-
- // Latch the fallback keycode for this key on an initial down.
- // The fallback keycode cannot change at any other point in the lifecycle.
- if (initialDown) {
- if (fallback) {
- fallbackKeyCode = event.getKeyCode();
- } else {
- fallbackKeyCode = AKEYCODE_UNKNOWN;
- }
- connection->inputState.setFallbackKey(originalKeyCode, fallbackKeyCode);
- }
-
- ALOG_ASSERT(fallbackKeyCode != -1);
-
- // Cancel the fallback key if the policy decides not to send it anymore.
- // We will continue to dispatch the key to the policy but we will no
- // longer dispatch a fallback key to the application.
- if (fallbackKeyCode != AKEYCODE_UNKNOWN
- && (!fallback || fallbackKeyCode != event.getKeyCode())) {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- if (fallback) {
- ALOGD("Unhandled key event: Policy requested to send key %d"
- "as a fallback for %d, but on the DOWN it had requested "
- "to send %d instead. Fallback canceled.",
- event.getKeyCode(), originalKeyCode, fallbackKeyCode);
- } else {
- ALOGD("Unhandled key event: Policy did not request fallback for %d, "
- "but on the DOWN it had requested to send %d. "
- "Fallback canceled.",
- originalKeyCode, fallbackKeyCode);
- }
-#endif
-
- CancelationOptions options(CancelationOptions::CANCEL_FALLBACK_EVENTS,
- "canceling fallback, policy no longer desires it");
- options.keyCode = fallbackKeyCode;
- synthesizeCancelationEventsForConnectionLocked(connection, options);
-
- fallback = false;
- fallbackKeyCode = AKEYCODE_UNKNOWN;
- if (keyEntry->action != AKEY_EVENT_ACTION_UP) {
- connection->inputState.setFallbackKey(originalKeyCode,
- fallbackKeyCode);
- }
- }
-
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- {
- String8 msg;
- const KeyedVector<int32_t, int32_t>& fallbackKeys =
- connection->inputState.getFallbackKeys();
- for (size_t i = 0; i < fallbackKeys.size(); i++) {
- msg.appendFormat(", %d->%d", fallbackKeys.keyAt(i),
- fallbackKeys.valueAt(i));
- }
- ALOGD("Unhandled key event: %d currently tracked fallback keys%s.",
- fallbackKeys.size(), msg.string());
- }
-#endif
-
- if (fallback) {
- // Restart the dispatch cycle using the fallback key.
- keyEntry->eventTime = event.getEventTime();
- keyEntry->deviceId = event.getDeviceId();
- keyEntry->source = event.getSource();
- keyEntry->flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
- keyEntry->keyCode = fallbackKeyCode;
- keyEntry->scanCode = event.getScanCode();
- keyEntry->metaState = event.getMetaState();
- keyEntry->repeatCount = event.getRepeatCount();
- keyEntry->downTime = event.getDownTime();
- keyEntry->syntheticRepeat = false;
-
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("Unhandled key event: Dispatching fallback key. "
- "originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x",
- originalKeyCode, fallbackKeyCode, keyEntry->metaState);
-#endif
- return true; // restart the event
- } else {
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("Unhandled key event: No fallback key.");
-#endif
- }
- }
- }
- return false;
-}
-
-bool InputDispatcher::afterMotionEventLockedInterruptible(const sp<Connection>& connection,
- DispatchEntry* dispatchEntry, MotionEntry* motionEntry, bool handled) {
- return false;
-}
-
-void InputDispatcher::doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry) {
- mLock.unlock();
-
- mPolicy->pokeUserActivity(commandEntry->eventTime, commandEntry->userActivityEventType);
-
- mLock.lock();
-}
-
-void InputDispatcher::initializeKeyEvent(KeyEvent* event, const KeyEntry* entry) {
- event->initialize(entry->deviceId, entry->source, entry->action, entry->flags,
- entry->keyCode, entry->scanCode, entry->metaState, entry->repeatCount,
- entry->downTime, entry->eventTime);
-}
-
-void InputDispatcher::updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
- int32_t injectionResult, nsecs_t timeSpentWaitingForApplication) {
- // TODO Write some statistics about how long we spend waiting.
-}
-
-void InputDispatcher::traceInboundQueueLengthLocked() {
- if (ATRACE_ENABLED()) {
- ATRACE_INT("iq", mInboundQueue.count());
- }
-}
-
-void InputDispatcher::traceOutboundQueueLengthLocked(const sp<Connection>& connection) {
- if (ATRACE_ENABLED()) {
- char counterName[40];
- snprintf(counterName, sizeof(counterName), "oq:%s", connection->getWindowName());
- ATRACE_INT(counterName, connection->outboundQueue.count());
- }
-}
-
-void InputDispatcher::traceWaitQueueLengthLocked(const sp<Connection>& connection) {
- if (ATRACE_ENABLED()) {
- char counterName[40];
- snprintf(counterName, sizeof(counterName), "wq:%s", connection->getWindowName());
- ATRACE_INT(counterName, connection->waitQueue.count());
- }
-}
-
-void InputDispatcher::dump(String8& dump) {
- AutoMutex _l(mLock);
-
- dump.append("Input Dispatcher State:\n");
- dumpDispatchStateLocked(dump);
-
- if (!mLastANRState.isEmpty()) {
- dump.append("\nInput Dispatcher State at time of last ANR:\n");
- dump.append(mLastANRState);
- }
-}
-
-void InputDispatcher::monitor() {
- // Acquire and release the lock to ensure that the dispatcher has not deadlocked.
- mLock.lock();
- mLooper->wake();
- mDispatcherIsAliveCondition.wait(mLock);
- mLock.unlock();
-}
-
-
-// --- InputDispatcher::Queue ---
-
-template <typename T>
-uint32_t InputDispatcher::Queue<T>::count() const {
- uint32_t result = 0;
- for (const T* entry = head; entry; entry = entry->next) {
- result += 1;
- }
- return result;
-}
-
-
-// --- InputDispatcher::InjectionState ---
-
-InputDispatcher::InjectionState::InjectionState(int32_t injectorPid, int32_t injectorUid) :
- refCount(1),
- injectorPid(injectorPid), injectorUid(injectorUid),
- injectionResult(INPUT_EVENT_INJECTION_PENDING), injectionIsAsync(false),
- pendingForegroundDispatches(0) {
-}
-
-InputDispatcher::InjectionState::~InjectionState() {
-}
-
-void InputDispatcher::InjectionState::release() {
- refCount -= 1;
- if (refCount == 0) {
- delete this;
- } else {
- ALOG_ASSERT(refCount > 0);
- }
-}
-
-
-// --- InputDispatcher::EventEntry ---
-
-InputDispatcher::EventEntry::EventEntry(int32_t type, nsecs_t eventTime, uint32_t policyFlags) :
- refCount(1), type(type), eventTime(eventTime), policyFlags(policyFlags),
- injectionState(NULL), dispatchInProgress(false) {
-}
-
-InputDispatcher::EventEntry::~EventEntry() {
- releaseInjectionState();
-}
-
-void InputDispatcher::EventEntry::release() {
- refCount -= 1;
- if (refCount == 0) {
- delete this;
- } else {
- ALOG_ASSERT(refCount > 0);
- }
-}
-
-void InputDispatcher::EventEntry::releaseInjectionState() {
- if (injectionState) {
- injectionState->release();
- injectionState = NULL;
- }
-}
-
-
-// --- InputDispatcher::ConfigurationChangedEntry ---
-
-InputDispatcher::ConfigurationChangedEntry::ConfigurationChangedEntry(nsecs_t eventTime) :
- EventEntry(TYPE_CONFIGURATION_CHANGED, eventTime, 0) {
-}
-
-InputDispatcher::ConfigurationChangedEntry::~ConfigurationChangedEntry() {
-}
-
-void InputDispatcher::ConfigurationChangedEntry::appendDescription(String8& msg) const {
- msg.append("ConfigurationChangedEvent(), policyFlags=0x%08x",
- policyFlags);
-}
-
-
-// --- InputDispatcher::DeviceResetEntry ---
-
-InputDispatcher::DeviceResetEntry::DeviceResetEntry(nsecs_t eventTime, int32_t deviceId) :
- EventEntry(TYPE_DEVICE_RESET, eventTime, 0),
- deviceId(deviceId) {
-}
-
-InputDispatcher::DeviceResetEntry::~DeviceResetEntry() {
-}
-
-void InputDispatcher::DeviceResetEntry::appendDescription(String8& msg) const {
- msg.appendFormat("DeviceResetEvent(deviceId=%d), policyFlags=0x%08x",
- deviceId, policyFlags);
-}
-
-
-// --- InputDispatcher::KeyEntry ---
-
-InputDispatcher::KeyEntry::KeyEntry(nsecs_t eventTime,
- int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action,
- int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
- int32_t repeatCount, nsecs_t downTime) :
- EventEntry(TYPE_KEY, eventTime, policyFlags),
- deviceId(deviceId), source(source), action(action), flags(flags),
- keyCode(keyCode), scanCode(scanCode), metaState(metaState),
- repeatCount(repeatCount), downTime(downTime),
- syntheticRepeat(false), interceptKeyResult(KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN),
- interceptKeyWakeupTime(0) {
-}
-
-InputDispatcher::KeyEntry::~KeyEntry() {
-}
-
-void InputDispatcher::KeyEntry::appendDescription(String8& msg) const {
- msg.appendFormat("KeyEvent(deviceId=%d, source=0x%08x, action=%d, "
- "flags=0x%08x, keyCode=%d, scanCode=%d, metaState=0x%08x, "
- "repeatCount=%d), policyFlags=0x%08x",
- deviceId, source, action, flags, keyCode, scanCode, metaState,
- repeatCount, policyFlags);
-}
-
-void InputDispatcher::KeyEntry::recycle() {
- releaseInjectionState();
-
- dispatchInProgress = false;
- syntheticRepeat = false;
- interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
- interceptKeyWakeupTime = 0;
-}
-
-
-// --- InputDispatcher::MotionEntry ---
-
-InputDispatcher::MotionEntry::MotionEntry(nsecs_t eventTime,
- int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action, int32_t flags,
- int32_t metaState, int32_t buttonState,
- int32_t edgeFlags, float xPrecision, float yPrecision,
- nsecs_t downTime, int32_t displayId, uint32_t pointerCount,
- const PointerProperties* pointerProperties, const PointerCoords* pointerCoords) :
- EventEntry(TYPE_MOTION, eventTime, policyFlags),
- eventTime(eventTime),
- deviceId(deviceId), source(source), action(action), flags(flags),
- metaState(metaState), buttonState(buttonState), edgeFlags(edgeFlags),
- xPrecision(xPrecision), yPrecision(yPrecision),
- downTime(downTime), displayId(displayId), pointerCount(pointerCount) {
- for (uint32_t i = 0; i < pointerCount; i++) {
- this->pointerProperties[i].copyFrom(pointerProperties[i]);
- this->pointerCoords[i].copyFrom(pointerCoords[i]);
- }
-}
-
-InputDispatcher::MotionEntry::~MotionEntry() {
-}
-
-void InputDispatcher::MotionEntry::appendDescription(String8& msg) const {
- msg.appendFormat("MotionEvent(deviceId=%d, source=0x%08x, action=%d, "
- "flags=0x%08x, metaState=0x%08x, buttonState=0x%08x, edgeFlags=0x%08x, "
- "xPrecision=%.1f, yPrecision=%.1f, displayId=%d, pointers=[",
- deviceId, source, action, flags, metaState, buttonState, edgeFlags,
- xPrecision, yPrecision, displayId);
- for (uint32_t i = 0; i < pointerCount; i++) {
- if (i) {
- msg.append(", ");
- }
- msg.appendFormat("%d: (%.1f, %.1f)", pointerProperties[i].id,
- pointerCoords[i].getX(), pointerCoords[i].getY());
- }
- msg.appendFormat("]), policyFlags=0x%08x", policyFlags);
-}
-
-
-// --- InputDispatcher::DispatchEntry ---
-
-volatile int32_t InputDispatcher::DispatchEntry::sNextSeqAtomic;
-
-InputDispatcher::DispatchEntry::DispatchEntry(EventEntry* eventEntry,
- int32_t targetFlags, float xOffset, float yOffset, float scaleFactor) :
- seq(nextSeq()),
- eventEntry(eventEntry), targetFlags(targetFlags),
- xOffset(xOffset), yOffset(yOffset), scaleFactor(scaleFactor),
- deliveryTime(0), resolvedAction(0), resolvedFlags(0) {
- eventEntry->refCount += 1;
-}
-
-InputDispatcher::DispatchEntry::~DispatchEntry() {
- eventEntry->release();
-}
-
-uint32_t InputDispatcher::DispatchEntry::nextSeq() {
- // Sequence number 0 is reserved and will never be returned.
- uint32_t seq;
- do {
- seq = android_atomic_inc(&sNextSeqAtomic);
- } while (!seq);
- return seq;
-}
-
-
-// --- InputDispatcher::InputState ---
-
-InputDispatcher::InputState::InputState() {
-}
-
-InputDispatcher::InputState::~InputState() {
-}
-
-bool InputDispatcher::InputState::isNeutral() const {
- return mKeyMementos.isEmpty() && mMotionMementos.isEmpty();
-}
-
-bool InputDispatcher::InputState::isHovering(int32_t deviceId, uint32_t source,
- int32_t displayId) const {
- for (size_t i = 0; i < mMotionMementos.size(); i++) {
- const MotionMemento& memento = mMotionMementos.itemAt(i);
- if (memento.deviceId == deviceId
- && memento.source == source
- && memento.displayId == displayId
- && memento.hovering) {
- return true;
- }
- }
- return false;
-}
-
-bool InputDispatcher::InputState::trackKey(const KeyEntry* entry,
- int32_t action, int32_t flags) {
- switch (action) {
- case AKEY_EVENT_ACTION_UP: {
- if (entry->flags & AKEY_EVENT_FLAG_FALLBACK) {
- for (size_t i = 0; i < mFallbackKeys.size(); ) {
- if (mFallbackKeys.valueAt(i) == entry->keyCode) {
- mFallbackKeys.removeItemsAt(i);
- } else {
- i += 1;
- }
- }
- }
- ssize_t index = findKeyMemento(entry);
- if (index >= 0) {
- mKeyMementos.removeAt(index);
- return true;
- }
- /* FIXME: We can't just drop the key up event because that prevents creating
- * popup windows that are automatically shown when a key is held and then
- * dismissed when the key is released. The problem is that the popup will
- * not have received the original key down, so the key up will be considered
- * to be inconsistent with its observed state. We could perhaps handle this
- * by synthesizing a key down but that will cause other problems.
- *
- * So for now, allow inconsistent key up events to be dispatched.
- *
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("Dropping inconsistent key up event: deviceId=%d, source=%08x, "
- "keyCode=%d, scanCode=%d",
- entry->deviceId, entry->source, entry->keyCode, entry->scanCode);
-#endif
- return false;
- */
- return true;
- }
-
- case AKEY_EVENT_ACTION_DOWN: {
- ssize_t index = findKeyMemento(entry);
- if (index >= 0) {
- mKeyMementos.removeAt(index);
- }
- addKeyMemento(entry, flags);
- return true;
- }
-
- default:
- return true;
- }
-}
-
-bool InputDispatcher::InputState::trackMotion(const MotionEntry* entry,
- int32_t action, int32_t flags) {
- int32_t actionMasked = action & AMOTION_EVENT_ACTION_MASK;
- switch (actionMasked) {
- case AMOTION_EVENT_ACTION_UP:
- case AMOTION_EVENT_ACTION_CANCEL: {
- ssize_t index = findMotionMemento(entry, false /*hovering*/);
- if (index >= 0) {
- mMotionMementos.removeAt(index);
- return true;
- }
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("Dropping inconsistent motion up or cancel event: deviceId=%d, source=%08x, "
- "actionMasked=%d",
- entry->deviceId, entry->source, actionMasked);
-#endif
- return false;
- }
-
- case AMOTION_EVENT_ACTION_DOWN: {
- ssize_t index = findMotionMemento(entry, false /*hovering*/);
- if (index >= 0) {
- mMotionMementos.removeAt(index);
- }
- addMotionMemento(entry, flags, false /*hovering*/);
- return true;
- }
-
- case AMOTION_EVENT_ACTION_POINTER_UP:
- case AMOTION_EVENT_ACTION_POINTER_DOWN:
- case AMOTION_EVENT_ACTION_MOVE: {
- ssize_t index = findMotionMemento(entry, false /*hovering*/);
- if (index >= 0) {
- MotionMemento& memento = mMotionMementos.editItemAt(index);
- memento.setPointers(entry);
- return true;
- }
- if (actionMasked == AMOTION_EVENT_ACTION_MOVE
- && (entry->source & (AINPUT_SOURCE_CLASS_JOYSTICK
- | AINPUT_SOURCE_CLASS_NAVIGATION))) {
- // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP.
- return true;
- }
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("Dropping inconsistent motion pointer up/down or move event: "
- "deviceId=%d, source=%08x, actionMasked=%d",
- entry->deviceId, entry->source, actionMasked);
-#endif
- return false;
- }
-
- case AMOTION_EVENT_ACTION_HOVER_EXIT: {
- ssize_t index = findMotionMemento(entry, true /*hovering*/);
- if (index >= 0) {
- mMotionMementos.removeAt(index);
- return true;
- }
-#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("Dropping inconsistent motion hover exit event: deviceId=%d, source=%08x",
- entry->deviceId, entry->source);
-#endif
- return false;
- }
-
- case AMOTION_EVENT_ACTION_HOVER_ENTER:
- case AMOTION_EVENT_ACTION_HOVER_MOVE: {
- ssize_t index = findMotionMemento(entry, true /*hovering*/);
- if (index >= 0) {
- mMotionMementos.removeAt(index);
- }
- addMotionMemento(entry, flags, true /*hovering*/);
- return true;
- }
-
- default:
- return true;
- }
-}
-
-ssize_t InputDispatcher::InputState::findKeyMemento(const KeyEntry* entry) const {
- for (size_t i = 0; i < mKeyMementos.size(); i++) {
- const KeyMemento& memento = mKeyMementos.itemAt(i);
- if (memento.deviceId == entry->deviceId
- && memento.source == entry->source
- && memento.keyCode == entry->keyCode
- && memento.scanCode == entry->scanCode) {
- return i;
- }
- }
- return -1;
-}
-
-ssize_t InputDispatcher::InputState::findMotionMemento(const MotionEntry* entry,
- bool hovering) const {
- for (size_t i = 0; i < mMotionMementos.size(); i++) {
- const MotionMemento& memento = mMotionMementos.itemAt(i);
- if (memento.deviceId == entry->deviceId
- && memento.source == entry->source
- && memento.displayId == entry->displayId
- && memento.hovering == hovering) {
- return i;
- }
- }
- return -1;
-}
-
-void InputDispatcher::InputState::addKeyMemento(const KeyEntry* entry, int32_t flags) {
- mKeyMementos.push();
- KeyMemento& memento = mKeyMementos.editTop();
- memento.deviceId = entry->deviceId;
- memento.source = entry->source;
- memento.keyCode = entry->keyCode;
- memento.scanCode = entry->scanCode;
- memento.metaState = entry->metaState;
- memento.flags = flags;
- memento.downTime = entry->downTime;
- memento.policyFlags = entry->policyFlags;
-}
-
-void InputDispatcher::InputState::addMotionMemento(const MotionEntry* entry,
- int32_t flags, bool hovering) {
- mMotionMementos.push();
- MotionMemento& memento = mMotionMementos.editTop();
- memento.deviceId = entry->deviceId;
- memento.source = entry->source;
- memento.flags = flags;
- memento.xPrecision = entry->xPrecision;
- memento.yPrecision = entry->yPrecision;
- memento.downTime = entry->downTime;
- memento.displayId = entry->displayId;
- memento.setPointers(entry);
- memento.hovering = hovering;
- memento.policyFlags = entry->policyFlags;
-}
-
-void InputDispatcher::InputState::MotionMemento::setPointers(const MotionEntry* entry) {
- pointerCount = entry->pointerCount;
- for (uint32_t i = 0; i < entry->pointerCount; i++) {
- pointerProperties[i].copyFrom(entry->pointerProperties[i]);
- pointerCoords[i].copyFrom(entry->pointerCoords[i]);
- }
-}
-
-void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTime,
- Vector<EventEntry*>& outEvents, const CancelationOptions& options) {
- for (size_t i = 0; i < mKeyMementos.size(); i++) {
- const KeyMemento& memento = mKeyMementos.itemAt(i);
- if (shouldCancelKey(memento, options)) {
- outEvents.push(new KeyEntry(currentTime,
- memento.deviceId, memento.source, memento.policyFlags,
- AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED,
- memento.keyCode, memento.scanCode, memento.metaState, 0, memento.downTime));
- }
- }
-
- for (size_t i = 0; i < mMotionMementos.size(); i++) {
- const MotionMemento& memento = mMotionMementos.itemAt(i);
- if (shouldCancelMotion(memento, options)) {
- outEvents.push(new MotionEntry(currentTime,
- memento.deviceId, memento.source, memento.policyFlags,
- memento.hovering
- ? AMOTION_EVENT_ACTION_HOVER_EXIT
- : AMOTION_EVENT_ACTION_CANCEL,
- memento.flags, 0, 0, 0,
- memento.xPrecision, memento.yPrecision, memento.downTime,
- memento.displayId,
- memento.pointerCount, memento.pointerProperties, memento.pointerCoords));
- }
- }
-}
-
-void InputDispatcher::InputState::clear() {
- mKeyMementos.clear();
- mMotionMementos.clear();
- mFallbackKeys.clear();
-}
-
-void InputDispatcher::InputState::copyPointerStateTo(InputState& other) const {
- for (size_t i = 0; i < mMotionMementos.size(); i++) {
- const MotionMemento& memento = mMotionMementos.itemAt(i);
- if (memento.source & AINPUT_SOURCE_CLASS_POINTER) {
- for (size_t j = 0; j < other.mMotionMementos.size(); ) {
- const MotionMemento& otherMemento = other.mMotionMementos.itemAt(j);
- if (memento.deviceId == otherMemento.deviceId
- && memento.source == otherMemento.source
- && memento.displayId == otherMemento.displayId) {
- other.mMotionMementos.removeAt(j);
- } else {
- j += 1;
- }
- }
- other.mMotionMementos.push(memento);
- }
- }
-}
-
-int32_t InputDispatcher::InputState::getFallbackKey(int32_t originalKeyCode) {
- ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
- return index >= 0 ? mFallbackKeys.valueAt(index) : -1;
-}
-
-void InputDispatcher::InputState::setFallbackKey(int32_t originalKeyCode,
- int32_t fallbackKeyCode) {
- ssize_t index = mFallbackKeys.indexOfKey(originalKeyCode);
- if (index >= 0) {
- mFallbackKeys.replaceValueAt(index, fallbackKeyCode);
- } else {
- mFallbackKeys.add(originalKeyCode, fallbackKeyCode);
- }
-}
-
-void InputDispatcher::InputState::removeFallbackKey(int32_t originalKeyCode) {
- mFallbackKeys.removeItem(originalKeyCode);
-}
-
-bool InputDispatcher::InputState::shouldCancelKey(const KeyMemento& memento,
- const CancelationOptions& options) {
- if (options.keyCode != -1 && memento.keyCode != options.keyCode) {
- return false;
- }
-
- if (options.deviceId != -1 && memento.deviceId != options.deviceId) {
- return false;
- }
-
- switch (options.mode) {
- case CancelationOptions::CANCEL_ALL_EVENTS:
- case CancelationOptions::CANCEL_NON_POINTER_EVENTS:
- return true;
- case CancelationOptions::CANCEL_FALLBACK_EVENTS:
- return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
- default:
- return false;
- }
-}
-
-bool InputDispatcher::InputState::shouldCancelMotion(const MotionMemento& memento,
- const CancelationOptions& options) {
- if (options.deviceId != -1 && memento.deviceId != options.deviceId) {
- return false;
- }
-
- switch (options.mode) {
- case CancelationOptions::CANCEL_ALL_EVENTS:
- return true;
- case CancelationOptions::CANCEL_POINTER_EVENTS:
- return memento.source & AINPUT_SOURCE_CLASS_POINTER;
- case CancelationOptions::CANCEL_NON_POINTER_EVENTS:
- return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
- default:
- return false;
- }
-}
-
-
-// --- InputDispatcher::Connection ---
-
-InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel,
- const sp<InputWindowHandle>& inputWindowHandle, bool monitor) :
- status(STATUS_NORMAL), inputChannel(inputChannel), inputWindowHandle(inputWindowHandle),
- monitor(monitor),
- inputPublisher(inputChannel), inputPublisherBlocked(false) {
-}
-
-InputDispatcher::Connection::~Connection() {
-}
-
-const char* InputDispatcher::Connection::getWindowName() const {
- if (inputWindowHandle != NULL) {
- return inputWindowHandle->getName().string();
- }
- if (monitor) {
- return "monitor";
- }
- return "?";
-}
-
-const char* InputDispatcher::Connection::getStatusLabel() const {
- switch (status) {
- case STATUS_NORMAL:
- return "NORMAL";
-
- case STATUS_BROKEN:
- return "BROKEN";
-
- case STATUS_ZOMBIE:
- return "ZOMBIE";
-
- default:
- return "UNKNOWN";
- }
-}
-
-InputDispatcher::DispatchEntry* InputDispatcher::Connection::findWaitQueueEntry(uint32_t seq) {
- for (DispatchEntry* entry = waitQueue.head; entry != NULL; entry = entry->next) {
- if (entry->seq == seq) {
- return entry;
- }
- }
- return NULL;
-}
-
-
-// --- InputDispatcher::CommandEntry ---
-
-InputDispatcher::CommandEntry::CommandEntry(Command command) :
- command(command), eventTime(0), keyEntry(NULL), userActivityEventType(0),
- seq(0), handled(false) {
-}
-
-InputDispatcher::CommandEntry::~CommandEntry() {
-}
-
-
-// --- InputDispatcher::TouchState ---
-
-InputDispatcher::TouchState::TouchState() :
- down(false), split(false), deviceId(-1), source(0), displayId(-1) {
-}
-
-InputDispatcher::TouchState::~TouchState() {
-}
-
-void InputDispatcher::TouchState::reset() {
- down = false;
- split = false;
- deviceId = -1;
- source = 0;
- displayId = -1;
- windows.clear();
-}
-
-void InputDispatcher::TouchState::copyFrom(const TouchState& other) {
- down = other.down;
- split = other.split;
- deviceId = other.deviceId;
- source = other.source;
- displayId = other.displayId;
- windows = other.windows;
-}
-
-void InputDispatcher::TouchState::addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle,
- int32_t targetFlags, BitSet32 pointerIds) {
- if (targetFlags & InputTarget::FLAG_SPLIT) {
- split = true;
- }
-
- for (size_t i = 0; i < windows.size(); i++) {
- TouchedWindow& touchedWindow = windows.editItemAt(i);
- if (touchedWindow.windowHandle == windowHandle) {
- touchedWindow.targetFlags |= targetFlags;
- if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
- touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS;
- }
- touchedWindow.pointerIds.value |= pointerIds.value;
- return;
- }
- }
-
- windows.push();
-
- TouchedWindow& touchedWindow = windows.editTop();
- touchedWindow.windowHandle = windowHandle;
- touchedWindow.targetFlags = targetFlags;
- touchedWindow.pointerIds = pointerIds;
-}
-
-void InputDispatcher::TouchState::removeWindow(const sp<InputWindowHandle>& windowHandle) {
- for (size_t i = 0; i < windows.size(); i++) {
- if (windows.itemAt(i).windowHandle == windowHandle) {
- windows.removeAt(i);
- return;
- }
- }
-}
-
-void InputDispatcher::TouchState::filterNonAsIsTouchWindows() {
- for (size_t i = 0 ; i < windows.size(); ) {
- TouchedWindow& window = windows.editItemAt(i);
- if (window.targetFlags & (InputTarget::FLAG_DISPATCH_AS_IS
- | InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER)) {
- window.targetFlags &= ~InputTarget::FLAG_DISPATCH_MASK;
- window.targetFlags |= InputTarget::FLAG_DISPATCH_AS_IS;
- i += 1;
- } else {
- windows.removeAt(i);
- }
- }
-}
-
-sp<InputWindowHandle> InputDispatcher::TouchState::getFirstForegroundWindowHandle() const {
- for (size_t i = 0; i < windows.size(); i++) {
- const TouchedWindow& window = windows.itemAt(i);
- if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
- return window.windowHandle;
- }
- }
- return NULL;
-}
-
-bool InputDispatcher::TouchState::isSlippery() const {
- // Must have exactly one foreground window.
- bool haveSlipperyForegroundWindow = false;
- for (size_t i = 0; i < windows.size(); i++) {
- const TouchedWindow& window = windows.itemAt(i);
- if (window.targetFlags & InputTarget::FLAG_FOREGROUND) {
- if (haveSlipperyForegroundWindow
- || !(window.windowHandle->getInfo()->layoutParamsFlags
- & InputWindowInfo::FLAG_SLIPPERY)) {
- return false;
- }
- haveSlipperyForegroundWindow = true;
- }
- }
- return haveSlipperyForegroundWindow;
-}
-
-
-// --- InputDispatcherThread ---
-
-InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
- Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
-}
-
-InputDispatcherThread::~InputDispatcherThread() {
-}
-
-bool InputDispatcherThread::threadLoop() {
- mDispatcher->dispatchOnce();
- return true;
-}
-
-} // namespace android
diff --git a/libs/input/InputDispatcher.h b/libs/input/InputDispatcher.h
deleted file mode 100644
index 190e7b2..0000000
--- a/libs/input/InputDispatcher.h
+++ /dev/null
@@ -1,1123 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_DISPATCHER_H
-#define _UI_INPUT_DISPATCHER_H
-
-#include <input/Input.h>
-#include <input/InputTransport.h>
-#include <utils/KeyedVector.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-#include <utils/Timers.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <utils/Looper.h>
-#include <utils/BitSet.h>
-#include <cutils/atomic.h>
-
-#include <stddef.h>
-#include <unistd.h>
-#include <limits.h>
-
-#include "InputWindow.h"
-#include "InputApplication.h"
-#include "InputListener.h"
-
-
-namespace android {
-
-/*
- * Constants used to report the outcome of input event injection.
- */
-enum {
- /* (INTERNAL USE ONLY) Specifies that injection is pending and its outcome is unknown. */
- INPUT_EVENT_INJECTION_PENDING = -1,
-
- /* Injection succeeded. */
- INPUT_EVENT_INJECTION_SUCCEEDED = 0,
-
- /* Injection failed because the injector did not have permission to inject
- * into the application with input focus. */
- INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1,
-
- /* Injection failed because there were no available input targets. */
- INPUT_EVENT_INJECTION_FAILED = 2,
-
- /* Injection failed due to a timeout. */
- INPUT_EVENT_INJECTION_TIMED_OUT = 3
-};
-
-/*
- * Constants used to determine the input event injection synchronization mode.
- */
-enum {
- /* Injection is asynchronous and is assumed always to be successful. */
- INPUT_EVENT_INJECTION_SYNC_NONE = 0,
-
- /* Waits for previous events to be dispatched so that the input dispatcher can determine
- * whether input event injection willbe permitted based on the current input focus.
- * Does not wait for the input event to finish processing. */
- INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT = 1,
-
- /* Waits for the input event to be completely processed. */
- INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISHED = 2,
-};
-
-
-/*
- * An input target specifies how an input event is to be dispatched to a particular window
- * including the window's input channel, control flags, a timeout, and an X / Y offset to
- * be added to input event coordinates to compensate for the absolute position of the
- * window area.
- */
-struct InputTarget {
- enum {
- /* This flag indicates that the event is being delivered to a foreground application. */
- FLAG_FOREGROUND = 1 << 0,
-
- /* This flag indicates that the target of a MotionEvent is partly or wholly
- * obscured by another visible window above it. The motion event should be
- * delivered with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED. */
- FLAG_WINDOW_IS_OBSCURED = 1 << 1,
-
- /* This flag indicates that a motion event is being split across multiple windows. */
- FLAG_SPLIT = 1 << 2,
-
- /* This flag indicates that the pointer coordinates dispatched to the application
- * will be zeroed out to avoid revealing information to an application. This is
- * used in conjunction with FLAG_DISPATCH_AS_OUTSIDE to prevent apps not sharing
- * the same UID from watching all touches. */
- FLAG_ZERO_COORDS = 1 << 3,
-
- /* This flag indicates that the event should be sent as is.
- * Should always be set unless the event is to be transmuted. */
- FLAG_DISPATCH_AS_IS = 1 << 8,
-
- /* This flag indicates that a MotionEvent with AMOTION_EVENT_ACTION_DOWN falls outside
- * of the area of this target and so should instead be delivered as an
- * AMOTION_EVENT_ACTION_OUTSIDE to this target. */
- FLAG_DISPATCH_AS_OUTSIDE = 1 << 9,
-
- /* This flag indicates that a hover sequence is starting in the given window.
- * The event is transmuted into ACTION_HOVER_ENTER. */
- FLAG_DISPATCH_AS_HOVER_ENTER = 1 << 10,
-
- /* This flag indicates that a hover event happened outside of a window which handled
- * previous hover events, signifying the end of the current hover sequence for that
- * window.
- * The event is transmuted into ACTION_HOVER_ENTER. */
- FLAG_DISPATCH_AS_HOVER_EXIT = 1 << 11,
-
- /* This flag indicates that the event should be canceled.
- * It is used to transmute ACTION_MOVE into ACTION_CANCEL when a touch slips
- * outside of a window. */
- FLAG_DISPATCH_AS_SLIPPERY_EXIT = 1 << 12,
-
- /* This flag indicates that the event should be dispatched as an initial down.
- * It is used to transmute ACTION_MOVE into ACTION_DOWN when a touch slips
- * into a new window. */
- FLAG_DISPATCH_AS_SLIPPERY_ENTER = 1 << 13,
-
- /* Mask for all dispatch modes. */
- FLAG_DISPATCH_MASK = FLAG_DISPATCH_AS_IS
- | FLAG_DISPATCH_AS_OUTSIDE
- | FLAG_DISPATCH_AS_HOVER_ENTER
- | FLAG_DISPATCH_AS_HOVER_EXIT
- | FLAG_DISPATCH_AS_SLIPPERY_EXIT
- | FLAG_DISPATCH_AS_SLIPPERY_ENTER,
- };
-
- // The input channel to be targeted.
- sp<InputChannel> inputChannel;
-
- // Flags for the input target.
- int32_t flags;
-
- // The x and y offset to add to a MotionEvent as it is delivered.
- // (ignored for KeyEvents)
- float xOffset, yOffset;
-
- // Scaling factor to apply to MotionEvent as it is delivered.
- // (ignored for KeyEvents)
- float scaleFactor;
-
- // The subset of pointer ids to include in motion events dispatched to this input target
- // if FLAG_SPLIT is set.
- BitSet32 pointerIds;
-};
-
-
-/*
- * Input dispatcher configuration.
- *
- * Specifies various options that modify the behavior of the input dispatcher.
- * The values provided here are merely defaults. The actual values will come from ViewConfiguration
- * and are passed into the dispatcher during initialization.
- */
-struct InputDispatcherConfiguration {
- // The key repeat initial timeout.
- nsecs_t keyRepeatTimeout;
-
- // The key repeat inter-key delay.
- nsecs_t keyRepeatDelay;
-
- InputDispatcherConfiguration() :
- keyRepeatTimeout(500 * 1000000LL),
- keyRepeatDelay(50 * 1000000LL) { }
-};
-
-
-/*
- * Input dispatcher policy interface.
- *
- * The input reader policy is used by the input reader to interact with the Window Manager
- * and other system components.
- *
- * The actual implementation is partially supported by callbacks into the DVM
- * via JNI. This interface is also mocked in the unit tests.
- */
-class InputDispatcherPolicyInterface : public virtual RefBase {
-protected:
- InputDispatcherPolicyInterface() { }
- virtual ~InputDispatcherPolicyInterface() { }
-
-public:
- /* Notifies the system that a configuration change has occurred. */
- virtual void notifyConfigurationChanged(nsecs_t when) = 0;
-
- /* Notifies the system that an application is not responding.
- * Returns a new timeout to continue waiting, or 0 to abort dispatch. */
- virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
- const sp<InputWindowHandle>& inputWindowHandle,
- const String8& reason) = 0;
-
- /* Notifies the system that an input channel is unrecoverably broken. */
- virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) = 0;
-
- /* Gets the input dispatcher configuration. */
- virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) = 0;
-
- /* Returns true if automatic key repeating is enabled. */
- virtual bool isKeyRepeatEnabled() = 0;
-
- /* Filters an input event.
- * Return true to dispatch the event unmodified, false to consume the event.
- * A filter can also transform and inject events later by passing POLICY_FLAG_FILTERED
- * to injectInputEvent.
- */
- virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) = 0;
-
- /* Intercepts a key event immediately before queueing it.
- * The policy can use this method as an opportunity to perform power management functions
- * and early event preprocessing such as updating policy flags.
- *
- * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
- * should be dispatched to applications.
- */
- virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) = 0;
-
- /* Intercepts a touch, trackball or other motion event before queueing it.
- * The policy can use this method as an opportunity to perform power management functions
- * and early event preprocessing such as updating policy flags.
- *
- * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
- * should be dispatched to applications.
- */
- virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) = 0;
-
- /* Allows the policy a chance to intercept a key before dispatching. */
- virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
- const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
-
- /* Allows the policy a chance to perform default processing for an unhandled key.
- * Returns an alternate keycode to redispatch as a fallback, or 0 to give up. */
- virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
- const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) = 0;
-
- /* Notifies the policy about switch events.
- */
- virtual void notifySwitch(nsecs_t when,
- uint32_t switchValues, uint32_t switchMask, uint32_t policyFlags) = 0;
-
- /* Poke user activity for an event dispatched to a window. */
- virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) = 0;
-
- /* Checks whether a given application pid/uid has permission to inject input events
- * into other applications.
- *
- * This method is special in that its implementation promises to be non-reentrant and
- * is safe to call while holding other locks. (Most other methods make no such guarantees!)
- */
- virtual bool checkInjectEventsPermissionNonReentrant(
- int32_t injectorPid, int32_t injectorUid) = 0;
-};
-
-
-/* Notifies the system about input events generated by the input reader.
- * The dispatcher is expected to be mostly asynchronous. */
-class InputDispatcherInterface : public virtual RefBase, public InputListenerInterface {
-protected:
- InputDispatcherInterface() { }
- virtual ~InputDispatcherInterface() { }
-
-public:
- /* Dumps the state of the input dispatcher.
- *
- * This method may be called on any thread (usually by the input manager). */
- virtual void dump(String8& dump) = 0;
-
- /* Called by the heatbeat to ensures that the dispatcher has not deadlocked. */
- virtual void monitor() = 0;
-
- /* Runs a single iteration of the dispatch loop.
- * Nominally processes one queued event, a timeout, or a response from an input consumer.
- *
- * This method should only be called on the input dispatcher thread.
- */
- virtual void dispatchOnce() = 0;
-
- /* Injects an input event and optionally waits for sync.
- * The synchronization mode determines whether the method blocks while waiting for
- * input injection to proceed.
- * Returns one of the INPUT_EVENT_INJECTION_XXX constants.
- *
- * This method may be called on any thread (usually by the input manager).
- */
- virtual int32_t injectInputEvent(const InputEvent* event,
- int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
- uint32_t policyFlags) = 0;
-
- /* Sets the list of input windows.
- *
- * This method may be called on any thread (usually by the input manager).
- */
- virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles) = 0;
-
- /* Sets the focused application.
- *
- * This method may be called on any thread (usually by the input manager).
- */
- virtual void setFocusedApplication(
- const sp<InputApplicationHandle>& inputApplicationHandle) = 0;
-
- /* Sets the input dispatching mode.
- *
- * This method may be called on any thread (usually by the input manager).
- */
- virtual void setInputDispatchMode(bool enabled, bool frozen) = 0;
-
- /* Sets whether input event filtering is enabled.
- * When enabled, incoming input events are sent to the policy's filterInputEvent
- * method instead of being dispatched. The filter is expected to use
- * injectInputEvent to inject the events it would like to have dispatched.
- * It should include POLICY_FLAG_FILTERED in the policy flags during injection.
- */
- virtual void setInputFilterEnabled(bool enabled) = 0;
-
- /* Transfers touch focus from the window associated with one channel to the
- * window associated with the other channel.
- *
- * Returns true on success. False if the window did not actually have touch focus.
- */
- virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
- const sp<InputChannel>& toChannel) = 0;
-
- /* Registers or unregister input channels that may be used as targets for input events.
- * If monitor is true, the channel will receive a copy of all input events.
- *
- * These methods may be called on any thread (usually by the input manager).
- */
- virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
- const sp<InputWindowHandle>& inputWindowHandle, bool monitor) = 0;
- virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) = 0;
-};
-
-/* Dispatches events to input targets. Some functions of the input dispatcher, such as
- * identifying input targets, are controlled by a separate policy object.
- *
- * IMPORTANT INVARIANT:
- * Because the policy can potentially block or cause re-entrance into the input dispatcher,
- * the input dispatcher never calls into the policy while holding its internal locks.
- * The implementation is also carefully designed to recover from scenarios such as an
- * input channel becoming unregistered while identifying input targets or processing timeouts.
- *
- * Methods marked 'Locked' must be called with the lock acquired.
- *
- * Methods marked 'LockedInterruptible' must be called with the lock acquired but
- * may during the course of their execution release the lock, call into the policy, and
- * then reacquire the lock. The caller is responsible for recovering gracefully.
- *
- * A 'LockedInterruptible' method may called a 'Locked' method, but NOT vice-versa.
- */
-class InputDispatcher : public InputDispatcherInterface {
-protected:
- virtual ~InputDispatcher();
-
-public:
- explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy);
-
- virtual void dump(String8& dump);
- virtual void monitor();
-
- virtual void dispatchOnce();
-
- virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args);
- virtual void notifyKey(const NotifyKeyArgs* args);
- virtual void notifyMotion(const NotifyMotionArgs* args);
- virtual void notifySwitch(const NotifySwitchArgs* args);
- virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args);
-
- virtual int32_t injectInputEvent(const InputEvent* event,
- int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
- uint32_t policyFlags);
-
- virtual void setInputWindows(const Vector<sp<InputWindowHandle> >& inputWindowHandles);
- virtual void setFocusedApplication(const sp<InputApplicationHandle>& inputApplicationHandle);
- virtual void setInputDispatchMode(bool enabled, bool frozen);
- virtual void setInputFilterEnabled(bool enabled);
-
- virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
- const sp<InputChannel>& toChannel);
-
- virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
- const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
- virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel);
-
-private:
- template <typename T>
- struct Link {
- T* next;
- T* prev;
-
- protected:
- inline Link() : next(NULL), prev(NULL) { }
- };
-
- struct InjectionState {
- mutable int32_t refCount;
-
- int32_t injectorPid;
- int32_t injectorUid;
- int32_t injectionResult; // initially INPUT_EVENT_INJECTION_PENDING
- bool injectionIsAsync; // set to true if injection is not waiting for the result
- int32_t pendingForegroundDispatches; // the number of foreground dispatches in progress
-
- InjectionState(int32_t injectorPid, int32_t injectorUid);
- void release();
-
- private:
- ~InjectionState();
- };
-
- struct EventEntry : Link<EventEntry> {
- enum {
- TYPE_CONFIGURATION_CHANGED,
- TYPE_DEVICE_RESET,
- TYPE_KEY,
- TYPE_MOTION
- };
-
- mutable int32_t refCount;
- int32_t type;
- nsecs_t eventTime;
- uint32_t policyFlags;
- InjectionState* injectionState;
-
- bool dispatchInProgress; // initially false, set to true while dispatching
-
- inline bool isInjected() const { return injectionState != NULL; }
-
- void release();
-
- virtual void appendDescription(String8& msg) const = 0;
-
- protected:
- EventEntry(int32_t type, nsecs_t eventTime, uint32_t policyFlags);
- virtual ~EventEntry();
- void releaseInjectionState();
- };
-
- struct ConfigurationChangedEntry : EventEntry {
- ConfigurationChangedEntry(nsecs_t eventTime);
- virtual void appendDescription(String8& msg) const;
-
- protected:
- virtual ~ConfigurationChangedEntry();
- };
-
- struct DeviceResetEntry : EventEntry {
- int32_t deviceId;
-
- DeviceResetEntry(nsecs_t eventTime, int32_t deviceId);
- virtual void appendDescription(String8& msg) const;
-
- protected:
- virtual ~DeviceResetEntry();
- };
-
- struct KeyEntry : EventEntry {
- int32_t deviceId;
- uint32_t source;
- int32_t action;
- int32_t flags;
- int32_t keyCode;
- int32_t scanCode;
- int32_t metaState;
- int32_t repeatCount;
- nsecs_t downTime;
-
- bool syntheticRepeat; // set to true for synthetic key repeats
-
- enum InterceptKeyResult {
- INTERCEPT_KEY_RESULT_UNKNOWN,
- INTERCEPT_KEY_RESULT_SKIP,
- INTERCEPT_KEY_RESULT_CONTINUE,
- INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER,
- };
- InterceptKeyResult interceptKeyResult; // set based on the interception result
- nsecs_t interceptKeyWakeupTime; // used with INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER
-
- KeyEntry(nsecs_t eventTime,
- int32_t deviceId, uint32_t source, uint32_t policyFlags, int32_t action,
- int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
- int32_t repeatCount, nsecs_t downTime);
- virtual void appendDescription(String8& msg) const;
- void recycle();
-
- protected:
- virtual ~KeyEntry();
- };
-
- struct MotionEntry : EventEntry {
- nsecs_t eventTime;
- int32_t deviceId;
- uint32_t source;
- int32_t action;
- int32_t flags;
- int32_t metaState;
- int32_t buttonState;
- int32_t edgeFlags;
- float xPrecision;
- float yPrecision;
- nsecs_t downTime;
- int32_t displayId;
- uint32_t pointerCount;
- PointerProperties pointerProperties[MAX_POINTERS];
- PointerCoords pointerCoords[MAX_POINTERS];
-
- MotionEntry(nsecs_t eventTime,
- int32_t deviceId, uint32_t source, uint32_t policyFlags,
- int32_t action, int32_t flags,
- int32_t metaState, int32_t buttonState, int32_t edgeFlags,
- float xPrecision, float yPrecision,
- nsecs_t downTime, int32_t displayId, uint32_t pointerCount,
- const PointerProperties* pointerProperties, const PointerCoords* pointerCoords);
- virtual void appendDescription(String8& msg) const;
-
- protected:
- virtual ~MotionEntry();
- };
-
- // Tracks the progress of dispatching a particular event to a particular connection.
- struct DispatchEntry : Link<DispatchEntry> {
- const uint32_t seq; // unique sequence number, never 0
-
- EventEntry* eventEntry; // the event to dispatch
- int32_t targetFlags;
- float xOffset;
- float yOffset;
- float scaleFactor;
- nsecs_t deliveryTime; // time when the event was actually delivered
-
- // Set to the resolved action and flags when the event is enqueued.
- int32_t resolvedAction;
- int32_t resolvedFlags;
-
- DispatchEntry(EventEntry* eventEntry,
- int32_t targetFlags, float xOffset, float yOffset, float scaleFactor);
- ~DispatchEntry();
-
- inline bool hasForegroundTarget() const {
- return targetFlags & InputTarget::FLAG_FOREGROUND;
- }
-
- inline bool isSplit() const {
- return targetFlags & InputTarget::FLAG_SPLIT;
- }
-
- private:
- static volatile int32_t sNextSeqAtomic;
-
- static uint32_t nextSeq();
- };
-
- // A command entry captures state and behavior for an action to be performed in the
- // dispatch loop after the initial processing has taken place. It is essentially
- // a kind of continuation used to postpone sensitive policy interactions to a point
- // in the dispatch loop where it is safe to release the lock (generally after finishing
- // the critical parts of the dispatch cycle).
- //
- // The special thing about commands is that they can voluntarily release and reacquire
- // the dispatcher lock at will. Initially when the command starts running, the
- // dispatcher lock is held. However, if the command needs to call into the policy to
- // do some work, it can release the lock, do the work, then reacquire the lock again
- // before returning.
- //
- // This mechanism is a bit clunky but it helps to preserve the invariant that the dispatch
- // never calls into the policy while holding its lock.
- //
- // Commands are implicitly 'LockedInterruptible'.
- struct CommandEntry;
- typedef void (InputDispatcher::*Command)(CommandEntry* commandEntry);
-
- class Connection;
- struct CommandEntry : Link<CommandEntry> {
- CommandEntry(Command command);
- ~CommandEntry();
-
- Command command;
-
- // parameters for the command (usage varies by command)
- sp<Connection> connection;
- nsecs_t eventTime;
- KeyEntry* keyEntry;
- sp<InputApplicationHandle> inputApplicationHandle;
- sp<InputWindowHandle> inputWindowHandle;
- String8 reason;
- int32_t userActivityEventType;
- uint32_t seq;
- bool handled;
- };
-
- // Generic queue implementation.
- template <typename T>
- struct Queue {
- T* head;
- T* tail;
-
- inline Queue() : head(NULL), tail(NULL) {
- }
-
- inline bool isEmpty() const {
- return !head;
- }
-
- inline void enqueueAtTail(T* entry) {
- entry->prev = tail;
- if (tail) {
- tail->next = entry;
- } else {
- head = entry;
- }
- entry->next = NULL;
- tail = entry;
- }
-
- inline void enqueueAtHead(T* entry) {
- entry->next = head;
- if (head) {
- head->prev = entry;
- } else {
- tail = entry;
- }
- entry->prev = NULL;
- head = entry;
- }
-
- inline void dequeue(T* entry) {
- if (entry->prev) {
- entry->prev->next = entry->next;
- } else {
- head = entry->next;
- }
- if (entry->next) {
- entry->next->prev = entry->prev;
- } else {
- tail = entry->prev;
- }
- }
-
- inline T* dequeueAtHead() {
- T* entry = head;
- head = entry->next;
- if (head) {
- head->prev = NULL;
- } else {
- tail = NULL;
- }
- return entry;
- }
-
- uint32_t count() const;
- };
-
- /* Specifies which events are to be canceled and why. */
- struct CancelationOptions {
- enum Mode {
- CANCEL_ALL_EVENTS = 0,
- CANCEL_POINTER_EVENTS = 1,
- CANCEL_NON_POINTER_EVENTS = 2,
- CANCEL_FALLBACK_EVENTS = 3,
- };
-
- // The criterion to use to determine which events should be canceled.
- Mode mode;
-
- // Descriptive reason for the cancelation.
- const char* reason;
-
- // The specific keycode of the key event to cancel, or -1 to cancel any key event.
- int32_t keyCode;
-
- // The specific device id of events to cancel, or -1 to cancel events from any device.
- int32_t deviceId;
-
- CancelationOptions(Mode mode, const char* reason) :
- mode(mode), reason(reason), keyCode(-1), deviceId(-1) { }
- };
-
- /* Tracks dispatched key and motion event state so that cancelation events can be
- * synthesized when events are dropped. */
- class InputState {
- public:
- InputState();
- ~InputState();
-
- // Returns true if there is no state to be canceled.
- bool isNeutral() const;
-
- // Returns true if the specified source is known to have received a hover enter
- // motion event.
- bool isHovering(int32_t deviceId, uint32_t source, int32_t displayId) const;
-
- // Records tracking information for a key event that has just been published.
- // Returns true if the event should be delivered, false if it is inconsistent
- // and should be skipped.
- bool trackKey(const KeyEntry* entry, int32_t action, int32_t flags);
-
- // Records tracking information for a motion event that has just been published.
- // Returns true if the event should be delivered, false if it is inconsistent
- // and should be skipped.
- bool trackMotion(const MotionEntry* entry, int32_t action, int32_t flags);
-
- // Synthesizes cancelation events for the current state and resets the tracked state.
- void synthesizeCancelationEvents(nsecs_t currentTime,
- Vector<EventEntry*>& outEvents, const CancelationOptions& options);
-
- // Clears the current state.
- void clear();
-
- // Copies pointer-related parts of the input state to another instance.
- void copyPointerStateTo(InputState& other) const;
-
- // Gets the fallback key associated with a keycode.
- // Returns -1 if none.
- // Returns AKEYCODE_UNKNOWN if we are only dispatching the unhandled key to the policy.
- int32_t getFallbackKey(int32_t originalKeyCode);
-
- // Sets the fallback key for a particular keycode.
- void setFallbackKey(int32_t originalKeyCode, int32_t fallbackKeyCode);
-
- // Removes the fallback key for a particular keycode.
- void removeFallbackKey(int32_t originalKeyCode);
-
- inline const KeyedVector<int32_t, int32_t>& getFallbackKeys() const {
- return mFallbackKeys;
- }
-
- private:
- struct KeyMemento {
- int32_t deviceId;
- uint32_t source;
- int32_t keyCode;
- int32_t scanCode;
- int32_t metaState;
- int32_t flags;
- nsecs_t downTime;
- uint32_t policyFlags;
- };
-
- struct MotionMemento {
- int32_t deviceId;
- uint32_t source;
- int32_t flags;
- float xPrecision;
- float yPrecision;
- nsecs_t downTime;
- int32_t displayId;
- uint32_t pointerCount;
- PointerProperties pointerProperties[MAX_POINTERS];
- PointerCoords pointerCoords[MAX_POINTERS];
- bool hovering;
- uint32_t policyFlags;
-
- void setPointers(const MotionEntry* entry);
- };
-
- Vector<KeyMemento> mKeyMementos;
- Vector<MotionMemento> mMotionMementos;
- KeyedVector<int32_t, int32_t> mFallbackKeys;
-
- ssize_t findKeyMemento(const KeyEntry* entry) const;
- ssize_t findMotionMemento(const MotionEntry* entry, bool hovering) const;
-
- void addKeyMemento(const KeyEntry* entry, int32_t flags);
- void addMotionMemento(const MotionEntry* entry, int32_t flags, bool hovering);
-
- static bool shouldCancelKey(const KeyMemento& memento,
- const CancelationOptions& options);
- static bool shouldCancelMotion(const MotionMemento& memento,
- const CancelationOptions& options);
- };
-
- /* Manages the dispatch state associated with a single input channel. */
- class Connection : public RefBase {
- protected:
- virtual ~Connection();
-
- public:
- enum Status {
- // Everything is peachy.
- STATUS_NORMAL,
- // An unrecoverable communication error has occurred.
- STATUS_BROKEN,
- // The input channel has been unregistered.
- STATUS_ZOMBIE
- };
-
- Status status;
- sp<InputChannel> inputChannel; // never null
- sp<InputWindowHandle> inputWindowHandle; // may be null
- bool monitor;
- InputPublisher inputPublisher;
- InputState inputState;
-
- // True if the socket is full and no further events can be published until
- // the application consumes some of the input.
- bool inputPublisherBlocked;
-
- // Queue of events that need to be published to the connection.
- Queue<DispatchEntry> outboundQueue;
-
- // Queue of events that have been published to the connection but that have not
- // yet received a "finished" response from the application.
- Queue<DispatchEntry> waitQueue;
-
- explicit Connection(const sp<InputChannel>& inputChannel,
- const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
-
- inline const char* getInputChannelName() const { return inputChannel->getName().string(); }
-
- const char* getWindowName() const;
- const char* getStatusLabel() const;
-
- DispatchEntry* findWaitQueueEntry(uint32_t seq);
- };
-
- enum DropReason {
- DROP_REASON_NOT_DROPPED = 0,
- DROP_REASON_POLICY = 1,
- DROP_REASON_APP_SWITCH = 2,
- DROP_REASON_DISABLED = 3,
- DROP_REASON_BLOCKED = 4,
- DROP_REASON_STALE = 5,
- };
-
- sp<InputDispatcherPolicyInterface> mPolicy;
- InputDispatcherConfiguration mConfig;
-
- Mutex mLock;
-
- Condition mDispatcherIsAliveCondition;
-
- sp<Looper> mLooper;
-
- EventEntry* mPendingEvent;
- Queue<EventEntry> mInboundQueue;
- Queue<EventEntry> mRecentQueue;
- Queue<CommandEntry> mCommandQueue;
-
- void dispatchOnceInnerLocked(nsecs_t* nextWakeupTime);
-
- // Enqueues an inbound event. Returns true if mLooper->wake() should be called.
- bool enqueueInboundEventLocked(EventEntry* entry);
-
- // Cleans up input state when dropping an inbound event.
- void dropInboundEventLocked(EventEntry* entry, DropReason dropReason);
-
- // Adds an event to a queue of recent events for debugging purposes.
- void addRecentEventLocked(EventEntry* entry);
-
- // App switch latency optimization.
- bool mAppSwitchSawKeyDown;
- nsecs_t mAppSwitchDueTime;
-
- static bool isAppSwitchKeyCode(int32_t keyCode);
- bool isAppSwitchKeyEventLocked(KeyEntry* keyEntry);
- bool isAppSwitchPendingLocked();
- void resetPendingAppSwitchLocked(bool handled);
-
- // Stale event latency optimization.
- static bool isStaleEventLocked(nsecs_t currentTime, EventEntry* entry);
-
- // Blocked event latency optimization. Drops old events when the user intends
- // to transfer focus to a new application.
- EventEntry* mNextUnblockedEvent;
-
- sp<InputWindowHandle> findTouchedWindowAtLocked(int32_t displayId, int32_t x, int32_t y);
-
- // All registered connections mapped by channel file descriptor.
- KeyedVector<int, sp<Connection> > mConnectionsByFd;
-
- ssize_t getConnectionIndexLocked(const sp<InputChannel>& inputChannel);
-
- // Input channels that will receive a copy of all input events.
- Vector<sp<InputChannel> > mMonitoringChannels;
-
- // Event injection and synchronization.
- Condition mInjectionResultAvailableCondition;
- bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid);
- void setInjectionResultLocked(EventEntry* entry, int32_t injectionResult);
-
- Condition mInjectionSyncFinishedCondition;
- void incrementPendingForegroundDispatchesLocked(EventEntry* entry);
- void decrementPendingForegroundDispatchesLocked(EventEntry* entry);
-
- // Key repeat tracking.
- struct KeyRepeatState {
- KeyEntry* lastKeyEntry; // or null if no repeat
- nsecs_t nextRepeatTime;
- } mKeyRepeatState;
-
- void resetKeyRepeatLocked();
- KeyEntry* synthesizeKeyRepeatLocked(nsecs_t currentTime);
-
- // Deferred command processing.
- bool haveCommandsLocked() const;
- bool runCommandsLockedInterruptible();
- CommandEntry* postCommandLocked(Command command);
-
- // Input filter processing.
- bool shouldSendKeyToInputFilterLocked(const NotifyKeyArgs* args);
- bool shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args);
-
- // Inbound event processing.
- void drainInboundQueueLocked();
- void releasePendingEventLocked();
- void releaseInboundEventLocked(EventEntry* entry);
-
- // Dispatch state.
- bool mDispatchEnabled;
- bool mDispatchFrozen;
- bool mInputFilterEnabled;
-
- Vector<sp<InputWindowHandle> > mWindowHandles;
-
- sp<InputWindowHandle> getWindowHandleLocked(const sp<InputChannel>& inputChannel) const;
- bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const;
-
- // Focus tracking for keys, trackball, etc.
- sp<InputWindowHandle> mFocusedWindowHandle;
-
- // Focus tracking for touch.
- struct TouchedWindow {
- sp<InputWindowHandle> windowHandle;
- int32_t targetFlags;
- BitSet32 pointerIds; // zero unless target flag FLAG_SPLIT is set
- };
- struct TouchState {
- bool down;
- bool split;
- int32_t deviceId; // id of the device that is currently down, others are rejected
- uint32_t source; // source of the device that is current down, others are rejected
- int32_t displayId; // id to the display that currently has a touch, others are rejected
- Vector<TouchedWindow> windows;
-
- TouchState();
- ~TouchState();
- void reset();
- void copyFrom(const TouchState& other);
- void addOrUpdateWindow(const sp<InputWindowHandle>& windowHandle,
- int32_t targetFlags, BitSet32 pointerIds);
- void removeWindow(const sp<InputWindowHandle>& windowHandle);
- void filterNonAsIsTouchWindows();
- sp<InputWindowHandle> getFirstForegroundWindowHandle() const;
- bool isSlippery() const;
- };
-
- TouchState mTouchState;
- TouchState mTempTouchState;
-
- // Focused application.
- sp<InputApplicationHandle> mFocusedApplicationHandle;
-
- // Dispatcher state at time of last ANR.
- String8 mLastANRState;
-
- // Dispatch inbound events.
- bool dispatchConfigurationChangedLocked(
- nsecs_t currentTime, ConfigurationChangedEntry* entry);
- bool dispatchDeviceResetLocked(
- nsecs_t currentTime, DeviceResetEntry* entry);
- bool dispatchKeyLocked(
- nsecs_t currentTime, KeyEntry* entry,
- DropReason* dropReason, nsecs_t* nextWakeupTime);
- bool dispatchMotionLocked(
- nsecs_t currentTime, MotionEntry* entry,
- DropReason* dropReason, nsecs_t* nextWakeupTime);
- void dispatchEventLocked(nsecs_t currentTime, EventEntry* entry,
- const Vector<InputTarget>& inputTargets);
-
- void logOutboundKeyDetailsLocked(const char* prefix, const KeyEntry* entry);
- void logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry);
-
- // Keeping track of ANR timeouts.
- enum InputTargetWaitCause {
- INPUT_TARGET_WAIT_CAUSE_NONE,
- INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY,
- INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY,
- };
-
- InputTargetWaitCause mInputTargetWaitCause;
- nsecs_t mInputTargetWaitStartTime;
- nsecs_t mInputTargetWaitTimeoutTime;
- bool mInputTargetWaitTimeoutExpired;
- sp<InputApplicationHandle> mInputTargetWaitApplicationHandle;
-
- // Contains the last window which received a hover event.
- sp<InputWindowHandle> mLastHoverWindowHandle;
-
- // Finding targets for input events.
- int32_t handleTargetsNotReadyLocked(nsecs_t currentTime, const EventEntry* entry,
- const sp<InputApplicationHandle>& applicationHandle,
- const sp<InputWindowHandle>& windowHandle,
- nsecs_t* nextWakeupTime, const char* reason);
- void resumeAfterTargetsNotReadyTimeoutLocked(nsecs_t newTimeout,
- const sp<InputChannel>& inputChannel);
- nsecs_t getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime);
- void resetANRTimeoutsLocked();
-
- int32_t findFocusedWindowTargetsLocked(nsecs_t currentTime, const EventEntry* entry,
- Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime);
- int32_t findTouchedWindowTargetsLocked(nsecs_t currentTime, const MotionEntry* entry,
- Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime,
- bool* outConflictingPointerActions);
-
- void addWindowTargetLocked(const sp<InputWindowHandle>& windowHandle,
- int32_t targetFlags, BitSet32 pointerIds, Vector<InputTarget>& inputTargets);
- void addMonitoringTargetsLocked(Vector<InputTarget>& inputTargets);
-
- void pokeUserActivityLocked(const EventEntry* eventEntry);
- bool checkInjectionPermission(const sp<InputWindowHandle>& windowHandle,
- const InjectionState* injectionState);
- bool isWindowObscuredAtPointLocked(const sp<InputWindowHandle>& windowHandle,
- int32_t x, int32_t y) const;
- bool isWindowReadyForMoreInputLocked(nsecs_t currentTime,
- const sp<InputWindowHandle>& windowHandle, const EventEntry* eventEntry);
- String8 getApplicationWindowLabelLocked(const sp<InputApplicationHandle>& applicationHandle,
- const sp<InputWindowHandle>& windowHandle);
-
- // Manage the dispatch cycle for a single connection.
- // These methods are deliberately not Interruptible because doing all of the work
- // with the mutex held makes it easier to ensure that connection invariants are maintained.
- // If needed, the methods post commands to run later once the critical bits are done.
- void prepareDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
- EventEntry* eventEntry, const InputTarget* inputTarget);
- void enqueueDispatchEntriesLocked(nsecs_t currentTime, const sp<Connection>& connection,
- EventEntry* eventEntry, const InputTarget* inputTarget);
- void enqueueDispatchEntryLocked(const sp<Connection>& connection,
- EventEntry* eventEntry, const InputTarget* inputTarget, int32_t dispatchMode);
- void startDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection);
- void finishDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
- uint32_t seq, bool handled);
- void abortBrokenDispatchCycleLocked(nsecs_t currentTime, const sp<Connection>& connection,
- bool notify);
- void drainDispatchQueueLocked(Queue<DispatchEntry>* queue);
- void releaseDispatchEntryLocked(DispatchEntry* dispatchEntry);
- static int handleReceiveCallback(int fd, int events, void* data);
-
- void synthesizeCancelationEventsForAllConnectionsLocked(
- const CancelationOptions& options);
- void synthesizeCancelationEventsForInputChannelLocked(const sp<InputChannel>& channel,
- const CancelationOptions& options);
- void synthesizeCancelationEventsForConnectionLocked(const sp<Connection>& connection,
- const CancelationOptions& options);
-
- // Splitting motion events across windows.
- MotionEntry* splitMotionEvent(const MotionEntry* originalMotionEntry, BitSet32 pointerIds);
-
- // Reset and drop everything the dispatcher is doing.
- void resetAndDropEverythingLocked(const char* reason);
-
- // Dump state.
- void dumpDispatchStateLocked(String8& dump);
- void logDispatchStateLocked();
-
- // Registration.
- void removeMonitorChannelLocked(const sp<InputChannel>& inputChannel);
- status_t unregisterInputChannelLocked(const sp<InputChannel>& inputChannel, bool notify);
-
- // Add or remove a connection to the mActiveConnections vector.
- void activateConnectionLocked(Connection* connection);
- void deactivateConnectionLocked(Connection* connection);
-
- // Interesting events that we might like to log or tell the framework about.
- void onDispatchCycleFinishedLocked(
- nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled);
- void onDispatchCycleBrokenLocked(
- nsecs_t currentTime, const sp<Connection>& connection);
- void onANRLocked(
- nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
- const sp<InputWindowHandle>& windowHandle,
- nsecs_t eventTime, nsecs_t waitStartTime, const char* reason);
-
- // Outbound policy interactions.
- void doNotifyConfigurationChangedInterruptible(CommandEntry* commandEntry);
- void doNotifyInputChannelBrokenLockedInterruptible(CommandEntry* commandEntry);
- void doNotifyANRLockedInterruptible(CommandEntry* commandEntry);
- void doInterceptKeyBeforeDispatchingLockedInterruptible(CommandEntry* commandEntry);
- void doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry);
- bool afterKeyEventLockedInterruptible(const sp<Connection>& connection,
- DispatchEntry* dispatchEntry, KeyEntry* keyEntry, bool handled);
- bool afterMotionEventLockedInterruptible(const sp<Connection>& connection,
- DispatchEntry* dispatchEntry, MotionEntry* motionEntry, bool handled);
- void doPokeUserActivityLockedInterruptible(CommandEntry* commandEntry);
- void initializeKeyEvent(KeyEvent* event, const KeyEntry* entry);
-
- // Statistics gathering.
- void updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
- int32_t injectionResult, nsecs_t timeSpentWaitingForApplication);
- void traceInboundQueueLengthLocked();
- void traceOutboundQueueLengthLocked(const sp<Connection>& connection);
- void traceWaitQueueLengthLocked(const sp<Connection>& connection);
-};
-
-/* Enqueues and dispatches input events, endlessly. */
-class InputDispatcherThread : public Thread {
-public:
- explicit InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher);
- ~InputDispatcherThread();
-
-private:
- virtual bool threadLoop();
-
- sp<InputDispatcherInterface> mDispatcher;
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_DISPATCHER_H
diff --git a/libs/input/InputListener.cpp b/libs/input/InputListener.cpp
deleted file mode 100644
index 85bb0ed..0000000
--- a/libs/input/InputListener.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "InputListener"
-
-//#define LOG_NDEBUG 0
-
-#include "InputListener.h"
-
-#include <cutils/log.h>
-
-namespace android {
-
-// --- NotifyConfigurationChangedArgs ---
-
-NotifyConfigurationChangedArgs::NotifyConfigurationChangedArgs(nsecs_t eventTime) :
- eventTime(eventTime) {
-}
-
-NotifyConfigurationChangedArgs::NotifyConfigurationChangedArgs(
- const NotifyConfigurationChangedArgs& other) :
- eventTime(other.eventTime) {
-}
-
-void NotifyConfigurationChangedArgs::notify(const sp<InputListenerInterface>& listener) const {
- listener->notifyConfigurationChanged(this);
-}
-
-
-// --- NotifyKeyArgs ---
-
-NotifyKeyArgs::NotifyKeyArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source,
- uint32_t policyFlags,
- int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode,
- int32_t metaState, nsecs_t downTime) :
- eventTime(eventTime), deviceId(deviceId), source(source), policyFlags(policyFlags),
- action(action), flags(flags), keyCode(keyCode), scanCode(scanCode),
- metaState(metaState), downTime(downTime) {
-}
-
-NotifyKeyArgs::NotifyKeyArgs(const NotifyKeyArgs& other) :
- eventTime(other.eventTime), deviceId(other.deviceId), source(other.source),
- policyFlags(other.policyFlags),
- action(other.action), flags(other.flags),
- keyCode(other.keyCode), scanCode(other.scanCode),
- metaState(other.metaState), downTime(other.downTime) {
-}
-
-void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const {
- listener->notifyKey(this);
-}
-
-
-// --- NotifyMotionArgs ---
-
-NotifyMotionArgs::NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source,
- uint32_t policyFlags,
- int32_t action, int32_t flags, int32_t metaState, int32_t buttonState,
- int32_t edgeFlags, int32_t displayId, uint32_t pointerCount,
- const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
- float xPrecision, float yPrecision, nsecs_t downTime) :
- eventTime(eventTime), deviceId(deviceId), source(source), policyFlags(policyFlags),
- action(action), flags(flags), metaState(metaState), buttonState(buttonState),
- edgeFlags(edgeFlags), displayId(displayId), pointerCount(pointerCount),
- xPrecision(xPrecision), yPrecision(yPrecision), downTime(downTime) {
- for (uint32_t i = 0; i < pointerCount; i++) {
- this->pointerProperties[i].copyFrom(pointerProperties[i]);
- this->pointerCoords[i].copyFrom(pointerCoords[i]);
- }
-}
-
-NotifyMotionArgs::NotifyMotionArgs(const NotifyMotionArgs& other) :
- eventTime(other.eventTime), deviceId(other.deviceId), source(other.source),
- policyFlags(other.policyFlags),
- action(other.action), flags(other.flags),
- metaState(other.metaState), buttonState(other.buttonState),
- edgeFlags(other.edgeFlags), displayId(other.displayId),
- pointerCount(other.pointerCount),
- xPrecision(other.xPrecision), yPrecision(other.yPrecision), downTime(other.downTime) {
- for (uint32_t i = 0; i < pointerCount; i++) {
- pointerProperties[i].copyFrom(other.pointerProperties[i]);
- pointerCoords[i].copyFrom(other.pointerCoords[i]);
- }
-}
-
-void NotifyMotionArgs::notify(const sp<InputListenerInterface>& listener) const {
- listener->notifyMotion(this);
-}
-
-
-// --- NotifySwitchArgs ---
-
-NotifySwitchArgs::NotifySwitchArgs(nsecs_t eventTime, uint32_t policyFlags,
- uint32_t switchValues, uint32_t switchMask) :
- eventTime(eventTime), policyFlags(policyFlags),
- switchValues(switchValues), switchMask(switchMask) {
-}
-
-NotifySwitchArgs::NotifySwitchArgs(const NotifySwitchArgs& other) :
- eventTime(other.eventTime), policyFlags(other.policyFlags),
- switchValues(other.switchValues), switchMask(other.switchMask) {
-}
-
-void NotifySwitchArgs::notify(const sp<InputListenerInterface>& listener) const {
- listener->notifySwitch(this);
-}
-
-
-// --- NotifyDeviceResetArgs ---
-
-NotifyDeviceResetArgs::NotifyDeviceResetArgs(nsecs_t eventTime, int32_t deviceId) :
- eventTime(eventTime), deviceId(deviceId) {
-}
-
-NotifyDeviceResetArgs::NotifyDeviceResetArgs(const NotifyDeviceResetArgs& other) :
- eventTime(other.eventTime), deviceId(other.deviceId) {
-}
-
-void NotifyDeviceResetArgs::notify(const sp<InputListenerInterface>& listener) const {
- listener->notifyDeviceReset(this);
-}
-
-
-// --- QueuedInputListener ---
-
-QueuedInputListener::QueuedInputListener(const sp<InputListenerInterface>& innerListener) :
- mInnerListener(innerListener) {
-}
-
-QueuedInputListener::~QueuedInputListener() {
- size_t count = mArgsQueue.size();
- for (size_t i = 0; i < count; i++) {
- delete mArgsQueue[i];
- }
-}
-
-void QueuedInputListener::notifyConfigurationChanged(
- const NotifyConfigurationChangedArgs* args) {
- mArgsQueue.push(new NotifyConfigurationChangedArgs(*args));
-}
-
-void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
- mArgsQueue.push(new NotifyKeyArgs(*args));
-}
-
-void QueuedInputListener::notifyMotion(const NotifyMotionArgs* args) {
- mArgsQueue.push(new NotifyMotionArgs(*args));
-}
-
-void QueuedInputListener::notifySwitch(const NotifySwitchArgs* args) {
- mArgsQueue.push(new NotifySwitchArgs(*args));
-}
-
-void QueuedInputListener::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
- mArgsQueue.push(new NotifyDeviceResetArgs(*args));
-}
-
-void QueuedInputListener::flush() {
- size_t count = mArgsQueue.size();
- for (size_t i = 0; i < count; i++) {
- NotifyArgs* args = mArgsQueue[i];
- args->notify(mInnerListener);
- delete args;
- }
- mArgsQueue.clear();
-}
-
-
-} // namespace android
diff --git a/libs/input/InputListener.h b/libs/input/InputListener.h
deleted file mode 100644
index 78ae10f..0000000
--- a/libs/input/InputListener.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_LISTENER_H
-#define _UI_INPUT_LISTENER_H
-
-#include <input/Input.h>
-#include <utils/RefBase.h>
-#include <utils/Vector.h>
-
-namespace android {
-
-class InputListenerInterface;
-
-
-/* Superclass of all input event argument objects */
-struct NotifyArgs {
- virtual ~NotifyArgs() { }
-
- virtual void notify(const sp<InputListenerInterface>& listener) const = 0;
-};
-
-
-/* Describes a configuration change event. */
-struct NotifyConfigurationChangedArgs : public NotifyArgs {
- nsecs_t eventTime;
-
- inline NotifyConfigurationChangedArgs() { }
-
- NotifyConfigurationChangedArgs(nsecs_t eventTime);
-
- NotifyConfigurationChangedArgs(const NotifyConfigurationChangedArgs& other);
-
- virtual ~NotifyConfigurationChangedArgs() { }
-
- virtual void notify(const sp<InputListenerInterface>& listener) const;
-};
-
-
-/* Describes a key event. */
-struct NotifyKeyArgs : public NotifyArgs {
- nsecs_t eventTime;
- int32_t deviceId;
- uint32_t source;
- uint32_t policyFlags;
- int32_t action;
- int32_t flags;
- int32_t keyCode;
- int32_t scanCode;
- int32_t metaState;
- nsecs_t downTime;
-
- inline NotifyKeyArgs() { }
-
- NotifyKeyArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, uint32_t policyFlags,
- int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode,
- int32_t metaState, nsecs_t downTime);
-
- NotifyKeyArgs(const NotifyKeyArgs& other);
-
- virtual ~NotifyKeyArgs() { }
-
- virtual void notify(const sp<InputListenerInterface>& listener) const;
-};
-
-
-/* Describes a motion event. */
-struct NotifyMotionArgs : public NotifyArgs {
- nsecs_t eventTime;
- int32_t deviceId;
- uint32_t source;
- uint32_t policyFlags;
- int32_t action;
- int32_t flags;
- int32_t metaState;
- int32_t buttonState;
- int32_t edgeFlags;
- int32_t displayId;
- uint32_t pointerCount;
- PointerProperties pointerProperties[MAX_POINTERS];
- PointerCoords pointerCoords[MAX_POINTERS];
- float xPrecision;
- float yPrecision;
- nsecs_t downTime;
-
- inline NotifyMotionArgs() { }
-
- NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, uint32_t policyFlags,
- int32_t action, int32_t flags, int32_t metaState, int32_t buttonState,
- int32_t edgeFlags, int32_t displayId, uint32_t pointerCount,
- const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
- float xPrecision, float yPrecision, nsecs_t downTime);
-
- NotifyMotionArgs(const NotifyMotionArgs& other);
-
- virtual ~NotifyMotionArgs() { }
-
- virtual void notify(const sp<InputListenerInterface>& listener) const;
-};
-
-
-/* Describes a switch event. */
-struct NotifySwitchArgs : public NotifyArgs {
- nsecs_t eventTime;
- uint32_t policyFlags;
- uint32_t switchValues;
- uint32_t switchMask;
-
- inline NotifySwitchArgs() { }
-
- NotifySwitchArgs(nsecs_t eventTime, uint32_t policyFlags,
- uint32_t switchValues, uint32_t switchMask);
-
- NotifySwitchArgs(const NotifySwitchArgs& other);
-
- virtual ~NotifySwitchArgs() { }
-
- virtual void notify(const sp<InputListenerInterface>& listener) const;
-};
-
-
-/* Describes a device reset event, such as when a device is added,
- * reconfigured, or removed. */
-struct NotifyDeviceResetArgs : public NotifyArgs {
- nsecs_t eventTime;
- int32_t deviceId;
-
- inline NotifyDeviceResetArgs() { }
-
- NotifyDeviceResetArgs(nsecs_t eventTime, int32_t deviceId);
-
- NotifyDeviceResetArgs(const NotifyDeviceResetArgs& other);
-
- virtual ~NotifyDeviceResetArgs() { }
-
- virtual void notify(const sp<InputListenerInterface>& listener) const;
-};
-
-
-/*
- * The interface used by the InputReader to notify the InputListener about input events.
- */
-class InputListenerInterface : public virtual RefBase {
-protected:
- InputListenerInterface() { }
- virtual ~InputListenerInterface() { }
-
-public:
- virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) = 0;
- virtual void notifyKey(const NotifyKeyArgs* args) = 0;
- virtual void notifyMotion(const NotifyMotionArgs* args) = 0;
- virtual void notifySwitch(const NotifySwitchArgs* args) = 0;
- virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) = 0;
-};
-
-
-/*
- * An implementation of the listener interface that queues up and defers dispatch
- * of decoded events until flushed.
- */
-class QueuedInputListener : public InputListenerInterface {
-protected:
- virtual ~QueuedInputListener();
-
-public:
- QueuedInputListener(const sp<InputListenerInterface>& innerListener);
-
- virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args);
- virtual void notifyKey(const NotifyKeyArgs* args);
- virtual void notifyMotion(const NotifyMotionArgs* args);
- virtual void notifySwitch(const NotifySwitchArgs* args);
- virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args);
-
- void flush();
-
-private:
- sp<InputListenerInterface> mInnerListener;
- Vector<NotifyArgs*> mArgsQueue;
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_LISTENER_H
diff --git a/libs/input/InputManager.cpp b/libs/input/InputManager.cpp
deleted file mode 100644
index 6a6547b..0000000
--- a/libs/input/InputManager.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "InputManager"
-
-//#define LOG_NDEBUG 0
-
-#include "InputManager.h"
-
-#include <cutils/log.h>
-
-namespace android {
-
-InputManager::InputManager(
- const sp<EventHubInterface>& eventHub,
- const sp<InputReaderPolicyInterface>& readerPolicy,
- const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
- mDispatcher = new InputDispatcher(dispatcherPolicy);
- mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
- initialize();
-}
-
-InputManager::InputManager(
- const sp<InputReaderInterface>& reader,
- const sp<InputDispatcherInterface>& dispatcher) :
- mReader(reader),
- mDispatcher(dispatcher) {
- initialize();
-}
-
-InputManager::~InputManager() {
- stop();
-}
-
-void InputManager::initialize() {
- mReaderThread = new InputReaderThread(mReader);
- mDispatcherThread = new InputDispatcherThread(mDispatcher);
-}
-
-status_t InputManager::start() {
- status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
- if (result) {
- ALOGE("Could not start InputDispatcher thread due to error %d.", result);
- return result;
- }
-
- result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
- if (result) {
- ALOGE("Could not start InputReader thread due to error %d.", result);
-
- mDispatcherThread->requestExit();
- return result;
- }
-
- return OK;
-}
-
-status_t InputManager::stop() {
- status_t result = mReaderThread->requestExitAndWait();
- if (result) {
- ALOGW("Could not stop InputReader thread due to error %d.", result);
- }
-
- result = mDispatcherThread->requestExitAndWait();
- if (result) {
- ALOGW("Could not stop InputDispatcher thread due to error %d.", result);
- }
-
- return OK;
-}
-
-sp<InputReaderInterface> InputManager::getReader() {
- return mReader;
-}
-
-sp<InputDispatcherInterface> InputManager::getDispatcher() {
- return mDispatcher;
-}
-
-} // namespace android
diff --git a/libs/input/InputManager.h b/libs/input/InputManager.h
deleted file mode 100644
index a213b2d..0000000
--- a/libs/input/InputManager.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_MANAGER_H
-#define _UI_INPUT_MANAGER_H
-
-/**
- * Native input manager.
- */
-
-#include "EventHub.h"
-#include "InputReader.h"
-#include "InputDispatcher.h"
-
-#include <input/Input.h>
-#include <input/InputTransport.h>
-#include <utils/Errors.h>
-#include <utils/Vector.h>
-#include <utils/Timers.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-
-namespace android {
-
-/*
- * The input manager is the core of the system event processing.
- *
- * The input manager uses two threads.
- *
- * 1. The InputReaderThread (called "InputReader") reads and preprocesses raw input events,
- * applies policy, and posts messages to a queue managed by the DispatcherThread.
- * 2. The InputDispatcherThread (called "InputDispatcher") thread waits for new events on the
- * queue and asynchronously dispatches them to applications.
- *
- * By design, the InputReaderThread class and InputDispatcherThread class do not share any
- * internal state. Moreover, all communication is done one way from the InputReaderThread
- * into the InputDispatcherThread and never the reverse. Both classes may interact with the
- * InputDispatchPolicy, however.
- *
- * The InputManager class never makes any calls into Java itself. Instead, the
- * InputDispatchPolicy is responsible for performing all external interactions with the
- * system, including calling DVM services.
- */
-class InputManagerInterface : public virtual RefBase {
-protected:
- InputManagerInterface() { }
- virtual ~InputManagerInterface() { }
-
-public:
- /* Starts the input manager threads. */
- virtual status_t start() = 0;
-
- /* Stops the input manager threads and waits for them to exit. */
- virtual status_t stop() = 0;
-
- /* Gets the input reader. */
- virtual sp<InputReaderInterface> getReader() = 0;
-
- /* Gets the input dispatcher. */
- virtual sp<InputDispatcherInterface> getDispatcher() = 0;
-};
-
-class InputManager : public InputManagerInterface {
-protected:
- virtual ~InputManager();
-
-public:
- InputManager(
- const sp<EventHubInterface>& eventHub,
- const sp<InputReaderPolicyInterface>& readerPolicy,
- const sp<InputDispatcherPolicyInterface>& dispatcherPolicy);
-
- // (used for testing purposes)
- InputManager(
- const sp<InputReaderInterface>& reader,
- const sp<InputDispatcherInterface>& dispatcher);
-
- virtual status_t start();
- virtual status_t stop();
-
- virtual sp<InputReaderInterface> getReader();
- virtual sp<InputDispatcherInterface> getDispatcher();
-
-private:
- sp<InputReaderInterface> mReader;
- sp<InputReaderThread> mReaderThread;
-
- sp<InputDispatcherInterface> mDispatcher;
- sp<InputDispatcherThread> mDispatcherThread;
-
- void initialize();
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_MANAGER_H
diff --git a/libs/input/InputReader.cpp b/libs/input/InputReader.cpp
deleted file mode 100644
index 94e2a80..0000000
--- a/libs/input/InputReader.cpp
+++ /dev/null
@@ -1,6530 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "InputReader"
-
-//#define LOG_NDEBUG 0
-
-// Log debug messages for each raw event received from the EventHub.
-#define DEBUG_RAW_EVENTS 0
-
-// Log debug messages about touch screen filtering hacks.
-#define DEBUG_HACKS 0
-
-// Log debug messages about virtual key processing.
-#define DEBUG_VIRTUAL_KEYS 0
-
-// Log debug messages about pointers.
-#define DEBUG_POINTERS 0
-
-// Log debug messages about pointer assignment calculations.
-#define DEBUG_POINTER_ASSIGNMENT 0
-
-// Log debug messages about gesture detection.
-#define DEBUG_GESTURES 0
-
-// Log debug messages about the vibrator.
-#define DEBUG_VIBRATOR 0
-
-#include "InputReader.h"
-
-#include <cutils/log.h>
-#include <input/Keyboard.h>
-#include <input/VirtualKeyMap.h>
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <limits.h>
-#include <math.h>
-
-#define INDENT " "
-#define INDENT2 " "
-#define INDENT3 " "
-#define INDENT4 " "
-#define INDENT5 " "
-
-namespace android {
-
-// --- Constants ---
-
-// Maximum number of slots supported when using the slot-based Multitouch Protocol B.
-static const size_t MAX_SLOTS = 32;
-
-// --- Static Functions ---
-
-template<typename T>
-inline static T abs(const T& value) {
- return value < 0 ? - value : value;
-}
-
-template<typename T>
-inline static T min(const T& a, const T& b) {
- return a < b ? a : b;
-}
-
-template<typename T>
-inline static void swap(T& a, T& b) {
- T temp = a;
- a = b;
- b = temp;
-}
-
-inline static float avg(float x, float y) {
- return (x + y) / 2;
-}
-
-inline static float distance(float x1, float y1, float x2, float y2) {
- return hypotf(x1 - x2, y1 - y2);
-}
-
-inline static int32_t signExtendNybble(int32_t value) {
- return value >= 8 ? value - 16 : value;
-}
-
-static inline const char* toString(bool value) {
- return value ? "true" : "false";
-}
-
-static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation,
- const int32_t map[][4], size_t mapSize) {
- if (orientation != DISPLAY_ORIENTATION_0) {
- for (size_t i = 0; i < mapSize; i++) {
- if (value == map[i][0]) {
- return map[i][orientation];
- }
- }
- }
- return value;
-}
-
-static const int32_t keyCodeRotationMap[][4] = {
- // key codes enumerated counter-clockwise with the original (unrotated) key first
- // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
- { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
- { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
- { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
- { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
-};
-static const size_t keyCodeRotationMapSize =
- sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
-
-static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
- return rotateValueUsingRotationMap(keyCode, orientation,
- keyCodeRotationMap, keyCodeRotationMapSize);
-}
-
-static void rotateDelta(int32_t orientation, float* deltaX, float* deltaY) {
- float temp;
- switch (orientation) {
- case DISPLAY_ORIENTATION_90:
- temp = *deltaX;
- *deltaX = *deltaY;
- *deltaY = -temp;
- break;
-
- case DISPLAY_ORIENTATION_180:
- *deltaX = -*deltaX;
- *deltaY = -*deltaY;
- break;
-
- case DISPLAY_ORIENTATION_270:
- temp = *deltaX;
- *deltaX = -*deltaY;
- *deltaY = temp;
- break;
- }
-}
-
-static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
- return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
-}
-
-// Returns true if the pointer should be reported as being down given the specified
-// button states. This determines whether the event is reported as a touch event.
-static bool isPointerDown(int32_t buttonState) {
- return buttonState &
- (AMOTION_EVENT_BUTTON_PRIMARY | AMOTION_EVENT_BUTTON_SECONDARY
- | AMOTION_EVENT_BUTTON_TERTIARY);
-}
-
-static float calculateCommonVector(float a, float b) {
- if (a > 0 && b > 0) {
- return a < b ? a : b;
- } else if (a < 0 && b < 0) {
- return a > b ? a : b;
- } else {
- return 0;
- }
-}
-
-static void synthesizeButtonKey(InputReaderContext* context, int32_t action,
- nsecs_t when, int32_t deviceId, uint32_t source,
- uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState,
- int32_t buttonState, int32_t keyCode) {
- if (
- (action == AKEY_EVENT_ACTION_DOWN
- && !(lastButtonState & buttonState)
- && (currentButtonState & buttonState))
- || (action == AKEY_EVENT_ACTION_UP
- && (lastButtonState & buttonState)
- && !(currentButtonState & buttonState))) {
- NotifyKeyArgs args(when, deviceId, source, policyFlags,
- action, 0, keyCode, 0, context->getGlobalMetaState(), when);
- context->getListener()->notifyKey(&args);
- }
-}
-
-static void synthesizeButtonKeys(InputReaderContext* context, int32_t action,
- nsecs_t when, int32_t deviceId, uint32_t source,
- uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState) {
- synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
- lastButtonState, currentButtonState,
- AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK);
- synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
- lastButtonState, currentButtonState,
- AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD);
-}
-
-
-// --- InputReaderConfiguration ---
-
-bool InputReaderConfiguration::getDisplayInfo(bool external, DisplayViewport* outViewport) const {
- const DisplayViewport& viewport = external ? mExternalDisplay : mInternalDisplay;
- if (viewport.displayId >= 0) {
- *outViewport = viewport;
- return true;
- }
- return false;
-}
-
-void InputReaderConfiguration::setDisplayInfo(bool external, const DisplayViewport& viewport) {
- DisplayViewport& v = external ? mExternalDisplay : mInternalDisplay;
- v = viewport;
-}
-
-
-// --- InputReader ---
-
-InputReader::InputReader(const sp<EventHubInterface>& eventHub,
- const sp<InputReaderPolicyInterface>& policy,
- const sp<InputListenerInterface>& listener) :
- mContext(this), mEventHub(eventHub), mPolicy(policy),
- mGlobalMetaState(0), mGeneration(1),
- mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
- mConfigurationChangesToRefresh(0) {
- mQueuedListener = new QueuedInputListener(listener);
-
- { // acquire lock
- AutoMutex _l(mLock);
-
- refreshConfigurationLocked(0);
- updateGlobalMetaStateLocked();
- } // release lock
-}
-
-InputReader::~InputReader() {
- for (size_t i = 0; i < mDevices.size(); i++) {
- delete mDevices.valueAt(i);
- }
-}
-
-void InputReader::loopOnce() {
- int32_t oldGeneration;
- int32_t timeoutMillis;
- bool inputDevicesChanged = false;
- Vector<InputDeviceInfo> inputDevices;
- { // acquire lock
- AutoMutex _l(mLock);
-
- oldGeneration = mGeneration;
- timeoutMillis = -1;
-
- uint32_t changes = mConfigurationChangesToRefresh;
- if (changes) {
- mConfigurationChangesToRefresh = 0;
- timeoutMillis = 0;
- refreshConfigurationLocked(changes);
- } else if (mNextTimeout != LLONG_MAX) {
- nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
- timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
- }
- } // release lock
-
- size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
-
- { // acquire lock
- AutoMutex _l(mLock);
- mReaderIsAliveCondition.broadcast();
-
- if (count) {
- processEventsLocked(mEventBuffer, count);
- }
-
- if (mNextTimeout != LLONG_MAX) {
- nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
- if (now >= mNextTimeout) {
-#if DEBUG_RAW_EVENTS
- ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
-#endif
- mNextTimeout = LLONG_MAX;
- timeoutExpiredLocked(now);
- }
- }
-
- if (oldGeneration != mGeneration) {
- inputDevicesChanged = true;
- getInputDevicesLocked(inputDevices);
- }
- } // release lock
-
- // Send out a message that the describes the changed input devices.
- if (inputDevicesChanged) {
- mPolicy->notifyInputDevicesChanged(inputDevices);
- }
-
- // Flush queued events out to the listener.
- // This must happen outside of the lock because the listener could potentially call
- // back into the InputReader's methods, such as getScanCodeState, or become blocked
- // on another thread similarly waiting to acquire the InputReader lock thereby
- // resulting in a deadlock. This situation is actually quite plausible because the
- // listener is actually the input dispatcher, which calls into the window manager,
- // which occasionally calls into the input reader.
- mQueuedListener->flush();
-}
-
-void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
- for (const RawEvent* rawEvent = rawEvents; count;) {
- int32_t type = rawEvent->type;
- size_t batchSize = 1;
- if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
- int32_t deviceId = rawEvent->deviceId;
- while (batchSize < count) {
- if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
- || rawEvent[batchSize].deviceId != deviceId) {
- break;
- }
- batchSize += 1;
- }
-#if DEBUG_RAW_EVENTS
- ALOGD("BatchSize: %d Count: %d", batchSize, count);
-#endif
- processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
- } else {
- switch (rawEvent->type) {
- case EventHubInterface::DEVICE_ADDED:
- addDeviceLocked(rawEvent->when, rawEvent->deviceId);
- break;
- case EventHubInterface::DEVICE_REMOVED:
- removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
- break;
- case EventHubInterface::FINISHED_DEVICE_SCAN:
- handleConfigurationChangedLocked(rawEvent->when);
- break;
- default:
- ALOG_ASSERT(false); // can't happen
- break;
- }
- }
- count -= batchSize;
- rawEvent += batchSize;
- }
-}
-
-void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex >= 0) {
- ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
- return;
- }
-
- InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
- uint32_t classes = mEventHub->getDeviceClasses(deviceId);
- int32_t controllerNumber = mEventHub->getDeviceControllerNumber(deviceId);
-
- InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);
- device->configure(when, &mConfig, 0);
- device->reset(when);
-
- if (device->isIgnored()) {
- ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
- identifier.name.string());
- } else {
- ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,
- identifier.name.string(), device->getSources());
- }
-
- mDevices.add(deviceId, device);
- bumpGenerationLocked();
-}
-
-void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
- InputDevice* device = NULL;
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex < 0) {
- ALOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
- return;
- }
-
- device = mDevices.valueAt(deviceIndex);
- mDevices.removeItemsAt(deviceIndex, 1);
- bumpGenerationLocked();
-
- if (device->isIgnored()) {
- ALOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
- device->getId(), device->getName().string());
- } else {
- ALOGI("Device removed: id=%d, name='%s', sources=0x%08x",
- device->getId(), device->getName().string(), device->getSources());
- }
-
- device->reset(when);
- delete device;
-}
-
-InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
- const InputDeviceIdentifier& identifier, uint32_t classes) {
- InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),
- controllerNumber, identifier, classes);
-
- // External devices.
- if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
- device->setExternal(true);
- }
-
- // Switch-like devices.
- if (classes & INPUT_DEVICE_CLASS_SWITCH) {
- device->addMapper(new SwitchInputMapper(device));
- }
-
- // Vibrator-like devices.
- if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {
- device->addMapper(new VibratorInputMapper(device));
- }
-
- // Keyboard-like devices.
- uint32_t keyboardSource = 0;
- int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
- if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
- keyboardSource |= AINPUT_SOURCE_KEYBOARD;
- }
- if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
- keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
- }
- if (classes & INPUT_DEVICE_CLASS_DPAD) {
- keyboardSource |= AINPUT_SOURCE_DPAD;
- }
- if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
- keyboardSource |= AINPUT_SOURCE_GAMEPAD;
- }
-
- if (keyboardSource != 0) {
- device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
- }
-
- // Cursor-like devices.
- if (classes & INPUT_DEVICE_CLASS_CURSOR) {
- device->addMapper(new CursorInputMapper(device));
- }
-
- // Touchscreens and touchpad devices.
- if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
- device->addMapper(new MultiTouchInputMapper(device));
- } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
- device->addMapper(new SingleTouchInputMapper(device));
- }
-
- // Joystick-like devices.
- if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
- device->addMapper(new JoystickInputMapper(device));
- }
-
- return device;
-}
-
-void InputReader::processEventsForDeviceLocked(int32_t deviceId,
- const RawEvent* rawEvents, size_t count) {
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex < 0) {
- ALOGW("Discarding event for unknown deviceId %d.", deviceId);
- return;
- }
-
- InputDevice* device = mDevices.valueAt(deviceIndex);
- if (device->isIgnored()) {
- //ALOGD("Discarding event for ignored deviceId %d.", deviceId);
- return;
- }
-
- device->process(rawEvents, count);
-}
-
-void InputReader::timeoutExpiredLocked(nsecs_t when) {
- for (size_t i = 0; i < mDevices.size(); i++) {
- InputDevice* device = mDevices.valueAt(i);
- if (!device->isIgnored()) {
- device->timeoutExpired(when);
- }
- }
-}
-
-void InputReader::handleConfigurationChangedLocked(nsecs_t when) {
- // Reset global meta state because it depends on the list of all configured devices.
- updateGlobalMetaStateLocked();
-
- // Enqueue configuration changed.
- NotifyConfigurationChangedArgs args(when);
- mQueuedListener->notifyConfigurationChanged(&args);
-}
-
-void InputReader::refreshConfigurationLocked(uint32_t changes) {
- mPolicy->getReaderConfiguration(&mConfig);
- mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
-
- if (changes) {
- ALOGI("Reconfiguring input devices. changes=0x%08x", changes);
- nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-
- if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) {
- mEventHub->requestReopenDevices();
- } else {
- for (size_t i = 0; i < mDevices.size(); i++) {
- InputDevice* device = mDevices.valueAt(i);
- device->configure(now, &mConfig, changes);
- }
- }
- }
-}
-
-void InputReader::updateGlobalMetaStateLocked() {
- mGlobalMetaState = 0;
-
- for (size_t i = 0; i < mDevices.size(); i++) {
- InputDevice* device = mDevices.valueAt(i);
- mGlobalMetaState |= device->getMetaState();
- }
-}
-
-int32_t InputReader::getGlobalMetaStateLocked() {
- return mGlobalMetaState;
-}
-
-void InputReader::disableVirtualKeysUntilLocked(nsecs_t time) {
- mDisableVirtualKeysTimeout = time;
-}
-
-bool InputReader::shouldDropVirtualKeyLocked(nsecs_t now,
- InputDevice* device, int32_t keyCode, int32_t scanCode) {
- if (now < mDisableVirtualKeysTimeout) {
- ALOGI("Dropping virtual key from device %s because virtual keys are "
- "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d",
- device->getName().string(),
- (mDisableVirtualKeysTimeout - now) * 0.000001,
- keyCode, scanCode);
- return true;
- } else {
- return false;
- }
-}
-
-void InputReader::fadePointerLocked() {
- for (size_t i = 0; i < mDevices.size(); i++) {
- InputDevice* device = mDevices.valueAt(i);
- device->fadePointer();
- }
-}
-
-void InputReader::requestTimeoutAtTimeLocked(nsecs_t when) {
- if (when < mNextTimeout) {
- mNextTimeout = when;
- mEventHub->wake();
- }
-}
-
-int32_t InputReader::bumpGenerationLocked() {
- return ++mGeneration;
-}
-
-void InputReader::getInputDevices(Vector<InputDeviceInfo>& outInputDevices) {
- AutoMutex _l(mLock);
- getInputDevicesLocked(outInputDevices);
-}
-
-void InputReader::getInputDevicesLocked(Vector<InputDeviceInfo>& outInputDevices) {
- outInputDevices.clear();
-
- size_t numDevices = mDevices.size();
- for (size_t i = 0; i < numDevices; i++) {
- InputDevice* device = mDevices.valueAt(i);
- if (!device->isIgnored()) {
- outInputDevices.push();
- device->getDeviceInfo(&outInputDevices.editTop());
- }
- }
-}
-
-int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
- int32_t keyCode) {
- AutoMutex _l(mLock);
-
- return getStateLocked(deviceId, sourceMask, keyCode, &InputDevice::getKeyCodeState);
-}
-
-int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
- int32_t scanCode) {
- AutoMutex _l(mLock);
-
- return getStateLocked(deviceId, sourceMask, scanCode, &InputDevice::getScanCodeState);
-}
-
-int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
- AutoMutex _l(mLock);
-
- return getStateLocked(deviceId, sourceMask, switchCode, &InputDevice::getSwitchState);
-}
-
-int32_t InputReader::getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code,
- GetStateFunc getStateFunc) {
- int32_t result = AKEY_STATE_UNKNOWN;
- if (deviceId >= 0) {
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex >= 0) {
- InputDevice* device = mDevices.valueAt(deviceIndex);
- if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
- result = (device->*getStateFunc)(sourceMask, code);
- }
- }
- } else {
- size_t numDevices = mDevices.size();
- for (size_t i = 0; i < numDevices; i++) {
- InputDevice* device = mDevices.valueAt(i);
- if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
- // If any device reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
- // value. Otherwise, return AKEY_STATE_UP as long as one device reports it.
- int32_t currentResult = (device->*getStateFunc)(sourceMask, code);
- if (currentResult >= AKEY_STATE_DOWN) {
- return currentResult;
- } else if (currentResult == AKEY_STATE_UP) {
- result = currentResult;
- }
- }
- }
- }
- return result;
-}
-
-bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
- size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
- AutoMutex _l(mLock);
-
- memset(outFlags, 0, numCodes);
- return markSupportedKeyCodesLocked(deviceId, sourceMask, numCodes, keyCodes, outFlags);
-}
-
-bool InputReader::markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask,
- size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
- bool result = false;
- if (deviceId >= 0) {
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex >= 0) {
- InputDevice* device = mDevices.valueAt(deviceIndex);
- if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
- result = device->markSupportedKeyCodes(sourceMask,
- numCodes, keyCodes, outFlags);
- }
- }
- } else {
- size_t numDevices = mDevices.size();
- for (size_t i = 0; i < numDevices; i++) {
- InputDevice* device = mDevices.valueAt(i);
- if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
- result |= device->markSupportedKeyCodes(sourceMask,
- numCodes, keyCodes, outFlags);
- }
- }
- }
- return result;
-}
-
-void InputReader::requestRefreshConfiguration(uint32_t changes) {
- AutoMutex _l(mLock);
-
- if (changes) {
- bool needWake = !mConfigurationChangesToRefresh;
- mConfigurationChangesToRefresh |= changes;
-
- if (needWake) {
- mEventHub->wake();
- }
- }
-}
-
-void InputReader::vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
- ssize_t repeat, int32_t token) {
- AutoMutex _l(mLock);
-
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex >= 0) {
- InputDevice* device = mDevices.valueAt(deviceIndex);
- device->vibrate(pattern, patternSize, repeat, token);
- }
-}
-
-void InputReader::cancelVibrate(int32_t deviceId, int32_t token) {
- AutoMutex _l(mLock);
-
- ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
- if (deviceIndex >= 0) {
- InputDevice* device = mDevices.valueAt(deviceIndex);
- device->cancelVibrate(token);
- }
-}
-
-void InputReader::dump(String8& dump) {
- AutoMutex _l(mLock);
-
- mEventHub->dump(dump);
- dump.append("\n");
-
- dump.append("Input Reader State:\n");
-
- for (size_t i = 0; i < mDevices.size(); i++) {
- mDevices.valueAt(i)->dump(dump);
- }
-
- dump.append(INDENT "Configuration:\n");
- dump.append(INDENT2 "ExcludedDeviceNames: [");
- for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
- if (i != 0) {
- dump.append(", ");
- }
- dump.append(mConfig.excludedDeviceNames.itemAt(i).string());
- }
- dump.append("]\n");
- dump.appendFormat(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
- mConfig.virtualKeyQuietTime * 0.000001f);
-
- dump.appendFormat(INDENT2 "PointerVelocityControlParameters: "
- "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
- mConfig.pointerVelocityControlParameters.scale,
- mConfig.pointerVelocityControlParameters.lowThreshold,
- mConfig.pointerVelocityControlParameters.highThreshold,
- mConfig.pointerVelocityControlParameters.acceleration);
-
- dump.appendFormat(INDENT2 "WheelVelocityControlParameters: "
- "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
- mConfig.wheelVelocityControlParameters.scale,
- mConfig.wheelVelocityControlParameters.lowThreshold,
- mConfig.wheelVelocityControlParameters.highThreshold,
- mConfig.wheelVelocityControlParameters.acceleration);
-
- dump.appendFormat(INDENT2 "PointerGesture:\n");
- dump.appendFormat(INDENT3 "Enabled: %s\n",
- toString(mConfig.pointerGesturesEnabled));
- dump.appendFormat(INDENT3 "QuietInterval: %0.1fms\n",
- mConfig.pointerGestureQuietInterval * 0.000001f);
- dump.appendFormat(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n",
- mConfig.pointerGestureDragMinSwitchSpeed);
- dump.appendFormat(INDENT3 "TapInterval: %0.1fms\n",
- mConfig.pointerGestureTapInterval * 0.000001f);
- dump.appendFormat(INDENT3 "TapDragInterval: %0.1fms\n",
- mConfig.pointerGestureTapDragInterval * 0.000001f);
- dump.appendFormat(INDENT3 "TapSlop: %0.1fpx\n",
- mConfig.pointerGestureTapSlop);
- dump.appendFormat(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
- mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
- dump.appendFormat(INDENT3 "MultitouchMinDistance: %0.1fpx\n",
- mConfig.pointerGestureMultitouchMinDistance);
- dump.appendFormat(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
- mConfig.pointerGestureSwipeTransitionAngleCosine);
- dump.appendFormat(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
- mConfig.pointerGestureSwipeMaxWidthRatio);
- dump.appendFormat(INDENT3 "MovementSpeedRatio: %0.1f\n",
- mConfig.pointerGestureMovementSpeedRatio);
- dump.appendFormat(INDENT3 "ZoomSpeedRatio: %0.1f\n",
- mConfig.pointerGestureZoomSpeedRatio);
-}
-
-void InputReader::monitor() {
- // Acquire and release the lock to ensure that the reader has not deadlocked.
- mLock.lock();
- mEventHub->wake();
- mReaderIsAliveCondition.wait(mLock);
- mLock.unlock();
-
- // Check the EventHub
- mEventHub->monitor();
-}
-
-
-// --- InputReader::ContextImpl ---
-
-InputReader::ContextImpl::ContextImpl(InputReader* reader) :
- mReader(reader) {
-}
-
-void InputReader::ContextImpl::updateGlobalMetaState() {
- // lock is already held by the input loop
- mReader->updateGlobalMetaStateLocked();
-}
-
-int32_t InputReader::ContextImpl::getGlobalMetaState() {
- // lock is already held by the input loop
- return mReader->getGlobalMetaStateLocked();
-}
-
-void InputReader::ContextImpl::disableVirtualKeysUntil(nsecs_t time) {
- // lock is already held by the input loop
- mReader->disableVirtualKeysUntilLocked(time);
-}
-
-bool InputReader::ContextImpl::shouldDropVirtualKey(nsecs_t now,
- InputDevice* device, int32_t keyCode, int32_t scanCode) {
- // lock is already held by the input loop
- return mReader->shouldDropVirtualKeyLocked(now, device, keyCode, scanCode);
-}
-
-void InputReader::ContextImpl::fadePointer() {
- // lock is already held by the input loop
- mReader->fadePointerLocked();
-}
-
-void InputReader::ContextImpl::requestTimeoutAtTime(nsecs_t when) {
- // lock is already held by the input loop
- mReader->requestTimeoutAtTimeLocked(when);
-}
-
-int32_t InputReader::ContextImpl::bumpGeneration() {
- // lock is already held by the input loop
- return mReader->bumpGenerationLocked();
-}
-
-InputReaderPolicyInterface* InputReader::ContextImpl::getPolicy() {
- return mReader->mPolicy.get();
-}
-
-InputListenerInterface* InputReader::ContextImpl::getListener() {
- return mReader->mQueuedListener.get();
-}
-
-EventHubInterface* InputReader::ContextImpl::getEventHub() {
- return mReader->mEventHub.get();
-}
-
-
-// --- InputReaderThread ---
-
-InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
- Thread(/*canCallJava*/ true), mReader(reader) {
-}
-
-InputReaderThread::~InputReaderThread() {
-}
-
-bool InputReaderThread::threadLoop() {
- mReader->loopOnce();
- return true;
-}
-
-
-// --- InputDevice ---
-
-InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
- int32_t controllerNumber, const InputDeviceIdentifier& identifier, uint32_t classes) :
- mContext(context), mId(id), mGeneration(generation), mControllerNumber(controllerNumber),
- mIdentifier(identifier), mClasses(classes),
- mSources(0), mIsExternal(false), mDropUntilNextSync(false) {
-}
-
-InputDevice::~InputDevice() {
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- delete mMappers[i];
- }
- mMappers.clear();
-}
-
-void InputDevice::dump(String8& dump) {
- InputDeviceInfo deviceInfo;
- getDeviceInfo(& deviceInfo);
-
- dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
- deviceInfo.getDisplayName().string());
- dump.appendFormat(INDENT2 "Generation: %d\n", mGeneration);
- dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
- dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
- dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
-
- const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
- if (!ranges.isEmpty()) {
- dump.append(INDENT2 "Motion Ranges:\n");
- for (size_t i = 0; i < ranges.size(); i++) {
- const InputDeviceInfo::MotionRange& range = ranges.itemAt(i);
- const char* label = getAxisLabel(range.axis);
- char name[32];
- if (label) {
- strncpy(name, label, sizeof(name));
- name[sizeof(name) - 1] = '\0';
- } else {
- snprintf(name, sizeof(name), "%d", range.axis);
- }
- dump.appendFormat(INDENT3 "%s: source=0x%08x, "
- "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, resolution=%0.3f\n",
- name, range.source, range.min, range.max, range.flat, range.fuzz,
- range.resolution);
- }
- }
-
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->dump(dump);
- }
-}
-
-void InputDevice::addMapper(InputMapper* mapper) {
- mMappers.add(mapper);
-}
-
-void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) {
- mSources = 0;
-
- if (!isIgnored()) {
- if (!changes) { // first time only
- mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
- }
-
- if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) {
- if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
- sp<KeyCharacterMap> keyboardLayout =
- mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier);
- if (mContext->getEventHub()->setKeyboardLayoutOverlay(mId, keyboardLayout)) {
- bumpGeneration();
- }
- }
- }
-
- if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) {
- if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
- String8 alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);
- if (mAlias != alias) {
- mAlias = alias;
- bumpGeneration();
- }
- }
- }
-
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->configure(when, config, changes);
- mSources |= mapper->getSources();
- }
- }
-}
-
-void InputDevice::reset(nsecs_t when) {
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->reset(when);
- }
-
- mContext->updateGlobalMetaState();
-
- notifyReset(when);
-}
-
-void InputDevice::process(const RawEvent* rawEvents, size_t count) {
- // Process all of the events in order for each mapper.
- // We cannot simply ask each mapper to process them in bulk because mappers may
- // have side-effects that must be interleaved. For example, joystick movement events and
- // gamepad button presses are handled by different mappers but they should be dispatched
- // in the order received.
- size_t numMappers = mMappers.size();
- for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
-#if DEBUG_RAW_EVENTS
- ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%lld",
- rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value,
- rawEvent->when);
-#endif
-
- if (mDropUntilNextSync) {
- if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
- mDropUntilNextSync = false;
-#if DEBUG_RAW_EVENTS
- ALOGD("Recovered from input event buffer overrun.");
-#endif
- } else {
-#if DEBUG_RAW_EVENTS
- ALOGD("Dropped input event while waiting for next input sync.");
-#endif
- }
- } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
- ALOGI("Detected input event buffer overrun for device %s.", getName().string());
- mDropUntilNextSync = true;
- reset(rawEvent->when);
- } else {
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->process(rawEvent);
- }
- }
- }
-}
-
-void InputDevice::timeoutExpired(nsecs_t when) {
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->timeoutExpired(when);
- }
-}
-
-void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
- outDeviceInfo->initialize(mId, mGeneration, mControllerNumber, mIdentifier, mAlias,
- mIsExternal);
-
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->populateDeviceInfo(outDeviceInfo);
- }
-}
-
-int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
- return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
-}
-
-int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
- return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
-}
-
-int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
- return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
-}
-
-int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
- int32_t result = AKEY_STATE_UNKNOWN;
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
- // If any mapper reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
- // value. Otherwise, return AKEY_STATE_UP as long as one mapper reports it.
- int32_t currentResult = (mapper->*getStateFunc)(sourceMask, code);
- if (currentResult >= AKEY_STATE_DOWN) {
- return currentResult;
- } else if (currentResult == AKEY_STATE_UP) {
- result = currentResult;
- }
- }
- }
- return result;
-}
-
-bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) {
- bool result = false;
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
- result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
- }
- }
- return result;
-}
-
-void InputDevice::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
- int32_t token) {
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->vibrate(pattern, patternSize, repeat, token);
- }
-}
-
-void InputDevice::cancelVibrate(int32_t token) {
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->cancelVibrate(token);
- }
-}
-
-int32_t InputDevice::getMetaState() {
- int32_t result = 0;
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- result |= mapper->getMetaState();
- }
- return result;
-}
-
-void InputDevice::fadePointer() {
- size_t numMappers = mMappers.size();
- for (size_t i = 0; i < numMappers; i++) {
- InputMapper* mapper = mMappers[i];
- mapper->fadePointer();
- }
-}
-
-void InputDevice::bumpGeneration() {
- mGeneration = mContext->bumpGeneration();
-}
-
-void InputDevice::notifyReset(nsecs_t when) {
- NotifyDeviceResetArgs args(when, mId);
- mContext->getListener()->notifyDeviceReset(&args);
-}
-
-
-// --- CursorButtonAccumulator ---
-
-CursorButtonAccumulator::CursorButtonAccumulator() {
- clearButtons();
-}
-
-void CursorButtonAccumulator::reset(InputDevice* device) {
- mBtnLeft = device->isKeyPressed(BTN_LEFT);
- mBtnRight = device->isKeyPressed(BTN_RIGHT);
- mBtnMiddle = device->isKeyPressed(BTN_MIDDLE);
- mBtnBack = device->isKeyPressed(BTN_BACK);
- mBtnSide = device->isKeyPressed(BTN_SIDE);
- mBtnForward = device->isKeyPressed(BTN_FORWARD);
- mBtnExtra = device->isKeyPressed(BTN_EXTRA);
- mBtnTask = device->isKeyPressed(BTN_TASK);
-}
-
-void CursorButtonAccumulator::clearButtons() {
- mBtnLeft = 0;
- mBtnRight = 0;
- mBtnMiddle = 0;
- mBtnBack = 0;
- mBtnSide = 0;
- mBtnForward = 0;
- mBtnExtra = 0;
- mBtnTask = 0;
-}
-
-void CursorButtonAccumulator::process(const RawEvent* rawEvent) {
- if (rawEvent->type == EV_KEY) {
- switch (rawEvent->code) {
- case BTN_LEFT:
- mBtnLeft = rawEvent->value;
- break;
- case BTN_RIGHT:
- mBtnRight = rawEvent->value;
- break;
- case BTN_MIDDLE:
- mBtnMiddle = rawEvent->value;
- break;
- case BTN_BACK:
- mBtnBack = rawEvent->value;
- break;
- case BTN_SIDE:
- mBtnSide = rawEvent->value;
- break;
- case BTN_FORWARD:
- mBtnForward = rawEvent->value;
- break;
- case BTN_EXTRA:
- mBtnExtra = rawEvent->value;
- break;
- case BTN_TASK:
- mBtnTask = rawEvent->value;
- break;
- }
- }
-}
-
-uint32_t CursorButtonAccumulator::getButtonState() const {
- uint32_t result = 0;
- if (mBtnLeft) {
- result |= AMOTION_EVENT_BUTTON_PRIMARY;
- }
- if (mBtnRight) {
- result |= AMOTION_EVENT_BUTTON_SECONDARY;
- }
- if (mBtnMiddle) {
- result |= AMOTION_EVENT_BUTTON_TERTIARY;
- }
- if (mBtnBack || mBtnSide) {
- result |= AMOTION_EVENT_BUTTON_BACK;
- }
- if (mBtnForward || mBtnExtra) {
- result |= AMOTION_EVENT_BUTTON_FORWARD;
- }
- return result;
-}
-
-
-// --- CursorMotionAccumulator ---
-
-CursorMotionAccumulator::CursorMotionAccumulator() {
- clearRelativeAxes();
-}
-
-void CursorMotionAccumulator::reset(InputDevice* device) {
- clearRelativeAxes();
-}
-
-void CursorMotionAccumulator::clearRelativeAxes() {
- mRelX = 0;
- mRelY = 0;
-}
-
-void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
- if (rawEvent->type == EV_REL) {
- switch (rawEvent->code) {
- case REL_X:
- mRelX = rawEvent->value;
- break;
- case REL_Y:
- mRelY = rawEvent->value;
- break;
- }
- }
-}
-
-void CursorMotionAccumulator::finishSync() {
- clearRelativeAxes();
-}
-
-
-// --- CursorScrollAccumulator ---
-
-CursorScrollAccumulator::CursorScrollAccumulator() :
- mHaveRelWheel(false), mHaveRelHWheel(false) {
- clearRelativeAxes();
-}
-
-void CursorScrollAccumulator::configure(InputDevice* device) {
- mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL);
- mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL);
-}
-
-void CursorScrollAccumulator::reset(InputDevice* device) {
- clearRelativeAxes();
-}
-
-void CursorScrollAccumulator::clearRelativeAxes() {
- mRelWheel = 0;
- mRelHWheel = 0;
-}
-
-void CursorScrollAccumulator::process(const RawEvent* rawEvent) {
- if (rawEvent->type == EV_REL) {
- switch (rawEvent->code) {
- case REL_WHEEL:
- mRelWheel = rawEvent->value;
- break;
- case REL_HWHEEL:
- mRelHWheel = rawEvent->value;
- break;
- }
- }
-}
-
-void CursorScrollAccumulator::finishSync() {
- clearRelativeAxes();
-}
-
-
-// --- TouchButtonAccumulator ---
-
-TouchButtonAccumulator::TouchButtonAccumulator() :
- mHaveBtnTouch(false), mHaveStylus(false) {
- clearButtons();
-}
-
-void TouchButtonAccumulator::configure(InputDevice* device) {
- mHaveBtnTouch = device->hasKey(BTN_TOUCH);
- mHaveStylus = device->hasKey(BTN_TOOL_PEN)
- || device->hasKey(BTN_TOOL_RUBBER)
- || device->hasKey(BTN_TOOL_BRUSH)
- || device->hasKey(BTN_TOOL_PENCIL)
- || device->hasKey(BTN_TOOL_AIRBRUSH);
-}
-
-void TouchButtonAccumulator::reset(InputDevice* device) {
- mBtnTouch = device->isKeyPressed(BTN_TOUCH);
- mBtnStylus = device->isKeyPressed(BTN_STYLUS);
- mBtnStylus2 = device->isKeyPressed(BTN_STYLUS);
- mBtnToolFinger = device->isKeyPressed(BTN_TOOL_FINGER);
- mBtnToolPen = device->isKeyPressed(BTN_TOOL_PEN);
- mBtnToolRubber = device->isKeyPressed(BTN_TOOL_RUBBER);
- mBtnToolBrush = device->isKeyPressed(BTN_TOOL_BRUSH);
- mBtnToolPencil = device->isKeyPressed(BTN_TOOL_PENCIL);
- mBtnToolAirbrush = device->isKeyPressed(BTN_TOOL_AIRBRUSH);
- mBtnToolMouse = device->isKeyPressed(BTN_TOOL_MOUSE);
- mBtnToolLens = device->isKeyPressed(BTN_TOOL_LENS);
- mBtnToolDoubleTap = device->isKeyPressed(BTN_TOOL_DOUBLETAP);
- mBtnToolTripleTap = device->isKeyPressed(BTN_TOOL_TRIPLETAP);
- mBtnToolQuadTap = device->isKeyPressed(BTN_TOOL_QUADTAP);
-}
-
-void TouchButtonAccumulator::clearButtons() {
- mBtnTouch = 0;
- mBtnStylus = 0;
- mBtnStylus2 = 0;
- mBtnToolFinger = 0;
- mBtnToolPen = 0;
- mBtnToolRubber = 0;
- mBtnToolBrush = 0;
- mBtnToolPencil = 0;
- mBtnToolAirbrush = 0;
- mBtnToolMouse = 0;
- mBtnToolLens = 0;
- mBtnToolDoubleTap = 0;
- mBtnToolTripleTap = 0;
- mBtnToolQuadTap = 0;
-}
-
-void TouchButtonAccumulator::process(const RawEvent* rawEvent) {
- if (rawEvent->type == EV_KEY) {
- switch (rawEvent->code) {
- case BTN_TOUCH:
- mBtnTouch = rawEvent->value;
- break;
- case BTN_STYLUS:
- mBtnStylus = rawEvent->value;
- break;
- case BTN_STYLUS2:
- mBtnStylus2 = rawEvent->value;
- break;
- case BTN_TOOL_FINGER:
- mBtnToolFinger = rawEvent->value;
- break;
- case BTN_TOOL_PEN:
- mBtnToolPen = rawEvent->value;
- break;
- case BTN_TOOL_RUBBER:
- mBtnToolRubber = rawEvent->value;
- break;
- case BTN_TOOL_BRUSH:
- mBtnToolBrush = rawEvent->value;
- break;
- case BTN_TOOL_PENCIL:
- mBtnToolPencil = rawEvent->value;
- break;
- case BTN_TOOL_AIRBRUSH:
- mBtnToolAirbrush = rawEvent->value;
- break;
- case BTN_TOOL_MOUSE:
- mBtnToolMouse = rawEvent->value;
- break;
- case BTN_TOOL_LENS:
- mBtnToolLens = rawEvent->value;
- break;
- case BTN_TOOL_DOUBLETAP:
- mBtnToolDoubleTap = rawEvent->value;
- break;
- case BTN_TOOL_TRIPLETAP:
- mBtnToolTripleTap = rawEvent->value;
- break;
- case BTN_TOOL_QUADTAP:
- mBtnToolQuadTap = rawEvent->value;
- break;
- }
- }
-}
-
-uint32_t TouchButtonAccumulator::getButtonState() const {
- uint32_t result = 0;
- if (mBtnStylus) {
- result |= AMOTION_EVENT_BUTTON_SECONDARY;
- }
- if (mBtnStylus2) {
- result |= AMOTION_EVENT_BUTTON_TERTIARY;
- }
- return result;
-}
-
-int32_t TouchButtonAccumulator::getToolType() const {
- if (mBtnToolMouse || mBtnToolLens) {
- return AMOTION_EVENT_TOOL_TYPE_MOUSE;
- }
- if (mBtnToolRubber) {
- return AMOTION_EVENT_TOOL_TYPE_ERASER;
- }
- if (mBtnToolPen || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush) {
- return AMOTION_EVENT_TOOL_TYPE_STYLUS;
- }
- if (mBtnToolFinger || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap) {
- return AMOTION_EVENT_TOOL_TYPE_FINGER;
- }
- return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
-}
-
-bool TouchButtonAccumulator::isToolActive() const {
- return mBtnTouch || mBtnToolFinger || mBtnToolPen || mBtnToolRubber
- || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush
- || mBtnToolMouse || mBtnToolLens
- || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap;
-}
-
-bool TouchButtonAccumulator::isHovering() const {
- return mHaveBtnTouch && !mBtnTouch;
-}
-
-bool TouchButtonAccumulator::hasStylus() const {
- return mHaveStylus;
-}
-
-
-// --- RawPointerAxes ---
-
-RawPointerAxes::RawPointerAxes() {
- clear();
-}
-
-void RawPointerAxes::clear() {
- x.clear();
- y.clear();
- pressure.clear();
- touchMajor.clear();
- touchMinor.clear();
- toolMajor.clear();
- toolMinor.clear();
- orientation.clear();
- distance.clear();
- tiltX.clear();
- tiltY.clear();
- trackingId.clear();
- slot.clear();
-}
-
-
-// --- RawPointerData ---
-
-RawPointerData::RawPointerData() {
- clear();
-}
-
-void RawPointerData::clear() {
- pointerCount = 0;
- clearIdBits();
-}
-
-void RawPointerData::copyFrom(const RawPointerData& other) {
- pointerCount = other.pointerCount;
- hoveringIdBits = other.hoveringIdBits;
- touchingIdBits = other.touchingIdBits;
-
- for (uint32_t i = 0; i < pointerCount; i++) {
- pointers[i] = other.pointers[i];
-
- int id = pointers[i].id;
- idToIndex[id] = other.idToIndex[id];
- }
-}
-
-void RawPointerData::getCentroidOfTouchingPointers(float* outX, float* outY) const {
- float x = 0, y = 0;
- uint32_t count = touchingIdBits.count();
- if (count) {
- for (BitSet32 idBits(touchingIdBits); !idBits.isEmpty(); ) {
- uint32_t id = idBits.clearFirstMarkedBit();
- const Pointer& pointer = pointerForId(id);
- x += pointer.x;
- y += pointer.y;
- }
- x /= count;
- y /= count;
- }
- *outX = x;
- *outY = y;
-}
-
-
-// --- CookedPointerData ---
-
-CookedPointerData::CookedPointerData() {
- clear();
-}
-
-void CookedPointerData::clear() {
- pointerCount = 0;
- hoveringIdBits.clear();
- touchingIdBits.clear();
-}
-
-void CookedPointerData::copyFrom(const CookedPointerData& other) {
- pointerCount = other.pointerCount;
- hoveringIdBits = other.hoveringIdBits;
- touchingIdBits = other.touchingIdBits;
-
- for (uint32_t i = 0; i < pointerCount; i++) {
- pointerProperties[i].copyFrom(other.pointerProperties[i]);
- pointerCoords[i].copyFrom(other.pointerCoords[i]);
-
- int id = pointerProperties[i].id;
- idToIndex[id] = other.idToIndex[id];
- }
-}
-
-
-// --- SingleTouchMotionAccumulator ---
-
-SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() {
- clearAbsoluteAxes();
-}
-
-void SingleTouchMotionAccumulator::reset(InputDevice* device) {
- mAbsX = device->getAbsoluteAxisValue(ABS_X);
- mAbsY = device->getAbsoluteAxisValue(ABS_Y);
- mAbsPressure = device->getAbsoluteAxisValue(ABS_PRESSURE);
- mAbsToolWidth = device->getAbsoluteAxisValue(ABS_TOOL_WIDTH);
- mAbsDistance = device->getAbsoluteAxisValue(ABS_DISTANCE);
- mAbsTiltX = device->getAbsoluteAxisValue(ABS_TILT_X);
- mAbsTiltY = device->getAbsoluteAxisValue(ABS_TILT_Y);
-}
-
-void SingleTouchMotionAccumulator::clearAbsoluteAxes() {
- mAbsX = 0;
- mAbsY = 0;
- mAbsPressure = 0;
- mAbsToolWidth = 0;
- mAbsDistance = 0;
- mAbsTiltX = 0;
- mAbsTiltY = 0;
-}
-
-void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) {
- if (rawEvent->type == EV_ABS) {
- switch (rawEvent->code) {
- case ABS_X:
- mAbsX = rawEvent->value;
- break;
- case ABS_Y:
- mAbsY = rawEvent->value;
- break;
- case ABS_PRESSURE:
- mAbsPressure = rawEvent->value;
- break;
- case ABS_TOOL_WIDTH:
- mAbsToolWidth = rawEvent->value;
- break;
- case ABS_DISTANCE:
- mAbsDistance = rawEvent->value;
- break;
- case ABS_TILT_X:
- mAbsTiltX = rawEvent->value;
- break;
- case ABS_TILT_Y:
- mAbsTiltY = rawEvent->value;
- break;
- }
- }
-}
-
-
-// --- MultiTouchMotionAccumulator ---
-
-MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() :
- mCurrentSlot(-1), mSlots(NULL), mSlotCount(0), mUsingSlotsProtocol(false),
- mHaveStylus(false) {
-}
-
-MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
- delete[] mSlots;
-}
-
-void MultiTouchMotionAccumulator::configure(InputDevice* device,
- size_t slotCount, bool usingSlotsProtocol) {
- mSlotCount = slotCount;
- mUsingSlotsProtocol = usingSlotsProtocol;
- mHaveStylus = device->hasAbsoluteAxis(ABS_MT_TOOL_TYPE);
-
- delete[] mSlots;
- mSlots = new Slot[slotCount];
-}
-
-void MultiTouchMotionAccumulator::reset(InputDevice* device) {
- // Unfortunately there is no way to read the initial contents of the slots.
- // So when we reset the accumulator, we must assume they are all zeroes.
- if (mUsingSlotsProtocol) {
- // Query the driver for the current slot index and use it as the initial slot
- // before we start reading events from the device. It is possible that the
- // current slot index will not be the same as it was when the first event was
- // written into the evdev buffer, which means the input mapper could start
- // out of sync with the initial state of the events in the evdev buffer.
- // In the extremely unlikely case that this happens, the data from
- // two slots will be confused until the next ABS_MT_SLOT event is received.
- // This can cause the touch point to "jump", but at least there will be
- // no stuck touches.
- int32_t initialSlot;
- status_t status = device->getEventHub()->getAbsoluteAxisValue(device->getId(),
- ABS_MT_SLOT, &initialSlot);
- if (status) {
- ALOGD("Could not retrieve current multitouch slot index. status=%d", status);
- initialSlot = -1;
- }
- clearSlots(initialSlot);
- } else {
- clearSlots(-1);
- }
-}
-
-void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
- if (mSlots) {
- for (size_t i = 0; i < mSlotCount; i++) {
- mSlots[i].clear();
- }
- }
- mCurrentSlot = initialSlot;
-}
-
-void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
- if (rawEvent->type == EV_ABS) {
- bool newSlot = false;
- if (mUsingSlotsProtocol) {
- if (rawEvent->code == ABS_MT_SLOT) {
- mCurrentSlot = rawEvent->value;
- newSlot = true;
- }
- } else if (mCurrentSlot < 0) {
- mCurrentSlot = 0;
- }
-
- if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
-#if DEBUG_POINTERS
- if (newSlot) {
- ALOGW("MultiTouch device emitted invalid slot index %d but it "
- "should be between 0 and %d; ignoring this slot.",
- mCurrentSlot, mSlotCount - 1);
- }
-#endif
- } else {
- Slot* slot = &mSlots[mCurrentSlot];
-
- switch (rawEvent->code) {
- case ABS_MT_POSITION_X:
- slot->mInUse = true;
- slot->mAbsMTPositionX = rawEvent->value;
- break;
- case ABS_MT_POSITION_Y:
- slot->mInUse = true;
- slot->mAbsMTPositionY = rawEvent->value;
- break;
- case ABS_MT_TOUCH_MAJOR:
- slot->mInUse = true;
- slot->mAbsMTTouchMajor = rawEvent->value;
- break;
- case ABS_MT_TOUCH_MINOR:
- slot->mInUse = true;
- slot->mAbsMTTouchMinor = rawEvent->value;
- slot->mHaveAbsMTTouchMinor = true;
- break;
- case ABS_MT_WIDTH_MAJOR:
- slot->mInUse = true;
- slot->mAbsMTWidthMajor = rawEvent->value;
- break;
- case ABS_MT_WIDTH_MINOR:
- slot->mInUse = true;
- slot->mAbsMTWidthMinor = rawEvent->value;
- slot->mHaveAbsMTWidthMinor = true;
- break;
- case ABS_MT_ORIENTATION:
- slot->mInUse = true;
- slot->mAbsMTOrientation = rawEvent->value;
- break;
- case ABS_MT_TRACKING_ID:
- if (mUsingSlotsProtocol && rawEvent->value < 0) {
- // The slot is no longer in use but it retains its previous contents,
- // which may be reused for subsequent touches.
- slot->mInUse = false;
- } else {
- slot->mInUse = true;
- slot->mAbsMTTrackingId = rawEvent->value;
- }
- break;
- case ABS_MT_PRESSURE:
- slot->mInUse = true;
- slot->mAbsMTPressure = rawEvent->value;
- break;
- case ABS_MT_DISTANCE:
- slot->mInUse = true;
- slot->mAbsMTDistance = rawEvent->value;
- break;
- case ABS_MT_TOOL_TYPE:
- slot->mInUse = true;
- slot->mAbsMTToolType = rawEvent->value;
- slot->mHaveAbsMTToolType = true;
- break;
- }
- }
- } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) {
- // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
- mCurrentSlot += 1;
- }
-}
-
-void MultiTouchMotionAccumulator::finishSync() {
- if (!mUsingSlotsProtocol) {
- clearSlots(-1);
- }
-}
-
-bool MultiTouchMotionAccumulator::hasStylus() const {
- return mHaveStylus;
-}
-
-
-// --- MultiTouchMotionAccumulator::Slot ---
-
-MultiTouchMotionAccumulator::Slot::Slot() {
- clear();
-}
-
-void MultiTouchMotionAccumulator::Slot::clear() {
- mInUse = false;
- mHaveAbsMTTouchMinor = false;
- mHaveAbsMTWidthMinor = false;
- mHaveAbsMTToolType = false;
- mAbsMTPositionX = 0;
- mAbsMTPositionY = 0;
- mAbsMTTouchMajor = 0;
- mAbsMTTouchMinor = 0;
- mAbsMTWidthMajor = 0;
- mAbsMTWidthMinor = 0;
- mAbsMTOrientation = 0;
- mAbsMTTrackingId = -1;
- mAbsMTPressure = 0;
- mAbsMTDistance = 0;
- mAbsMTToolType = 0;
-}
-
-int32_t MultiTouchMotionAccumulator::Slot::getToolType() const {
- if (mHaveAbsMTToolType) {
- switch (mAbsMTToolType) {
- case MT_TOOL_FINGER:
- return AMOTION_EVENT_TOOL_TYPE_FINGER;
- case MT_TOOL_PEN:
- return AMOTION_EVENT_TOOL_TYPE_STYLUS;
- }
- }
- return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
-}
-
-
-// --- InputMapper ---
-
-InputMapper::InputMapper(InputDevice* device) :
- mDevice(device), mContext(device->getContext()) {
-}
-
-InputMapper::~InputMapper() {
-}
-
-void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
- info->addSource(getSources());
-}
-
-void InputMapper::dump(String8& dump) {
-}
-
-void InputMapper::configure(nsecs_t when,
- const InputReaderConfiguration* config, uint32_t changes) {
-}
-
-void InputMapper::reset(nsecs_t when) {
-}
-
-void InputMapper::timeoutExpired(nsecs_t when) {
-}
-
-int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
- return AKEY_STATE_UNKNOWN;
-}
-
-int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
- return AKEY_STATE_UNKNOWN;
-}
-
-int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
- return AKEY_STATE_UNKNOWN;
-}
-
-bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) {
- return false;
-}
-
-void InputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
- int32_t token) {
-}
-
-void InputMapper::cancelVibrate(int32_t token) {
-}
-
-int32_t InputMapper::getMetaState() {
- return 0;
-}
-
-void InputMapper::fadePointer() {
-}
-
-status_t InputMapper::getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo) {
- return getEventHub()->getAbsoluteAxisInfo(getDeviceId(), axis, axisInfo);
-}
-
-void InputMapper::bumpGeneration() {
- mDevice->bumpGeneration();
-}
-
-void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump,
- const RawAbsoluteAxisInfo& axis, const char* name) {
- if (axis.valid) {
- dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d, resolution=%d\n",
- name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz, axis.resolution);
- } else {
- dump.appendFormat(INDENT4 "%s: unknown range\n", name);
- }
-}
-
-
-// --- SwitchInputMapper ---
-
-SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
- InputMapper(device), mUpdatedSwitchValues(0), mUpdatedSwitchMask(0) {
-}
-
-SwitchInputMapper::~SwitchInputMapper() {
-}
-
-uint32_t SwitchInputMapper::getSources() {
- return AINPUT_SOURCE_SWITCH;
-}
-
-void SwitchInputMapper::process(const RawEvent* rawEvent) {
- switch (rawEvent->type) {
- case EV_SW:
- processSwitch(rawEvent->code, rawEvent->value);
- break;
-
- case EV_SYN:
- if (rawEvent->code == SYN_REPORT) {
- sync(rawEvent->when);
- }
- }
-}
-
-void SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) {
- if (switchCode >= 0 && switchCode < 32) {
- if (switchValue) {
- mUpdatedSwitchValues |= 1 << switchCode;
- }
- mUpdatedSwitchMask |= 1 << switchCode;
- }
-}
-
-void SwitchInputMapper::sync(nsecs_t when) {
- if (mUpdatedSwitchMask) {
- NotifySwitchArgs args(when, 0, mUpdatedSwitchValues, mUpdatedSwitchMask);
- getListener()->notifySwitch(&args);
-
- mUpdatedSwitchValues = 0;
- mUpdatedSwitchMask = 0;
- }
-}
-
-int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
- return getEventHub()->getSwitchState(getDeviceId(), switchCode);
-}
-
-
-// --- VibratorInputMapper ---
-
-VibratorInputMapper::VibratorInputMapper(InputDevice* device) :
- InputMapper(device), mVibrating(false) {
-}
-
-VibratorInputMapper::~VibratorInputMapper() {
-}
-
-uint32_t VibratorInputMapper::getSources() {
- return 0;
-}
-
-void VibratorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
- InputMapper::populateDeviceInfo(info);
-
- info->setVibrator(true);
-}
-
-void VibratorInputMapper::process(const RawEvent* rawEvent) {
- // TODO: Handle FF_STATUS, although it does not seem to be widely supported.
-}
-
-void VibratorInputMapper::vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
- int32_t token) {
-#if DEBUG_VIBRATOR
- String8 patternStr;
- for (size_t i = 0; i < patternSize; i++) {
- if (i != 0) {
- patternStr.append(", ");
- }
- patternStr.appendFormat("%lld", pattern[i]);
- }
- ALOGD("vibrate: deviceId=%d, pattern=[%s], repeat=%ld, token=%d",
- getDeviceId(), patternStr.string(), repeat, token);
-#endif
-
- mVibrating = true;
- memcpy(mPattern, pattern, patternSize * sizeof(nsecs_t));
- mPatternSize = patternSize;
- mRepeat = repeat;
- mToken = token;
- mIndex = -1;
-
- nextStep();
-}
-
-void VibratorInputMapper::cancelVibrate(int32_t token) {
-#if DEBUG_VIBRATOR
- ALOGD("cancelVibrate: deviceId=%d, token=%d", getDeviceId(), token);
-#endif
-
- if (mVibrating && mToken == token) {
- stopVibrating();
- }
-}
-
-void VibratorInputMapper::timeoutExpired(nsecs_t when) {
- if (mVibrating) {
- if (when >= mNextStepTime) {
- nextStep();
- } else {
- getContext()->requestTimeoutAtTime(mNextStepTime);
- }
- }
-}
-
-void VibratorInputMapper::nextStep() {
- mIndex += 1;
- if (size_t(mIndex) >= mPatternSize) {
- if (mRepeat < 0) {
- // We are done.
- stopVibrating();
- return;
- }
- mIndex = mRepeat;
- }
-
- bool vibratorOn = mIndex & 1;
- nsecs_t duration = mPattern[mIndex];
- if (vibratorOn) {
-#if DEBUG_VIBRATOR
- ALOGD("nextStep: sending vibrate deviceId=%d, duration=%lld",
- getDeviceId(), duration);
-#endif
- getEventHub()->vibrate(getDeviceId(), duration);
- } else {
-#if DEBUG_VIBRATOR
- ALOGD("nextStep: sending cancel vibrate deviceId=%d", getDeviceId());
-#endif
- getEventHub()->cancelVibrate(getDeviceId());
- }
- nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
- mNextStepTime = now + duration;
- getContext()->requestTimeoutAtTime(mNextStepTime);
-#if DEBUG_VIBRATOR
- ALOGD("nextStep: scheduled timeout in %0.3fms", duration * 0.000001f);
-#endif
-}
-
-void VibratorInputMapper::stopVibrating() {
- mVibrating = false;
-#if DEBUG_VIBRATOR
- ALOGD("stopVibrating: sending cancel vibrate deviceId=%d", getDeviceId());
-#endif
- getEventHub()->cancelVibrate(getDeviceId());
-}
-
-void VibratorInputMapper::dump(String8& dump) {
- dump.append(INDENT2 "Vibrator Input Mapper:\n");
- dump.appendFormat(INDENT3 "Vibrating: %s\n", toString(mVibrating));
-}
-
-
-// --- KeyboardInputMapper ---
-
-KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
- uint32_t source, int32_t keyboardType) :
- InputMapper(device), mSource(source),
- mKeyboardType(keyboardType) {
-}
-
-KeyboardInputMapper::~KeyboardInputMapper() {
-}
-
-uint32_t KeyboardInputMapper::getSources() {
- return mSource;
-}
-
-void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
- InputMapper::populateDeviceInfo(info);
-
- info->setKeyboardType(mKeyboardType);
- info->setKeyCharacterMap(getEventHub()->getKeyCharacterMap(getDeviceId()));
-}
-
-void KeyboardInputMapper::dump(String8& dump) {
- dump.append(INDENT2 "Keyboard Input Mapper:\n");
- dumpParameters(dump);
- dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
- dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
- dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mKeyDowns.size());
- dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mMetaState);
- dump.appendFormat(INDENT3 "DownTime: %lld\n", mDownTime);
-}
-
-
-void KeyboardInputMapper::configure(nsecs_t when,
- const InputReaderConfiguration* config, uint32_t changes) {
- InputMapper::configure(when, config, changes);
-
- if (!changes) { // first time only
- // Configure basic parameters.
- configureParameters();
- }
-
- if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
- if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
- DisplayViewport v;
- if (config->getDisplayInfo(false /*external*/, &v)) {
- mOrientation = v.orientation;
- } else {
- mOrientation = DISPLAY_ORIENTATION_0;
- }
- } else {
- mOrientation = DISPLAY_ORIENTATION_0;
- }
- }
-}
-
-void KeyboardInputMapper::configureParameters() {
- mParameters.orientationAware = false;
- getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
- mParameters.orientationAware);
-
- mParameters.hasAssociatedDisplay = false;
- if (mParameters.orientationAware) {
- mParameters.hasAssociatedDisplay = true;
- }
-}
-
-void KeyboardInputMapper::dumpParameters(String8& dump) {
- dump.append(INDENT3 "Parameters:\n");
- dump.appendFormat(INDENT4 "HasAssociatedDisplay: %s\n",
- toString(mParameters.hasAssociatedDisplay));
- dump.appendFormat(INDENT4 "OrientationAware: %s\n",
- toString(mParameters.orientationAware));
-}
-
-void KeyboardInputMapper::reset(nsecs_t when) {
- mMetaState = AMETA_NONE;
- mDownTime = 0;
- mKeyDowns.clear();
- mCurrentHidUsage = 0;
-
- resetLedState();
-
- InputMapper::reset(when);
-}
-
-void KeyboardInputMapper::process(const RawEvent* rawEvent) {
- switch (rawEvent->type) {
- case EV_KEY: {
- int32_t scanCode = rawEvent->code;
- int32_t usageCode = mCurrentHidUsage;
- mCurrentHidUsage = 0;
-
- if (isKeyboardOrGamepadKey(scanCode)) {
- int32_t keyCode;
- uint32_t flags;
- if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, &keyCode, &flags)) {
- keyCode = AKEYCODE_UNKNOWN;
- flags = 0;
- }
- processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);
- }
- break;
- }
- case EV_MSC: {
- if (rawEvent->code == MSC_SCAN) {
- mCurrentHidUsage = rawEvent->value;
- }
- break;
- }
- case EV_SYN: {
- if (rawEvent->code == SYN_REPORT) {
- mCurrentHidUsage = 0;
- }
- }
- }
-}
-
-bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
- return scanCode < BTN_MOUSE
- || scanCode >= KEY_OK
- || (scanCode >= BTN_MISC && scanCode < BTN_MOUSE)
- || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
-}
-
-void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
- int32_t scanCode, uint32_t policyFlags) {
-
- if (down) {
- // Rotate key codes according to orientation if needed.
- if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
- keyCode = rotateKeyCode(keyCode, mOrientation);
- }
-
- // Add key down.
- ssize_t keyDownIndex = findKeyDown(scanCode);
- if (keyDownIndex >= 0) {
- // key repeat, be sure to use same keycode as before in case of rotation
- keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;
- } else {
- // key down
- if ((policyFlags & POLICY_FLAG_VIRTUAL)
- && mContext->shouldDropVirtualKey(when,
- getDevice(), keyCode, scanCode)) {
- return;
- }
-
- mKeyDowns.push();
- KeyDown& keyDown = mKeyDowns.editTop();
- keyDown.keyCode = keyCode;
- keyDown.scanCode = scanCode;
- }
-
- mDownTime = when;
- } else {
- // Remove key down.
- ssize_t keyDownIndex = findKeyDown(scanCode);
- if (keyDownIndex >= 0) {
- // key up, be sure to use same keycode as before in case of rotation
- keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;
- mKeyDowns.removeAt(size_t(keyDownIndex));
- } else {
- // key was not actually down
- ALOGI("Dropping key up from device %s because the key was not down. "
- "keyCode=%d, scanCode=%d",
- getDeviceName().string(), keyCode, scanCode);
- return;
- }
- }
-
- int32_t oldMetaState = mMetaState;
- int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);
- bool metaStateChanged = oldMetaState != newMetaState;
- if (metaStateChanged) {
- mMetaState = newMetaState;
- updateLedState(false);
- }
-
- nsecs_t downTime = mDownTime;
-
- // Key down on external an keyboard should wake the device.
- // We don't do this for internal keyboards to prevent them from waking up in your pocket.
- // For internal keyboards, the key layout file should specify the policy flags for
- // each wake key individually.
- // TODO: Use the input device configuration to control this behavior more finely.
- if (down && getDevice()->isExternal()
- && !(policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED))) {
- policyFlags |= POLICY_FLAG_WAKE_DROPPED;
- }
-
- if (metaStateChanged) {
- getContext()->updateGlobalMetaState();
- }
-
- if (down && !isMetaKey(keyCode)) {
- getContext()->fadePointer();
- }
-
- NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
- down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
- AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
- getListener()->notifyKey(&args);
-}
-
-ssize_t KeyboardInputMapper::findKeyDown(int32_t scanCode) {
- size_t n = mKeyDowns.size();
- for (size_t i = 0; i < n; i++) {
- if (mKeyDowns[i].scanCode == scanCode) {
- return i;
- }
- }
- return -1;
-}
-
-int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
- return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
-}
-
-int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
- return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
-}
-
-bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) {
- return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
-}
-
-int32_t KeyboardInputMapper::getMetaState() {
- return mMetaState;
-}
-
-void KeyboardInputMapper::resetLedState() {
- initializeLedState(mCapsLockLedState, ALED_CAPS_LOCK);
- initializeLedState(mNumLockLedState, ALED_NUM_LOCK);
- initializeLedState(mScrollLockLedState, ALED_SCROLL_LOCK);
-
- updateLedState(true);
-}
-
-void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) {
- ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
- ledState.on = false;
-}
-
-void KeyboardInputMapper::updateLedState(bool reset) {
- updateLedStateForModifier(mCapsLockLedState, ALED_CAPS_LOCK,
- AMETA_CAPS_LOCK_ON, reset);
- updateLedStateForModifier(mNumLockLedState, ALED_NUM_LOCK,
- AMETA_NUM_LOCK_ON, reset);
- updateLedStateForModifier(mScrollLockLedState, ALED_SCROLL_LOCK,
- AMETA_SCROLL_LOCK_ON, reset);
-}
-
-void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState,
- int32_t led, int32_t modifier, bool reset) {
- if (ledState.avail) {
- bool desiredState = (mMetaState & modifier) != 0;
- if (reset || ledState.on != desiredState) {
- getEventHub()->setLedState(getDeviceId(), led, desiredState);
- ledState.on = desiredState;
- }
- }
-}
-
-
-// --- CursorInputMapper ---
-
-CursorInputMapper::CursorInputMapper(InputDevice* device) :
- InputMapper(device) {
-}
-
-CursorInputMapper::~CursorInputMapper() {
-}
-
-uint32_t CursorInputMapper::getSources() {
- return mSource;
-}
-
-void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
- InputMapper::populateDeviceInfo(info);
-
- if (mParameters.mode == Parameters::MODE_POINTER) {
- float minX, minY, maxX, maxY;
- if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
- info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f, 0.0f);
- info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f, 0.0f);
- }
- } else {
- info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale, 0.0f);
- info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale, 0.0f);
- }
- info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f);
-
- if (mCursorScrollAccumulator.haveRelativeVWheel()) {
- info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
- }
- if (mCursorScrollAccumulator.haveRelativeHWheel()) {
- info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
- }
-}
-
-void CursorInputMapper::dump(String8& dump) {
- dump.append(INDENT2 "Cursor Input Mapper:\n");
- dumpParameters(dump);
- dump.appendFormat(INDENT3 "XScale: %0.3f\n", mXScale);
- dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
- dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
- dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
- dump.appendFormat(INDENT3 "HaveVWheel: %s\n",
- toString(mCursorScrollAccumulator.haveRelativeVWheel()));
- dump.appendFormat(INDENT3 "HaveHWheel: %s\n",
- toString(mCursorScrollAccumulator.haveRelativeHWheel()));
- dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
- dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
- dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
- dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
- dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
- dump.appendFormat(INDENT3 "DownTime: %lld\n", mDownTime);
-}
-
-void CursorInputMapper::configure(nsecs_t when,
- const InputReaderConfiguration* config, uint32_t changes) {
- InputMapper::configure(when, config, changes);
-
- if (!changes) { // first time only
- mCursorScrollAccumulator.configure(getDevice());
-
- // Configure basic parameters.
- configureParameters();
-
- // Configure device mode.
- switch (mParameters.mode) {
- case Parameters::MODE_POINTER:
- mSource = AINPUT_SOURCE_MOUSE;
- mXPrecision = 1.0f;
- mYPrecision = 1.0f;
- mXScale = 1.0f;
- mYScale = 1.0f;
- mPointerController = getPolicy()->obtainPointerController(getDeviceId());
- break;
- case Parameters::MODE_NAVIGATION:
- mSource = AINPUT_SOURCE_TRACKBALL;
- mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
- mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
- mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
- mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
- break;
- }
-
- mVWheelScale = 1.0f;
- mHWheelScale = 1.0f;
- }
-
- if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
- mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters);
- mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters);
- mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters);
- }
-
- if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
- if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
- DisplayViewport v;
- if (config->getDisplayInfo(false /*external*/, &v)) {
- mOrientation = v.orientation;
- } else {
- mOrientation = DISPLAY_ORIENTATION_0;
- }
- } else {
- mOrientation = DISPLAY_ORIENTATION_0;
- }
- bumpGeneration();
- }
-}
-
-void CursorInputMapper::configureParameters() {
- mParameters.mode = Parameters::MODE_POINTER;
- String8 cursorModeString;
- if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
- if (cursorModeString == "navigation") {
- mParameters.mode = Parameters::MODE_NAVIGATION;
- } else if (cursorModeString != "pointer" && cursorModeString != "default") {
- ALOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
- }
- }
-
- mParameters.orientationAware = false;
- getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
- mParameters.orientationAware);
-
- mParameters.hasAssociatedDisplay = false;
- if (mParameters.mode == Parameters::MODE_POINTER || mParameters.orientationAware) {
- mParameters.hasAssociatedDisplay = true;
- }
-}
-
-void CursorInputMapper::dumpParameters(String8& dump) {
- dump.append(INDENT3 "Parameters:\n");
- dump.appendFormat(INDENT4 "HasAssociatedDisplay: %s\n",
- toString(mParameters.hasAssociatedDisplay));
-
- switch (mParameters.mode) {
- case Parameters::MODE_POINTER:
- dump.append(INDENT4 "Mode: pointer\n");
- break;
- case Parameters::MODE_NAVIGATION:
- dump.append(INDENT4 "Mode: navigation\n");
- break;
- default:
- ALOG_ASSERT(false);
- }
-
- dump.appendFormat(INDENT4 "OrientationAware: %s\n",
- toString(mParameters.orientationAware));
-}
-
-void CursorInputMapper::reset(nsecs_t when) {
- mButtonState = 0;
- mDownTime = 0;
-
- mPointerVelocityControl.reset();
- mWheelXVelocityControl.reset();
- mWheelYVelocityControl.reset();
-
- mCursorButtonAccumulator.reset(getDevice());
- mCursorMotionAccumulator.reset(getDevice());
- mCursorScrollAccumulator.reset(getDevice());
-
- InputMapper::reset(when);
-}
-
-void CursorInputMapper::process(const RawEvent* rawEvent) {
- mCursorButtonAccumulator.process(rawEvent);
- mCursorMotionAccumulator.process(rawEvent);
- mCursorScrollAccumulator.process(rawEvent);
-
- if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
- sync(rawEvent->when);
- }
-}
-
-void CursorInputMapper::sync(nsecs_t when) {
- int32_t lastButtonState = mButtonState;
- int32_t currentButtonState = mCursorButtonAccumulator.getButtonState();
- mButtonState = currentButtonState;
-
- bool wasDown = isPointerDown(lastButtonState);
- bool down = isPointerDown(currentButtonState);
- bool downChanged;
- if (!wasDown && down) {
- mDownTime = when;
- downChanged = true;
- } else if (wasDown && !down) {
- downChanged = true;
- } else {
- downChanged = false;
- }
- nsecs_t downTime = mDownTime;
- bool buttonsChanged = currentButtonState != lastButtonState;
- bool buttonsPressed = currentButtonState & ~lastButtonState;
-
- float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
- float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
- bool moved = deltaX != 0 || deltaY != 0;
-
- // Rotate delta according to orientation if needed.
- if (mParameters.orientationAware && mParameters.hasAssociatedDisplay
- && (deltaX != 0.0f || deltaY != 0.0f)) {
- rotateDelta(mOrientation, &deltaX, &deltaY);
- }
-
- // Move the pointer.
- PointerProperties pointerProperties;
- pointerProperties.clear();
- pointerProperties.id = 0;
- pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE;
-
- PointerCoords pointerCoords;
- pointerCoords.clear();
-
- float vscroll = mCursorScrollAccumulator.getRelativeVWheel();
- float hscroll = mCursorScrollAccumulator.getRelativeHWheel();
- bool scrolled = vscroll != 0 || hscroll != 0;
-
- mWheelYVelocityControl.move(when, NULL, &vscroll);
- mWheelXVelocityControl.move(when, &hscroll, NULL);
-
- mPointerVelocityControl.move(when, &deltaX, &deltaY);
-
- int32_t displayId;
- if (mPointerController != NULL) {
- if (moved || scrolled || buttonsChanged) {
- mPointerController->setPresentation(
- PointerControllerInterface::PRESENTATION_POINTER);
-
- if (moved) {
- mPointerController->move(deltaX, deltaY);
- }
-
- if (buttonsChanged) {
- mPointerController->setButtonState(currentButtonState);
- }
-
- mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
- }
-
- float x, y;
- mPointerController->getPosition(&x, &y);
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
- displayId = ADISPLAY_ID_DEFAULT;
- } else {
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
- displayId = ADISPLAY_ID_NONE;
- }
-
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
-
- // Moving an external trackball or mouse should wake the device.
- // We don't do this for internal cursor devices to prevent them from waking up
- // the device in your pocket.
- // TODO: Use the input device configuration to control this behavior more finely.
- uint32_t policyFlags = 0;
- if ((buttonsPressed || moved || scrolled) && getDevice()->isExternal()) {
- policyFlags |= POLICY_FLAG_WAKE_DROPPED;
- }
-
- // Synthesize key down from buttons if needed.
- synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
- policyFlags, lastButtonState, currentButtonState);
-
- // Send motion event.
- if (downChanged || moved || scrolled || buttonsChanged) {
- int32_t metaState = mContext->getGlobalMetaState();
- int32_t motionEventAction;
- if (downChanged) {
- motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
- } else if (down || mPointerController == NULL) {
- motionEventAction = AMOTION_EVENT_ACTION_MOVE;
- } else {
- motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
- }
-
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- motionEventAction, 0, metaState, currentButtonState, 0,
- displayId, 1, &pointerProperties, &pointerCoords,
- mXPrecision, mYPrecision, downTime);
- getListener()->notifyMotion(&args);
-
- // Send hover move after UP to tell the application that the mouse is hovering now.
- if (motionEventAction == AMOTION_EVENT_ACTION_UP
- && mPointerController != NULL) {
- NotifyMotionArgs hoverArgs(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
- metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- displayId, 1, &pointerProperties, &pointerCoords,
- mXPrecision, mYPrecision, downTime);
- getListener()->notifyMotion(&hoverArgs);
- }
-
- // Send scroll events.
- if (scrolled) {
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
-
- NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_SCROLL, 0, metaState, currentButtonState,
- AMOTION_EVENT_EDGE_FLAG_NONE,
- displayId, 1, &pointerProperties, &pointerCoords,
- mXPrecision, mYPrecision, downTime);
- getListener()->notifyMotion(&scrollArgs);
- }
- }
-
- // Synthesize key up from buttons if needed.
- synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
- policyFlags, lastButtonState, currentButtonState);
-
- mCursorMotionAccumulator.finishSync();
- mCursorScrollAccumulator.finishSync();
-}
-
-int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
- if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
- return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
- } else {
- return AKEY_STATE_UNKNOWN;
- }
-}
-
-void CursorInputMapper::fadePointer() {
- if (mPointerController != NULL) {
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
- }
-}
-
-
-// --- TouchInputMapper ---
-
-TouchInputMapper::TouchInputMapper(InputDevice* device) :
- InputMapper(device),
- mSource(0), mDeviceMode(DEVICE_MODE_DISABLED),
- mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0),
- mSurfaceOrientation(DISPLAY_ORIENTATION_0) {
-}
-
-TouchInputMapper::~TouchInputMapper() {
-}
-
-uint32_t TouchInputMapper::getSources() {
- return mSource;
-}
-
-void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
- InputMapper::populateDeviceInfo(info);
-
- if (mDeviceMode != DEVICE_MODE_DISABLED) {
- info->addMotionRange(mOrientedRanges.x);
- info->addMotionRange(mOrientedRanges.y);
- info->addMotionRange(mOrientedRanges.pressure);
-
- if (mOrientedRanges.haveSize) {
- info->addMotionRange(mOrientedRanges.size);
- }
-
- if (mOrientedRanges.haveTouchSize) {
- info->addMotionRange(mOrientedRanges.touchMajor);
- info->addMotionRange(mOrientedRanges.touchMinor);
- }
-
- if (mOrientedRanges.haveToolSize) {
- info->addMotionRange(mOrientedRanges.toolMajor);
- info->addMotionRange(mOrientedRanges.toolMinor);
- }
-
- if (mOrientedRanges.haveOrientation) {
- info->addMotionRange(mOrientedRanges.orientation);
- }
-
- if (mOrientedRanges.haveDistance) {
- info->addMotionRange(mOrientedRanges.distance);
- }
-
- if (mOrientedRanges.haveTilt) {
- info->addMotionRange(mOrientedRanges.tilt);
- }
-
- if (mCursorScrollAccumulator.haveRelativeVWheel()) {
- info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
- 0.0f);
- }
- if (mCursorScrollAccumulator.haveRelativeHWheel()) {
- info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
- 0.0f);
- }
- if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
- const InputDeviceInfo::MotionRange& x = mOrientedRanges.x;
- const InputDeviceInfo::MotionRange& y = mOrientedRanges.y;
- info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_1, mSource, x.min, x.max, x.flat,
- x.fuzz, x.resolution);
- info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_2, mSource, y.min, y.max, y.flat,
- y.fuzz, y.resolution);
- info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_3, mSource, x.min, x.max, x.flat,
- x.fuzz, x.resolution);
- info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_4, mSource, y.min, y.max, y.flat,
- y.fuzz, y.resolution);
- }
- info->setButtonUnderPad(mParameters.hasButtonUnderPad);
- }
-}
-
-void TouchInputMapper::dump(String8& dump) {
- dump.append(INDENT2 "Touch Input Mapper:\n");
- dumpParameters(dump);
- dumpVirtualKeys(dump);
- dumpRawPointerAxes(dump);
- dumpCalibration(dump);
- dumpSurface(dump);
-
- dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
- dump.appendFormat(INDENT4 "XTranslate: %0.3f\n", mXTranslate);
- dump.appendFormat(INDENT4 "YTranslate: %0.3f\n", mYTranslate);
- dump.appendFormat(INDENT4 "XScale: %0.3f\n", mXScale);
- dump.appendFormat(INDENT4 "YScale: %0.3f\n", mYScale);
- dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mXPrecision);
- dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mYPrecision);
- dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mGeometricScale);
- dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mPressureScale);
- dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mSizeScale);
- dump.appendFormat(INDENT4 "OrientationScale: %0.3f\n", mOrientationScale);
- dump.appendFormat(INDENT4 "DistanceScale: %0.3f\n", mDistanceScale);
- dump.appendFormat(INDENT4 "HaveTilt: %s\n", toString(mHaveTilt));
- dump.appendFormat(INDENT4 "TiltXCenter: %0.3f\n", mTiltXCenter);
- dump.appendFormat(INDENT4 "TiltXScale: %0.3f\n", mTiltXScale);
- dump.appendFormat(INDENT4 "TiltYCenter: %0.3f\n", mTiltYCenter);
- dump.appendFormat(INDENT4 "TiltYScale: %0.3f\n", mTiltYScale);
-
- dump.appendFormat(INDENT3 "Last Button State: 0x%08x\n", mLastButtonState);
-
- dump.appendFormat(INDENT3 "Last Raw Touch: pointerCount=%d\n",
- mLastRawPointerData.pointerCount);
- for (uint32_t i = 0; i < mLastRawPointerData.pointerCount; i++) {
- const RawPointerData::Pointer& pointer = mLastRawPointerData.pointers[i];
- dump.appendFormat(INDENT4 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
- "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
- "orientation=%d, tiltX=%d, tiltY=%d, distance=%d, "
- "toolType=%d, isHovering=%s\n", i,
- pointer.id, pointer.x, pointer.y, pointer.pressure,
- pointer.touchMajor, pointer.touchMinor,
- pointer.toolMajor, pointer.toolMinor,
- pointer.orientation, pointer.tiltX, pointer.tiltY, pointer.distance,
- pointer.toolType, toString(pointer.isHovering));
- }
-
- dump.appendFormat(INDENT3 "Last Cooked Touch: pointerCount=%d\n",
- mLastCookedPointerData.pointerCount);
- for (uint32_t i = 0; i < mLastCookedPointerData.pointerCount; i++) {
- const PointerProperties& pointerProperties = mLastCookedPointerData.pointerProperties[i];
- const PointerCoords& pointerCoords = mLastCookedPointerData.pointerCoords[i];
- dump.appendFormat(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, pressure=%0.3f, "
- "touchMajor=%0.3f, touchMinor=%0.3f, toolMajor=%0.3f, toolMinor=%0.3f, "
- "orientation=%0.3f, tilt=%0.3f, distance=%0.3f, "
- "toolType=%d, isHovering=%s\n", i,
- pointerProperties.id,
- pointerCoords.getX(),
- pointerCoords.getY(),
- pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
- pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
- pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
- pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
- pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
- pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION),
- pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TILT),
- pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE),
- pointerProperties.toolType,
- toString(mLastCookedPointerData.isHovering(i)));
- }
-
- if (mDeviceMode == DEVICE_MODE_POINTER) {
- dump.appendFormat(INDENT3 "Pointer Gesture Detector:\n");
- dump.appendFormat(INDENT4 "XMovementScale: %0.3f\n",
- mPointerXMovementScale);
- dump.appendFormat(INDENT4 "YMovementScale: %0.3f\n",
- mPointerYMovementScale);
- dump.appendFormat(INDENT4 "XZoomScale: %0.3f\n",
- mPointerXZoomScale);
- dump.appendFormat(INDENT4 "YZoomScale: %0.3f\n",
- mPointerYZoomScale);
- dump.appendFormat(INDENT4 "MaxSwipeWidth: %f\n",
- mPointerGestureMaxSwipeWidth);
- }
-}
-
-void TouchInputMapper::configure(nsecs_t when,
- const InputReaderConfiguration* config, uint32_t changes) {
- InputMapper::configure(when, config, changes);
-
- mConfig = *config;
-
- if (!changes) { // first time only
- // Configure basic parameters.
- configureParameters();
-
- // Configure common accumulators.
- mCursorScrollAccumulator.configure(getDevice());
- mTouchButtonAccumulator.configure(getDevice());
-
- // Configure absolute axis information.
- configureRawPointerAxes();
-
- // Prepare input device calibration.
- parseCalibration();
- resolveCalibration();
- }
-
- if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
- // Update pointer speed.
- mPointerVelocityControl.setParameters(mConfig.pointerVelocityControlParameters);
- mWheelXVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
- mWheelYVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
- }
-
- bool resetNeeded = false;
- if (!changes || (changes & (InputReaderConfiguration::CHANGE_DISPLAY_INFO
- | InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT
- | InputReaderConfiguration::CHANGE_SHOW_TOUCHES))) {
- // Configure device sources, surface dimensions, orientation and
- // scaling factors.
- configureSurface(when, &resetNeeded);
- }
-
- if (changes && resetNeeded) {
- // Send reset, unless this is the first time the device has been configured,
- // in which case the reader will call reset itself after all mappers are ready.
- getDevice()->notifyReset(when);
- }
-}
-
-void TouchInputMapper::configureParameters() {
- // Use the pointer presentation mode for devices that do not support distinct
- // multitouch. The spot-based presentation relies on being able to accurately
- // locate two or more fingers on the touch pad.
- mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT)
- ? Parameters::GESTURE_MODE_POINTER : Parameters::GESTURE_MODE_SPOTS;
-
- String8 gestureModeString;
- if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
- gestureModeString)) {
- if (gestureModeString == "pointer") {
- mParameters.gestureMode = Parameters::GESTURE_MODE_POINTER;
- } else if (gestureModeString == "spots") {
- mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS;
- } else if (gestureModeString != "default") {
- ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
- }
- }
-
- if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) {
- // The device is a touch screen.
- mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
- } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_POINTER)) {
- // The device is a pointing device like a track pad.
- mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
- } else if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X)
- || getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) {
- // The device is a cursor device with a touch pad attached.
- // By default don't use the touch pad to move the pointer.
- mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
- } else {
- // The device is a touch pad of unknown purpose.
- mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
- }
-
- mParameters.hasButtonUnderPad=
- getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_BUTTONPAD);
-
- String8 deviceTypeString;
- if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
- deviceTypeString)) {
- if (deviceTypeString == "touchScreen") {
- mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
- } else if (deviceTypeString == "touchPad") {
- mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
- } else if (deviceTypeString == "touchNavigation") {
- mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_NAVIGATION;
- } else if (deviceTypeString == "pointer") {
- mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
- } else if (deviceTypeString != "default") {
- ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
- }
- }
-
- mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
- getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
- mParameters.orientationAware);
-
- mParameters.hasAssociatedDisplay = false;
- mParameters.associatedDisplayIsExternal = false;
- if (mParameters.orientationAware
- || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
- || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
- mParameters.hasAssociatedDisplay = true;
- mParameters.associatedDisplayIsExternal =
- mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
- && getDevice()->isExternal();
- }
-}
-
-void TouchInputMapper::dumpParameters(String8& dump) {
- dump.append(INDENT3 "Parameters:\n");
-
- switch (mParameters.gestureMode) {
- case Parameters::GESTURE_MODE_POINTER:
- dump.append(INDENT4 "GestureMode: pointer\n");
- break;
- case Parameters::GESTURE_MODE_SPOTS:
- dump.append(INDENT4 "GestureMode: spots\n");
- break;
- default:
- assert(false);
- }
-
- switch (mParameters.deviceType) {
- case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
- dump.append(INDENT4 "DeviceType: touchScreen\n");
- break;
- case Parameters::DEVICE_TYPE_TOUCH_PAD:
- dump.append(INDENT4 "DeviceType: touchPad\n");
- break;
- case Parameters::DEVICE_TYPE_TOUCH_NAVIGATION:
- dump.append(INDENT4 "DeviceType: touchNavigation\n");
- break;
- case Parameters::DEVICE_TYPE_POINTER:
- dump.append(INDENT4 "DeviceType: pointer\n");
- break;
- default:
- ALOG_ASSERT(false);
- }
-
- dump.appendFormat(INDENT4 "AssociatedDisplay: hasAssociatedDisplay=%s, isExternal=%s\n",
- toString(mParameters.hasAssociatedDisplay),
- toString(mParameters.associatedDisplayIsExternal));
- dump.appendFormat(INDENT4 "OrientationAware: %s\n",
- toString(mParameters.orientationAware));
-}
-
-void TouchInputMapper::configureRawPointerAxes() {
- mRawPointerAxes.clear();
-}
-
-void TouchInputMapper::dumpRawPointerAxes(String8& dump) {
- dump.append(INDENT3 "Raw Touch Axes:\n");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.x, "X");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.y, "Y");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.pressure, "Pressure");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMajor, "TouchMajor");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMinor, "TouchMinor");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMajor, "ToolMajor");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMinor, "ToolMinor");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.orientation, "Orientation");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.distance, "Distance");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltX, "TiltX");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltY, "TiltY");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.trackingId, "TrackingId");
- dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.slot, "Slot");
-}
-
-void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
- int32_t oldDeviceMode = mDeviceMode;
-
- // Determine device mode.
- if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
- && mConfig.pointerGesturesEnabled) {
- mSource = AINPUT_SOURCE_MOUSE;
- mDeviceMode = DEVICE_MODE_POINTER;
- if (hasStylus()) {
- mSource |= AINPUT_SOURCE_STYLUS;
- }
- } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
- && mParameters.hasAssociatedDisplay) {
- mSource = AINPUT_SOURCE_TOUCHSCREEN;
- mDeviceMode = DEVICE_MODE_DIRECT;
- if (hasStylus()) {
- mSource |= AINPUT_SOURCE_STYLUS;
- }
- } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) {
- mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
- mDeviceMode = DEVICE_MODE_NAVIGATION;
- } else {
- mSource = AINPUT_SOURCE_TOUCHPAD;
- mDeviceMode = DEVICE_MODE_UNSCALED;
- }
-
- // Ensure we have valid X and Y axes.
- if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
- ALOGW(INDENT "Touch device '%s' did not report support for X or Y axis! "
- "The device will be inoperable.", getDeviceName().string());
- mDeviceMode = DEVICE_MODE_DISABLED;
- return;
- }
-
- // Raw width and height in the natural orientation.
- int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
- int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
-
- // Get associated display dimensions.
- DisplayViewport newViewport;
- if (mParameters.hasAssociatedDisplay) {
- if (!mConfig.getDisplayInfo(mParameters.associatedDisplayIsExternal, &newViewport)) {
- ALOGI(INDENT "Touch device '%s' could not query the properties of its associated "
- "display. The device will be inoperable until the display size "
- "becomes available.",
- getDeviceName().string());
- mDeviceMode = DEVICE_MODE_DISABLED;
- return;
- }
- } else {
- newViewport.setNonDisplayViewport(rawWidth, rawHeight);
- }
- bool viewportChanged = mViewport != newViewport;
- if (viewportChanged) {
- mViewport = newViewport;
-
- if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) {
- // Convert rotated viewport to natural surface coordinates.
- int32_t naturalLogicalWidth, naturalLogicalHeight;
- int32_t naturalPhysicalWidth, naturalPhysicalHeight;
- int32_t naturalPhysicalLeft, naturalPhysicalTop;
- int32_t naturalDeviceWidth, naturalDeviceHeight;
- switch (mViewport.orientation) {
- case DISPLAY_ORIENTATION_90:
- naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
- naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
- naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
- naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
- naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom;
- naturalPhysicalTop = mViewport.physicalLeft;
- naturalDeviceWidth = mViewport.deviceHeight;
- naturalDeviceHeight = mViewport.deviceWidth;
- break;
- case DISPLAY_ORIENTATION_180:
- naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
- naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
- naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
- naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
- naturalPhysicalLeft = mViewport.deviceWidth - mViewport.physicalRight;
- naturalPhysicalTop = mViewport.deviceHeight - mViewport.physicalBottom;
- naturalDeviceWidth = mViewport.deviceWidth;
- naturalDeviceHeight = mViewport.deviceHeight;
- break;
- case DISPLAY_ORIENTATION_270:
- naturalLogicalWidth = mViewport.logicalBottom - mViewport.logicalTop;
- naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
- naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
- naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
- naturalPhysicalLeft = mViewport.physicalTop;
- naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight;
- naturalDeviceWidth = mViewport.deviceHeight;
- naturalDeviceHeight = mViewport.deviceWidth;
- break;
- case DISPLAY_ORIENTATION_0:
- default:
- naturalLogicalWidth = mViewport.logicalRight - mViewport.logicalLeft;
- naturalLogicalHeight = mViewport.logicalBottom - mViewport.logicalTop;
- naturalPhysicalWidth = mViewport.physicalRight - mViewport.physicalLeft;
- naturalPhysicalHeight = mViewport.physicalBottom - mViewport.physicalTop;
- naturalPhysicalLeft = mViewport.physicalLeft;
- naturalPhysicalTop = mViewport.physicalTop;
- naturalDeviceWidth = mViewport.deviceWidth;
- naturalDeviceHeight = mViewport.deviceHeight;
- break;
- }
-
- mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth;
- mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight;
- mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth;
- mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight;
-
- mSurfaceOrientation = mParameters.orientationAware ?
- mViewport.orientation : DISPLAY_ORIENTATION_0;
- } else {
- mSurfaceWidth = rawWidth;
- mSurfaceHeight = rawHeight;
- mSurfaceLeft = 0;
- mSurfaceTop = 0;
- mSurfaceOrientation = DISPLAY_ORIENTATION_0;
- }
- }
-
- // If moving between pointer modes, need to reset some state.
- bool deviceModeChanged = mDeviceMode != oldDeviceMode;
- if (deviceModeChanged) {
- mOrientedRanges.clear();
- }
-
- // Create pointer controller if needed.
- if (mDeviceMode == DEVICE_MODE_POINTER ||
- (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
- if (mPointerController == NULL) {
- mPointerController = getPolicy()->obtainPointerController(getDeviceId());
- }
- } else {
- mPointerController.clear();
- }
-
- if (viewportChanged || deviceModeChanged) {
- ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, "
- "display id %d",
- getDeviceId(), getDeviceName().string(), mSurfaceWidth, mSurfaceHeight,
- mSurfaceOrientation, mDeviceMode, mViewport.displayId);
-
- // Configure X and Y factors.
- mXScale = float(mSurfaceWidth) / rawWidth;
- mYScale = float(mSurfaceHeight) / rawHeight;
- mXTranslate = -mSurfaceLeft;
- mYTranslate = -mSurfaceTop;
- mXPrecision = 1.0f / mXScale;
- mYPrecision = 1.0f / mYScale;
-
- mOrientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
- mOrientedRanges.x.source = mSource;
- mOrientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
- mOrientedRanges.y.source = mSource;
-
- configureVirtualKeys();
-
- // Scale factor for terms that are not oriented in a particular axis.
- // If the pixels are square then xScale == yScale otherwise we fake it
- // by choosing an average.
- mGeometricScale = avg(mXScale, mYScale);
-
- // Size of diagonal axis.
- float diagonalSize = hypotf(mSurfaceWidth, mSurfaceHeight);
-
- // Size factors.
- if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
- if (mRawPointerAxes.touchMajor.valid
- && mRawPointerAxes.touchMajor.maxValue != 0) {
- mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue;
- } else if (mRawPointerAxes.toolMajor.valid
- && mRawPointerAxes.toolMajor.maxValue != 0) {
- mSizeScale = 1.0f / mRawPointerAxes.toolMajor.maxValue;
- } else {
- mSizeScale = 0.0f;
- }
-
- mOrientedRanges.haveTouchSize = true;
- mOrientedRanges.haveToolSize = true;
- mOrientedRanges.haveSize = true;
-
- mOrientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR;
- mOrientedRanges.touchMajor.source = mSource;
- mOrientedRanges.touchMajor.min = 0;
- mOrientedRanges.touchMajor.max = diagonalSize;
- mOrientedRanges.touchMajor.flat = 0;
- mOrientedRanges.touchMajor.fuzz = 0;
- mOrientedRanges.touchMajor.resolution = 0;
-
- mOrientedRanges.touchMinor = mOrientedRanges.touchMajor;
- mOrientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
-
- mOrientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR;
- mOrientedRanges.toolMajor.source = mSource;
- mOrientedRanges.toolMajor.min = 0;
- mOrientedRanges.toolMajor.max = diagonalSize;
- mOrientedRanges.toolMajor.flat = 0;
- mOrientedRanges.toolMajor.fuzz = 0;
- mOrientedRanges.toolMajor.resolution = 0;
-
- mOrientedRanges.toolMinor = mOrientedRanges.toolMajor;
- mOrientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
-
- mOrientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE;
- mOrientedRanges.size.source = mSource;
- mOrientedRanges.size.min = 0;
- mOrientedRanges.size.max = 1.0;
- mOrientedRanges.size.flat = 0;
- mOrientedRanges.size.fuzz = 0;
- mOrientedRanges.size.resolution = 0;
- } else {
- mSizeScale = 0.0f;
- }
-
- // Pressure factors.
- mPressureScale = 0;
- if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
- || mCalibration.pressureCalibration
- == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
- if (mCalibration.havePressureScale) {
- mPressureScale = mCalibration.pressureScale;
- } else if (mRawPointerAxes.pressure.valid
- && mRawPointerAxes.pressure.maxValue != 0) {
- mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue;
- }
- }
-
- mOrientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
- mOrientedRanges.pressure.source = mSource;
- mOrientedRanges.pressure.min = 0;
- mOrientedRanges.pressure.max = 1.0;
- mOrientedRanges.pressure.flat = 0;
- mOrientedRanges.pressure.fuzz = 0;
- mOrientedRanges.pressure.resolution = 0;
-
- // Tilt
- mTiltXCenter = 0;
- mTiltXScale = 0;
- mTiltYCenter = 0;
- mTiltYScale = 0;
- mHaveTilt = mRawPointerAxes.tiltX.valid && mRawPointerAxes.tiltY.valid;
- if (mHaveTilt) {
- mTiltXCenter = avg(mRawPointerAxes.tiltX.minValue,
- mRawPointerAxes.tiltX.maxValue);
- mTiltYCenter = avg(mRawPointerAxes.tiltY.minValue,
- mRawPointerAxes.tiltY.maxValue);
- mTiltXScale = M_PI / 180;
- mTiltYScale = M_PI / 180;
-
- mOrientedRanges.haveTilt = true;
-
- mOrientedRanges.tilt.axis = AMOTION_EVENT_AXIS_TILT;
- mOrientedRanges.tilt.source = mSource;
- mOrientedRanges.tilt.min = 0;
- mOrientedRanges.tilt.max = M_PI_2;
- mOrientedRanges.tilt.flat = 0;
- mOrientedRanges.tilt.fuzz = 0;
- mOrientedRanges.tilt.resolution = 0;
- }
-
- // Orientation
- mOrientationScale = 0;
- if (mHaveTilt) {
- mOrientedRanges.haveOrientation = true;
-
- mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
- mOrientedRanges.orientation.source = mSource;
- mOrientedRanges.orientation.min = -M_PI;
- mOrientedRanges.orientation.max = M_PI;
- mOrientedRanges.orientation.flat = 0;
- mOrientedRanges.orientation.fuzz = 0;
- mOrientedRanges.orientation.resolution = 0;
- } else if (mCalibration.orientationCalibration !=
- Calibration::ORIENTATION_CALIBRATION_NONE) {
- if (mCalibration.orientationCalibration
- == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
- if (mRawPointerAxes.orientation.valid) {
- if (mRawPointerAxes.orientation.maxValue > 0) {
- mOrientationScale = M_PI_2 / mRawPointerAxes.orientation.maxValue;
- } else if (mRawPointerAxes.orientation.minValue < 0) {
- mOrientationScale = -M_PI_2 / mRawPointerAxes.orientation.minValue;
- } else {
- mOrientationScale = 0;
- }
- }
- }
-
- mOrientedRanges.haveOrientation = true;
-
- mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
- mOrientedRanges.orientation.source = mSource;
- mOrientedRanges.orientation.min = -M_PI_2;
- mOrientedRanges.orientation.max = M_PI_2;
- mOrientedRanges.orientation.flat = 0;
- mOrientedRanges.orientation.fuzz = 0;
- mOrientedRanges.orientation.resolution = 0;
- }
-
- // Distance
- mDistanceScale = 0;
- if (mCalibration.distanceCalibration != Calibration::DISTANCE_CALIBRATION_NONE) {
- if (mCalibration.distanceCalibration
- == Calibration::DISTANCE_CALIBRATION_SCALED) {
- if (mCalibration.haveDistanceScale) {
- mDistanceScale = mCalibration.distanceScale;
- } else {
- mDistanceScale = 1.0f;
- }
- }
-
- mOrientedRanges.haveDistance = true;
-
- mOrientedRanges.distance.axis = AMOTION_EVENT_AXIS_DISTANCE;
- mOrientedRanges.distance.source = mSource;
- mOrientedRanges.distance.min =
- mRawPointerAxes.distance.minValue * mDistanceScale;
- mOrientedRanges.distance.max =
- mRawPointerAxes.distance.maxValue * mDistanceScale;
- mOrientedRanges.distance.flat = 0;
- mOrientedRanges.distance.fuzz =
- mRawPointerAxes.distance.fuzz * mDistanceScale;
- mOrientedRanges.distance.resolution = 0;
- }
-
- // Compute oriented precision, scales and ranges.
- // Note that the maximum value reported is an inclusive maximum value so it is one
- // unit less than the total width or height of surface.
- switch (mSurfaceOrientation) {
- case DISPLAY_ORIENTATION_90:
- case DISPLAY_ORIENTATION_270:
- mOrientedXPrecision = mYPrecision;
- mOrientedYPrecision = mXPrecision;
-
- mOrientedRanges.x.min = mYTranslate;
- mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1;
- mOrientedRanges.x.flat = 0;
- mOrientedRanges.x.fuzz = 0;
- mOrientedRanges.x.resolution = mRawPointerAxes.y.resolution * mYScale;
-
- mOrientedRanges.y.min = mXTranslate;
- mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1;
- mOrientedRanges.y.flat = 0;
- mOrientedRanges.y.fuzz = 0;
- mOrientedRanges.y.resolution = mRawPointerAxes.x.resolution * mXScale;
- break;
-
- default:
- mOrientedXPrecision = mXPrecision;
- mOrientedYPrecision = mYPrecision;
-
- mOrientedRanges.x.min = mXTranslate;
- mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1;
- mOrientedRanges.x.flat = 0;
- mOrientedRanges.x.fuzz = 0;
- mOrientedRanges.x.resolution = mRawPointerAxes.x.resolution * mXScale;
-
- mOrientedRanges.y.min = mYTranslate;
- mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1;
- mOrientedRanges.y.flat = 0;
- mOrientedRanges.y.fuzz = 0;
- mOrientedRanges.y.resolution = mRawPointerAxes.y.resolution * mYScale;
- break;
- }
-
- if (mDeviceMode == DEVICE_MODE_POINTER) {
- // Compute pointer gesture detection parameters.
- float rawDiagonal = hypotf(rawWidth, rawHeight);
- float displayDiagonal = hypotf(mSurfaceWidth, mSurfaceHeight);
-
- // Scale movements such that one whole swipe of the touch pad covers a
- // given area relative to the diagonal size of the display when no acceleration
- // is applied.
- // Assume that the touch pad has a square aspect ratio such that movements in
- // X and Y of the same number of raw units cover the same physical distance.
- mPointerXMovementScale = mConfig.pointerGestureMovementSpeedRatio
- * displayDiagonal / rawDiagonal;
- mPointerYMovementScale = mPointerXMovementScale;
-
- // Scale zooms to cover a smaller range of the display than movements do.
- // This value determines the area around the pointer that is affected by freeform
- // pointer gestures.
- mPointerXZoomScale = mConfig.pointerGestureZoomSpeedRatio
- * displayDiagonal / rawDiagonal;
- mPointerYZoomScale = mPointerXZoomScale;
-
- // Max width between pointers to detect a swipe gesture is more than some fraction
- // of the diagonal axis of the touch pad. Touches that are wider than this are
- // translated into freeform gestures.
- mPointerGestureMaxSwipeWidth =
- mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal;
-
- // Abort current pointer usages because the state has changed.
- abortPointerUsage(when, 0 /*policyFlags*/);
- }
-
- // Inform the dispatcher about the changes.
- *outResetNeeded = true;
- bumpGeneration();
- }
-}
-
-void TouchInputMapper::dumpSurface(String8& dump) {
- dump.appendFormat(INDENT3 "Viewport: displayId=%d, orientation=%d, "
- "logicalFrame=[%d, %d, %d, %d], "
- "physicalFrame=[%d, %d, %d, %d], "
- "deviceSize=[%d, %d]\n",
- mViewport.displayId, mViewport.orientation,
- mViewport.logicalLeft, mViewport.logicalTop,
- mViewport.logicalRight, mViewport.logicalBottom,
- mViewport.physicalLeft, mViewport.physicalTop,
- mViewport.physicalRight, mViewport.physicalBottom,
- mViewport.deviceWidth, mViewport.deviceHeight);
-
- dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth);
- dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
- dump.appendFormat(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft);
- dump.appendFormat(INDENT3 "SurfaceTop: %d\n", mSurfaceTop);
- dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation);
-}
-
-void TouchInputMapper::configureVirtualKeys() {
- Vector<VirtualKeyDefinition> virtualKeyDefinitions;
- getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
-
- mVirtualKeys.clear();
-
- if (virtualKeyDefinitions.size() == 0) {
- return;
- }
-
- mVirtualKeys.setCapacity(virtualKeyDefinitions.size());
-
- int32_t touchScreenLeft = mRawPointerAxes.x.minValue;
- int32_t touchScreenTop = mRawPointerAxes.y.minValue;
- int32_t touchScreenWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
- int32_t touchScreenHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
-
- for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
- const VirtualKeyDefinition& virtualKeyDefinition =
- virtualKeyDefinitions[i];
-
- mVirtualKeys.add();
- VirtualKey& virtualKey = mVirtualKeys.editTop();
-
- virtualKey.scanCode = virtualKeyDefinition.scanCode;
- int32_t keyCode;
- uint32_t flags;
- if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode, 0, &keyCode, &flags)) {
- ALOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
- virtualKey.scanCode);
- mVirtualKeys.pop(); // drop the key
- continue;
- }
-
- virtualKey.keyCode = keyCode;
- virtualKey.flags = flags;
-
- // convert the key definition's display coordinates into touch coordinates for a hit box
- int32_t halfWidth = virtualKeyDefinition.width / 2;
- int32_t halfHeight = virtualKeyDefinition.height / 2;
-
- virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
- * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
- virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
- * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
- virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
- * touchScreenHeight / mSurfaceHeight + touchScreenTop;
- virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
- * touchScreenHeight / mSurfaceHeight + touchScreenTop;
- }
-}
-
-void TouchInputMapper::dumpVirtualKeys(String8& dump) {
- if (!mVirtualKeys.isEmpty()) {
- dump.append(INDENT3 "Virtual Keys:\n");
-
- for (size_t i = 0; i < mVirtualKeys.size(); i++) {
- const VirtualKey& virtualKey = mVirtualKeys.itemAt(i);
- dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
- "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
- i, virtualKey.scanCode, virtualKey.keyCode,
- virtualKey.hitLeft, virtualKey.hitRight,
- virtualKey.hitTop, virtualKey.hitBottom);
- }
- }
-}
-
-void TouchInputMapper::parseCalibration() {
- const PropertyMap& in = getDevice()->getConfiguration();
- Calibration& out = mCalibration;
-
- // Size
- out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
- String8 sizeCalibrationString;
- if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
- if (sizeCalibrationString == "none") {
- out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
- } else if (sizeCalibrationString == "geometric") {
- out.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
- } else if (sizeCalibrationString == "diameter") {
- out.sizeCalibration = Calibration::SIZE_CALIBRATION_DIAMETER;
- } else if (sizeCalibrationString == "box") {
- out.sizeCalibration = Calibration::SIZE_CALIBRATION_BOX;
- } else if (sizeCalibrationString == "area") {
- out.sizeCalibration = Calibration::SIZE_CALIBRATION_AREA;
- } else if (sizeCalibrationString != "default") {
- ALOGW("Invalid value for touch.size.calibration: '%s'",
- sizeCalibrationString.string());
- }
- }
-
- out.haveSizeScale = in.tryGetProperty(String8("touch.size.scale"),
- out.sizeScale);
- out.haveSizeBias = in.tryGetProperty(String8("touch.size.bias"),
- out.sizeBias);
- out.haveSizeIsSummed = in.tryGetProperty(String8("touch.size.isSummed"),
- out.sizeIsSummed);
-
- // Pressure
- out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
- String8 pressureCalibrationString;
- if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
- if (pressureCalibrationString == "none") {
- out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
- } else if (pressureCalibrationString == "physical") {
- out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
- } else if (pressureCalibrationString == "amplitude") {
- out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
- } else if (pressureCalibrationString != "default") {
- ALOGW("Invalid value for touch.pressure.calibration: '%s'",
- pressureCalibrationString.string());
- }
- }
-
- out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
- out.pressureScale);
-
- // Orientation
- out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
- String8 orientationCalibrationString;
- if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
- if (orientationCalibrationString == "none") {
- out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
- } else if (orientationCalibrationString == "interpolated") {
- out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
- } else if (orientationCalibrationString == "vector") {
- out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
- } else if (orientationCalibrationString != "default") {
- ALOGW("Invalid value for touch.orientation.calibration: '%s'",
- orientationCalibrationString.string());
- }
- }
-
- // Distance
- out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_DEFAULT;
- String8 distanceCalibrationString;
- if (in.tryGetProperty(String8("touch.distance.calibration"), distanceCalibrationString)) {
- if (distanceCalibrationString == "none") {
- out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
- } else if (distanceCalibrationString == "scaled") {
- out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
- } else if (distanceCalibrationString != "default") {
- ALOGW("Invalid value for touch.distance.calibration: '%s'",
- distanceCalibrationString.string());
- }
- }
-
- out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"),
- out.distanceScale);
-
- out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_DEFAULT;
- String8 coverageCalibrationString;
- if (in.tryGetProperty(String8("touch.coverage.calibration"), coverageCalibrationString)) {
- if (coverageCalibrationString == "none") {
- out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
- } else if (coverageCalibrationString == "box") {
- out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_BOX;
- } else if (coverageCalibrationString != "default") {
- ALOGW("Invalid value for touch.coverage.calibration: '%s'",
- coverageCalibrationString.string());
- }
- }
-}
-
-void TouchInputMapper::resolveCalibration() {
- // Size
- if (mRawPointerAxes.touchMajor.valid || mRawPointerAxes.toolMajor.valid) {
- if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DEFAULT) {
- mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
- }
- } else {
- mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
- }
-
- // Pressure
- if (mRawPointerAxes.pressure.valid) {
- if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_DEFAULT) {
- mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
- }
- } else {
- mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
- }
-
- // Orientation
- if (mRawPointerAxes.orientation.valid) {
- if (mCalibration.orientationCalibration == Calibration::ORIENTATION_CALIBRATION_DEFAULT) {
- mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
- }
- } else {
- mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
- }
-
- // Distance
- if (mRawPointerAxes.distance.valid) {
- if (mCalibration.distanceCalibration == Calibration::DISTANCE_CALIBRATION_DEFAULT) {
- mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
- }
- } else {
- mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
- }
-
- // Coverage
- if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_DEFAULT) {
- mCalibration.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
- }
-}
-
-void TouchInputMapper::dumpCalibration(String8& dump) {
- dump.append(INDENT3 "Calibration:\n");
-
- // Size
- switch (mCalibration.sizeCalibration) {
- case Calibration::SIZE_CALIBRATION_NONE:
- dump.append(INDENT4 "touch.size.calibration: none\n");
- break;
- case Calibration::SIZE_CALIBRATION_GEOMETRIC:
- dump.append(INDENT4 "touch.size.calibration: geometric\n");
- break;
- case Calibration::SIZE_CALIBRATION_DIAMETER:
- dump.append(INDENT4 "touch.size.calibration: diameter\n");
- break;
- case Calibration::SIZE_CALIBRATION_BOX:
- dump.append(INDENT4 "touch.size.calibration: box\n");
- break;
- case Calibration::SIZE_CALIBRATION_AREA:
- dump.append(INDENT4 "touch.size.calibration: area\n");
- break;
- default:
- ALOG_ASSERT(false);
- }
-
- if (mCalibration.haveSizeScale) {
- dump.appendFormat(INDENT4 "touch.size.scale: %0.3f\n",
- mCalibration.sizeScale);
- }
-
- if (mCalibration.haveSizeBias) {
- dump.appendFormat(INDENT4 "touch.size.bias: %0.3f\n",
- mCalibration.sizeBias);
- }
-
- if (mCalibration.haveSizeIsSummed) {
- dump.appendFormat(INDENT4 "touch.size.isSummed: %s\n",
- toString(mCalibration.sizeIsSummed));
- }
-
- // Pressure
- switch (mCalibration.pressureCalibration) {
- case Calibration::PRESSURE_CALIBRATION_NONE:
- dump.append(INDENT4 "touch.pressure.calibration: none\n");
- break;
- case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
- dump.append(INDENT4 "touch.pressure.calibration: physical\n");
- break;
- case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
- dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
- break;
- default:
- ALOG_ASSERT(false);
- }
-
- if (mCalibration.havePressureScale) {
- dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
- mCalibration.pressureScale);
- }
-
- // Orientation
- switch (mCalibration.orientationCalibration) {
- case Calibration::ORIENTATION_CALIBRATION_NONE:
- dump.append(INDENT4 "touch.orientation.calibration: none\n");
- break;
- case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
- dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
- break;
- case Calibration::ORIENTATION_CALIBRATION_VECTOR:
- dump.append(INDENT4 "touch.orientation.calibration: vector\n");
- break;
- default:
- ALOG_ASSERT(false);
- }
-
- // Distance
- switch (mCalibration.distanceCalibration) {
- case Calibration::DISTANCE_CALIBRATION_NONE:
- dump.append(INDENT4 "touch.distance.calibration: none\n");
- break;
- case Calibration::DISTANCE_CALIBRATION_SCALED:
- dump.append(INDENT4 "touch.distance.calibration: scaled\n");
- break;
- default:
- ALOG_ASSERT(false);
- }
-
- if (mCalibration.haveDistanceScale) {
- dump.appendFormat(INDENT4 "touch.distance.scale: %0.3f\n",
- mCalibration.distanceScale);
- }
-
- switch (mCalibration.coverageCalibration) {
- case Calibration::COVERAGE_CALIBRATION_NONE:
- dump.append(INDENT4 "touch.coverage.calibration: none\n");
- break;
- case Calibration::COVERAGE_CALIBRATION_BOX:
- dump.append(INDENT4 "touch.coverage.calibration: box\n");
- break;
- default:
- ALOG_ASSERT(false);
- }
-}
-
-void TouchInputMapper::reset(nsecs_t when) {
- mCursorButtonAccumulator.reset(getDevice());
- mCursorScrollAccumulator.reset(getDevice());
- mTouchButtonAccumulator.reset(getDevice());
-
- mPointerVelocityControl.reset();
- mWheelXVelocityControl.reset();
- mWheelYVelocityControl.reset();
-
- mCurrentRawPointerData.clear();
- mLastRawPointerData.clear();
- mCurrentCookedPointerData.clear();
- mLastCookedPointerData.clear();
- mCurrentButtonState = 0;
- mLastButtonState = 0;
- mCurrentRawVScroll = 0;
- mCurrentRawHScroll = 0;
- mCurrentFingerIdBits.clear();
- mLastFingerIdBits.clear();
- mCurrentStylusIdBits.clear();
- mLastStylusIdBits.clear();
- mCurrentMouseIdBits.clear();
- mLastMouseIdBits.clear();
- mPointerUsage = POINTER_USAGE_NONE;
- mSentHoverEnter = false;
- mDownTime = 0;
-
- mCurrentVirtualKey.down = false;
-
- mPointerGesture.reset();
- mPointerSimple.reset();
-
- if (mPointerController != NULL) {
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
- mPointerController->clearSpots();
- }
-
- InputMapper::reset(when);
-}
-
-void TouchInputMapper::process(const RawEvent* rawEvent) {
- mCursorButtonAccumulator.process(rawEvent);
- mCursorScrollAccumulator.process(rawEvent);
- mTouchButtonAccumulator.process(rawEvent);
-
- if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
- sync(rawEvent->when);
- }
-}
-
-void TouchInputMapper::sync(nsecs_t when) {
- // Sync button state.
- mCurrentButtonState = mTouchButtonAccumulator.getButtonState()
- | mCursorButtonAccumulator.getButtonState();
-
- // Sync scroll state.
- mCurrentRawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
- mCurrentRawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
- mCursorScrollAccumulator.finishSync();
-
- // Sync touch state.
- bool havePointerIds = true;
- mCurrentRawPointerData.clear();
- syncTouch(when, &havePointerIds);
-
-#if DEBUG_RAW_EVENTS
- if (!havePointerIds) {
- ALOGD("syncTouch: pointerCount %d -> %d, no pointer ids",
- mLastRawPointerData.pointerCount,
- mCurrentRawPointerData.pointerCount);
- } else {
- ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
- "hovering ids 0x%08x -> 0x%08x",
- mLastRawPointerData.pointerCount,
- mCurrentRawPointerData.pointerCount,
- mLastRawPointerData.touchingIdBits.value,
- mCurrentRawPointerData.touchingIdBits.value,
- mLastRawPointerData.hoveringIdBits.value,
- mCurrentRawPointerData.hoveringIdBits.value);
- }
-#endif
-
- // Reset state that we will compute below.
- mCurrentFingerIdBits.clear();
- mCurrentStylusIdBits.clear();
- mCurrentMouseIdBits.clear();
- mCurrentCookedPointerData.clear();
-
- if (mDeviceMode == DEVICE_MODE_DISABLED) {
- // Drop all input if the device is disabled.
- mCurrentRawPointerData.clear();
- mCurrentButtonState = 0;
- } else {
- // Preprocess pointer data.
- if (!havePointerIds) {
- assignPointerIds();
- }
-
- // Handle policy on initial down or hover events.
- uint32_t policyFlags = 0;
- bool initialDown = mLastRawPointerData.pointerCount == 0
- && mCurrentRawPointerData.pointerCount != 0;
- bool buttonsPressed = mCurrentButtonState & ~mLastButtonState;
- if (initialDown || buttonsPressed) {
- // If this is a touch screen, hide the pointer on an initial down.
- if (mDeviceMode == DEVICE_MODE_DIRECT) {
- getContext()->fadePointer();
- }
-
- // Initial downs on external touch devices should wake the device.
- // We don't do this for internal touch screens to prevent them from waking
- // up in your pocket.
- // TODO: Use the input device configuration to control this behavior more finely.
- if (getDevice()->isExternal()) {
- policyFlags |= POLICY_FLAG_WAKE_DROPPED;
- }
- }
-
- // Synthesize key down from raw buttons if needed.
- synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
- policyFlags, mLastButtonState, mCurrentButtonState);
-
- // Consume raw off-screen touches before cooking pointer data.
- // If touches are consumed, subsequent code will not receive any pointer data.
- if (consumeRawTouches(when, policyFlags)) {
- mCurrentRawPointerData.clear();
- }
-
- // Cook pointer data. This call populates the mCurrentCookedPointerData structure
- // with cooked pointer data that has the same ids and indices as the raw data.
- // The following code can use either the raw or cooked data, as needed.
- cookPointerData();
-
- // Dispatch the touches either directly or by translation through a pointer on screen.
- if (mDeviceMode == DEVICE_MODE_POINTER) {
- for (BitSet32 idBits(mCurrentRawPointerData.touchingIdBits); !idBits.isEmpty(); ) {
- uint32_t id = idBits.clearFirstMarkedBit();
- const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
- if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
- || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
- mCurrentStylusIdBits.markBit(id);
- } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
- || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
- mCurrentFingerIdBits.markBit(id);
- } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
- mCurrentMouseIdBits.markBit(id);
- }
- }
- for (BitSet32 idBits(mCurrentRawPointerData.hoveringIdBits); !idBits.isEmpty(); ) {
- uint32_t id = idBits.clearFirstMarkedBit();
- const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
- if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
- || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
- mCurrentStylusIdBits.markBit(id);
- }
- }
-
- // Stylus takes precedence over all tools, then mouse, then finger.
- PointerUsage pointerUsage = mPointerUsage;
- if (!mCurrentStylusIdBits.isEmpty()) {
- mCurrentMouseIdBits.clear();
- mCurrentFingerIdBits.clear();
- pointerUsage = POINTER_USAGE_STYLUS;
- } else if (!mCurrentMouseIdBits.isEmpty()) {
- mCurrentFingerIdBits.clear();
- pointerUsage = POINTER_USAGE_MOUSE;
- } else if (!mCurrentFingerIdBits.isEmpty() || isPointerDown(mCurrentButtonState)) {
- pointerUsage = POINTER_USAGE_GESTURES;
- }
-
- dispatchPointerUsage(when, policyFlags, pointerUsage);
- } else {
- if (mDeviceMode == DEVICE_MODE_DIRECT
- && mConfig.showTouches && mPointerController != NULL) {
- mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
-
- mPointerController->setButtonState(mCurrentButtonState);
- mPointerController->setSpots(mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.idToIndex,
- mCurrentCookedPointerData.touchingIdBits);
- }
-
- dispatchHoverExit(when, policyFlags);
- dispatchTouches(when, policyFlags);
- dispatchHoverEnterAndMove(when, policyFlags);
- }
-
- // Synthesize key up from raw buttons if needed.
- synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
- policyFlags, mLastButtonState, mCurrentButtonState);
- }
-
- // Copy current touch to last touch in preparation for the next cycle.
- mLastRawPointerData.copyFrom(mCurrentRawPointerData);
- mLastCookedPointerData.copyFrom(mCurrentCookedPointerData);
- mLastButtonState = mCurrentButtonState;
- mLastFingerIdBits = mCurrentFingerIdBits;
- mLastStylusIdBits = mCurrentStylusIdBits;
- mLastMouseIdBits = mCurrentMouseIdBits;
-
- // Clear some transient state.
- mCurrentRawVScroll = 0;
- mCurrentRawHScroll = 0;
-}
-
-void TouchInputMapper::timeoutExpired(nsecs_t when) {
- if (mDeviceMode == DEVICE_MODE_POINTER) {
- if (mPointerUsage == POINTER_USAGE_GESTURES) {
- dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
- }
- }
-}
-
-bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) {
- // Check for release of a virtual key.
- if (mCurrentVirtualKey.down) {
- if (mCurrentRawPointerData.touchingIdBits.isEmpty()) {
- // Pointer went up while virtual key was down.
- mCurrentVirtualKey.down = false;
- if (!mCurrentVirtualKey.ignored) {
-#if DEBUG_VIRTUAL_KEYS
- ALOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
- mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
-#endif
- dispatchVirtualKey(when, policyFlags,
- AKEY_EVENT_ACTION_UP,
- AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
- }
- return true;
- }
-
- if (mCurrentRawPointerData.touchingIdBits.count() == 1) {
- uint32_t id = mCurrentRawPointerData.touchingIdBits.firstMarkedBit();
- const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
- const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
- if (virtualKey && virtualKey->keyCode == mCurrentVirtualKey.keyCode) {
- // Pointer is still within the space of the virtual key.
- return true;
- }
- }
-
- // Pointer left virtual key area or another pointer also went down.
- // Send key cancellation but do not consume the touch yet.
- // This is useful when the user swipes through from the virtual key area
- // into the main display surface.
- mCurrentVirtualKey.down = false;
- if (!mCurrentVirtualKey.ignored) {
-#if DEBUG_VIRTUAL_KEYS
- ALOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
- mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
-#endif
- dispatchVirtualKey(when, policyFlags,
- AKEY_EVENT_ACTION_UP,
- AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
- | AKEY_EVENT_FLAG_CANCELED);
- }
- }
-
- if (mLastRawPointerData.touchingIdBits.isEmpty()
- && !mCurrentRawPointerData.touchingIdBits.isEmpty()) {
- // Pointer just went down. Check for virtual key press or off-screen touches.
- uint32_t id = mCurrentRawPointerData.touchingIdBits.firstMarkedBit();
- const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
- if (!isPointInsideSurface(pointer.x, pointer.y)) {
- // If exactly one pointer went down, check for virtual key hit.
- // Otherwise we will drop the entire stroke.
- if (mCurrentRawPointerData.touchingIdBits.count() == 1) {
- const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
- if (virtualKey) {
- mCurrentVirtualKey.down = true;
- mCurrentVirtualKey.downTime = when;
- mCurrentVirtualKey.keyCode = virtualKey->keyCode;
- mCurrentVirtualKey.scanCode = virtualKey->scanCode;
- mCurrentVirtualKey.ignored = mContext->shouldDropVirtualKey(
- when, getDevice(), virtualKey->keyCode, virtualKey->scanCode);
-
- if (!mCurrentVirtualKey.ignored) {
-#if DEBUG_VIRTUAL_KEYS
- ALOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
- mCurrentVirtualKey.keyCode,
- mCurrentVirtualKey.scanCode);
-#endif
- dispatchVirtualKey(when, policyFlags,
- AKEY_EVENT_ACTION_DOWN,
- AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
- }
- }
- }
- return true;
- }
- }
-
- // Disable all virtual key touches that happen within a short time interval of the
- // most recent touch within the screen area. The idea is to filter out stray
- // virtual key presses when interacting with the touch screen.
- //
- // Problems we're trying to solve:
- //
- // 1. While scrolling a list or dragging the window shade, the user swipes down into a
- // virtual key area that is implemented by a separate touch panel and accidentally
- // triggers a virtual key.
- //
- // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
- // area and accidentally triggers a virtual key. This often happens when virtual keys
- // are layed out below the screen near to where the on screen keyboard's space bar
- // is displayed.
- if (mConfig.virtualKeyQuietTime > 0 && !mCurrentRawPointerData.touchingIdBits.isEmpty()) {
- mContext->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime);
- }
- return false;
-}
-
-void TouchInputMapper::dispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
- int32_t keyEventAction, int32_t keyEventFlags) {
- int32_t keyCode = mCurrentVirtualKey.keyCode;
- int32_t scanCode = mCurrentVirtualKey.scanCode;
- nsecs_t downTime = mCurrentVirtualKey.downTime;
- int32_t metaState = mContext->getGlobalMetaState();
- policyFlags |= POLICY_FLAG_VIRTUAL;
-
- NotifyKeyArgs args(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
- keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
- getListener()->notifyKey(&args);
-}
-
-void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
- BitSet32 currentIdBits = mCurrentCookedPointerData.touchingIdBits;
- BitSet32 lastIdBits = mLastCookedPointerData.touchingIdBits;
- int32_t metaState = getContext()->getGlobalMetaState();
- int32_t buttonState = mCurrentButtonState;
-
- if (currentIdBits == lastIdBits) {
- if (!currentIdBits.isEmpty()) {
- // No pointer id changes so this is a move event.
- // The listener takes care of batching moves so we don't have to deal with that here.
- dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState,
- AMOTION_EVENT_EDGE_FLAG_NONE,
- mCurrentCookedPointerData.pointerProperties,
- mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.idToIndex,
- currentIdBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
- }
- } else {
- // There may be pointers going up and pointers going down and pointers moving
- // all at the same time.
- BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
- BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
- BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
- BitSet32 dispatchedIdBits(lastIdBits.value);
-
- // Update last coordinates of pointers that have moved so that we observe the new
- // pointer positions at the same time as other pointers that have just gone up.
- bool moveNeeded = updateMovedPointers(
- mCurrentCookedPointerData.pointerProperties,
- mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.idToIndex,
- mLastCookedPointerData.pointerProperties,
- mLastCookedPointerData.pointerCoords,
- mLastCookedPointerData.idToIndex,
- moveIdBits);
- if (buttonState != mLastButtonState) {
- moveNeeded = true;
- }
-
- // Dispatch pointer up events.
- while (!upIdBits.isEmpty()) {
- uint32_t upId = upIdBits.clearFirstMarkedBit();
-
- dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, buttonState, 0,
- mLastCookedPointerData.pointerProperties,
- mLastCookedPointerData.pointerCoords,
- mLastCookedPointerData.idToIndex,
- dispatchedIdBits, upId,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
- dispatchedIdBits.clearBit(upId);
- }
-
- // Dispatch move events if any of the remaining pointers moved from their old locations.
- // Although applications receive new locations as part of individual pointer up
- // events, they do not generally handle them except when presented in a move event.
- if (moveNeeded) {
- ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
- dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0,
- mCurrentCookedPointerData.pointerProperties,
- mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.idToIndex,
- dispatchedIdBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
- }
-
- // Dispatch pointer down events using the new pointer locations.
- while (!downIdBits.isEmpty()) {
- uint32_t downId = downIdBits.clearFirstMarkedBit();
- dispatchedIdBits.markBit(downId);
-
- if (dispatchedIdBits.count() == 1) {
- // First pointer is going down. Set down time.
- mDownTime = when;
- }
-
- dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
- mCurrentCookedPointerData.pointerProperties,
- mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.idToIndex,
- dispatchedIdBits, downId,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
- }
- }
-}
-
-void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) {
- if (mSentHoverEnter &&
- (mCurrentCookedPointerData.hoveringIdBits.isEmpty()
- || !mCurrentCookedPointerData.touchingIdBits.isEmpty())) {
- int32_t metaState = getContext()->getGlobalMetaState();
- dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0,
- mLastCookedPointerData.pointerProperties,
- mLastCookedPointerData.pointerCoords,
- mLastCookedPointerData.idToIndex,
- mLastCookedPointerData.hoveringIdBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
- mSentHoverEnter = false;
- }
-}
-
-void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags) {
- if (mCurrentCookedPointerData.touchingIdBits.isEmpty()
- && !mCurrentCookedPointerData.hoveringIdBits.isEmpty()) {
- int32_t metaState = getContext()->getGlobalMetaState();
- if (!mSentHoverEnter) {
- dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0,
- mCurrentCookedPointerData.pointerProperties,
- mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.idToIndex,
- mCurrentCookedPointerData.hoveringIdBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
- mSentHoverEnter = true;
- }
-
- dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0,
- mCurrentCookedPointerData.pointerProperties,
- mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.idToIndex,
- mCurrentCookedPointerData.hoveringIdBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
- }
-}
-
-void TouchInputMapper::cookPointerData() {
- uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount;
-
- mCurrentCookedPointerData.clear();
- mCurrentCookedPointerData.pointerCount = currentPointerCount;
- mCurrentCookedPointerData.hoveringIdBits = mCurrentRawPointerData.hoveringIdBits;
- mCurrentCookedPointerData.touchingIdBits = mCurrentRawPointerData.touchingIdBits;
-
- // Walk through the the active pointers and map device coordinates onto
- // surface coordinates and adjust for display orientation.
- for (uint32_t i = 0; i < currentPointerCount; i++) {
- const RawPointerData::Pointer& in = mCurrentRawPointerData.pointers[i];
-
- // Size
- float touchMajor, touchMinor, toolMajor, toolMinor, size;
- switch (mCalibration.sizeCalibration) {
- case Calibration::SIZE_CALIBRATION_GEOMETRIC:
- case Calibration::SIZE_CALIBRATION_DIAMETER:
- case Calibration::SIZE_CALIBRATION_BOX:
- case Calibration::SIZE_CALIBRATION_AREA:
- if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {
- touchMajor = in.touchMajor;
- touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
- toolMajor = in.toolMajor;
- toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
- size = mRawPointerAxes.touchMinor.valid
- ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
- } else if (mRawPointerAxes.touchMajor.valid) {
- toolMajor = touchMajor = in.touchMajor;
- toolMinor = touchMinor = mRawPointerAxes.touchMinor.valid
- ? in.touchMinor : in.touchMajor;
- size = mRawPointerAxes.touchMinor.valid
- ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
- } else if (mRawPointerAxes.toolMajor.valid) {
- touchMajor = toolMajor = in.toolMajor;
- touchMinor = toolMinor = mRawPointerAxes.toolMinor.valid
- ? in.toolMinor : in.toolMajor;
- size = mRawPointerAxes.toolMinor.valid
- ? avg(in.toolMajor, in.toolMinor) : in.toolMajor;
- } else {
- ALOG_ASSERT(false, "No touch or tool axes. "
- "Size calibration should have been resolved to NONE.");
- touchMajor = 0;
- touchMinor = 0;
- toolMajor = 0;
- toolMinor = 0;
- size = 0;
- }
-
- if (mCalibration.haveSizeIsSummed && mCalibration.sizeIsSummed) {
- uint32_t touchingCount = mCurrentRawPointerData.touchingIdBits.count();
- if (touchingCount > 1) {
- touchMajor /= touchingCount;
- touchMinor /= touchingCount;
- toolMajor /= touchingCount;
- toolMinor /= touchingCount;
- size /= touchingCount;
- }
- }
-
- if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_GEOMETRIC) {
- touchMajor *= mGeometricScale;
- touchMinor *= mGeometricScale;
- toolMajor *= mGeometricScale;
- toolMinor *= mGeometricScale;
- } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_AREA) {
- touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0;
- touchMinor = touchMajor;
- toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0;
- toolMinor = toolMajor;
- } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DIAMETER) {
- touchMinor = touchMajor;
- toolMinor = toolMajor;
- }
-
- mCalibration.applySizeScaleAndBias(&touchMajor);
- mCalibration.applySizeScaleAndBias(&touchMinor);
- mCalibration.applySizeScaleAndBias(&toolMajor);
- mCalibration.applySizeScaleAndBias(&toolMinor);
- size *= mSizeScale;
- break;
- default:
- touchMajor = 0;
- touchMinor = 0;
- toolMajor = 0;
- toolMinor = 0;
- size = 0;
- break;
- }
-
- // Pressure
- float pressure;
- switch (mCalibration.pressureCalibration) {
- case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
- case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
- pressure = in.pressure * mPressureScale;
- break;
- default:
- pressure = in.isHovering ? 0 : 1;
- break;
- }
-
- // Tilt and Orientation
- float tilt;
- float orientation;
- if (mHaveTilt) {
- float tiltXAngle = (in.tiltX - mTiltXCenter) * mTiltXScale;
- float tiltYAngle = (in.tiltY - mTiltYCenter) * mTiltYScale;
- orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
- tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
- } else {
- tilt = 0;
-
- switch (mCalibration.orientationCalibration) {
- case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
- orientation = in.orientation * mOrientationScale;
- break;
- case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
- int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
- int32_t c2 = signExtendNybble(in.orientation & 0x0f);
- if (c1 != 0 || c2 != 0) {
- orientation = atan2f(c1, c2) * 0.5f;
- float confidence = hypotf(c1, c2);
- float scale = 1.0f + confidence / 16.0f;
- touchMajor *= scale;
- touchMinor /= scale;
- toolMajor *= scale;
- toolMinor /= scale;
- } else {
- orientation = 0;
- }
- break;
- }
- default:
- orientation = 0;
- }
- }
-
- // Distance
- float distance;
- switch (mCalibration.distanceCalibration) {
- case Calibration::DISTANCE_CALIBRATION_SCALED:
- distance = in.distance * mDistanceScale;
- break;
- default:
- distance = 0;
- }
-
- // Coverage
- int32_t rawLeft, rawTop, rawRight, rawBottom;
- switch (mCalibration.coverageCalibration) {
- case Calibration::COVERAGE_CALIBRATION_BOX:
- rawLeft = (in.toolMinor & 0xffff0000) >> 16;
- rawRight = in.toolMinor & 0x0000ffff;
- rawBottom = in.toolMajor & 0x0000ffff;
- rawTop = (in.toolMajor & 0xffff0000) >> 16;
- break;
- default:
- rawLeft = rawTop = rawRight = rawBottom = 0;
- break;
- }
-
- // X, Y, and the bounding box for coverage information
- // Adjust coords for surface orientation.
- float x, y, left, top, right, bottom;
- switch (mSurfaceOrientation) {
- case DISPLAY_ORIENTATION_90:
- x = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
- y = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate;
- left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
- right = float(rawBottom- mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
- bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
- top = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
- orientation -= M_PI_2;
- if (orientation < mOrientedRanges.orientation.min) {
- orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
- }
- break;
- case DISPLAY_ORIENTATION_180:
- x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate;
- y = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate;
- left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
- right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
- bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
- top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
- orientation -= M_PI;
- if (orientation < mOrientedRanges.orientation.min) {
- orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
- }
- break;
- case DISPLAY_ORIENTATION_270:
- x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate;
- y = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
- left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
- right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
- bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
- top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
- orientation += M_PI_2;
- if (orientation > mOrientedRanges.orientation.max) {
- orientation -= (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
- }
- break;
- default:
- x = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
- y = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
- left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
- right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
- bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
- top = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
- break;
- }
-
- // Write output coords.
- PointerCoords& out = mCurrentCookedPointerData.pointerCoords[i];
- out.clear();
- out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
- out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
- out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
- out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
- out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
- out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
- out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
- out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
- out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
- if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
- out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_1, left);
- out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_2, top);
- out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_3, right);
- out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_4, bottom);
- } else {
- out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
- out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
- }
-
- // Write output properties.
- PointerProperties& properties = mCurrentCookedPointerData.pointerProperties[i];
- uint32_t id = in.id;
- properties.clear();
- properties.id = id;
- properties.toolType = in.toolType;
-
- // Write id index.
- mCurrentCookedPointerData.idToIndex[id] = i;
- }
-}
-
-void TouchInputMapper::dispatchPointerUsage(nsecs_t when, uint32_t policyFlags,
- PointerUsage pointerUsage) {
- if (pointerUsage != mPointerUsage) {
- abortPointerUsage(when, policyFlags);
- mPointerUsage = pointerUsage;
- }
-
- switch (mPointerUsage) {
- case POINTER_USAGE_GESTURES:
- dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
- break;
- case POINTER_USAGE_STYLUS:
- dispatchPointerStylus(when, policyFlags);
- break;
- case POINTER_USAGE_MOUSE:
- dispatchPointerMouse(when, policyFlags);
- break;
- default:
- break;
- }
-}
-
-void TouchInputMapper::abortPointerUsage(nsecs_t when, uint32_t policyFlags) {
- switch (mPointerUsage) {
- case POINTER_USAGE_GESTURES:
- abortPointerGestures(when, policyFlags);
- break;
- case POINTER_USAGE_STYLUS:
- abortPointerStylus(when, policyFlags);
- break;
- case POINTER_USAGE_MOUSE:
- abortPointerMouse(when, policyFlags);
- break;
- default:
- break;
- }
-
- mPointerUsage = POINTER_USAGE_NONE;
-}
-
-void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
- bool isTimeout) {
- // Update current gesture coordinates.
- bool cancelPreviousGesture, finishPreviousGesture;
- bool sendEvents = preparePointerGestures(when,
- &cancelPreviousGesture, &finishPreviousGesture, isTimeout);
- if (!sendEvents) {
- return;
- }
- if (finishPreviousGesture) {
- cancelPreviousGesture = false;
- }
-
- // Update the pointer presentation and spots.
- if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
- mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
- if (finishPreviousGesture || cancelPreviousGesture) {
- mPointerController->clearSpots();
- }
- mPointerController->setSpots(mPointerGesture.currentGestureCoords,
- mPointerGesture.currentGestureIdToIndex,
- mPointerGesture.currentGestureIdBits);
- } else {
- mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
- }
-
- // Show or hide the pointer if needed.
- switch (mPointerGesture.currentGestureMode) {
- case PointerGesture::NEUTRAL:
- case PointerGesture::QUIET:
- if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
- && (mPointerGesture.lastGestureMode == PointerGesture::SWIPE
- || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)) {
- // Remind the user of where the pointer is after finishing a gesture with spots.
- mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL);
- }
- break;
- case PointerGesture::TAP:
- case PointerGesture::TAP_DRAG:
- case PointerGesture::BUTTON_CLICK_OR_DRAG:
- case PointerGesture::HOVER:
- case PointerGesture::PRESS:
- // Unfade the pointer when the current gesture manipulates the
- // area directly under the pointer.
- mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
- break;
- case PointerGesture::SWIPE:
- case PointerGesture::FREEFORM:
- // Fade the pointer when the current gesture manipulates a different
- // area and there are spots to guide the user experience.
- if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
- } else {
- mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
- }
- break;
- }
-
- // Send events!
- int32_t metaState = getContext()->getGlobalMetaState();
- int32_t buttonState = mCurrentButtonState;
-
- // Update last coordinates of pointers that have moved so that we observe the new
- // pointer positions at the same time as other pointers that have just gone up.
- bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP
- || mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG
- || mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
- || mPointerGesture.currentGestureMode == PointerGesture::PRESS
- || mPointerGesture.currentGestureMode == PointerGesture::SWIPE
- || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM;
- bool moveNeeded = false;
- if (down && !cancelPreviousGesture && !finishPreviousGesture
- && !mPointerGesture.lastGestureIdBits.isEmpty()
- && !mPointerGesture.currentGestureIdBits.isEmpty()) {
- BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value
- & mPointerGesture.lastGestureIdBits.value);
- moveNeeded = updateMovedPointers(mPointerGesture.currentGestureProperties,
- mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
- mPointerGesture.lastGestureProperties,
- mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
- movedGestureIdBits);
- if (buttonState != mLastButtonState) {
- moveNeeded = true;
- }
- }
-
- // Send motion events for all pointers that went up or were canceled.
- BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
- if (!dispatchedGestureIdBits.isEmpty()) {
- if (cancelPreviousGesture) {
- dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
- AMOTION_EVENT_EDGE_FLAG_NONE,
- mPointerGesture.lastGestureProperties,
- mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
- dispatchedGestureIdBits, -1,
- 0, 0, mPointerGesture.downTime);
-
- dispatchedGestureIdBits.clear();
- } else {
- BitSet32 upGestureIdBits;
- if (finishPreviousGesture) {
- upGestureIdBits = dispatchedGestureIdBits;
- } else {
- upGestureIdBits.value = dispatchedGestureIdBits.value
- & ~mPointerGesture.currentGestureIdBits.value;
- }
- while (!upGestureIdBits.isEmpty()) {
- uint32_t id = upGestureIdBits.clearFirstMarkedBit();
-
- dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_POINTER_UP, 0,
- metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- mPointerGesture.lastGestureProperties,
- mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
- dispatchedGestureIdBits, id,
- 0, 0, mPointerGesture.downTime);
-
- dispatchedGestureIdBits.clearBit(id);
- }
- }
- }
-
- // Send motion events for all pointers that moved.
- if (moveNeeded) {
- dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- mPointerGesture.currentGestureProperties,
- mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
- dispatchedGestureIdBits, -1,
- 0, 0, mPointerGesture.downTime);
- }
-
- // Send motion events for all pointers that went down.
- if (down) {
- BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value
- & ~dispatchedGestureIdBits.value);
- while (!downGestureIdBits.isEmpty()) {
- uint32_t id = downGestureIdBits.clearFirstMarkedBit();
- dispatchedGestureIdBits.markBit(id);
-
- if (dispatchedGestureIdBits.count() == 1) {
- mPointerGesture.downTime = when;
- }
-
- dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
- mPointerGesture.currentGestureProperties,
- mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
- dispatchedGestureIdBits, id,
- 0, 0, mPointerGesture.downTime);
- }
- }
-
- // Send motion events for hover.
- if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
- dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
- metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- mPointerGesture.currentGestureProperties,
- mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
- mPointerGesture.currentGestureIdBits, -1,
- 0, 0, mPointerGesture.downTime);
- } else if (dispatchedGestureIdBits.isEmpty()
- && !mPointerGesture.lastGestureIdBits.isEmpty()) {
- // Synthesize a hover move event after all pointers go up to indicate that
- // the pointer is hovering again even if the user is not currently touching
- // the touch pad. This ensures that a view will receive a fresh hover enter
- // event after a tap.
- float x, y;
- mPointerController->getPosition(&x, &y);
-
- PointerProperties pointerProperties;
- pointerProperties.clear();
- pointerProperties.id = 0;
- pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
-
- PointerCoords pointerCoords;
- pointerCoords.clear();
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
-
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
- metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- mViewport.displayId, 1, &pointerProperties, &pointerCoords,
- 0, 0, mPointerGesture.downTime);
- getListener()->notifyMotion(&args);
- }
-
- // Update state.
- mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode;
- if (!down) {
- mPointerGesture.lastGestureIdBits.clear();
- } else {
- mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits;
- for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) {
- uint32_t id = idBits.clearFirstMarkedBit();
- uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
- mPointerGesture.lastGestureProperties[index].copyFrom(
- mPointerGesture.currentGestureProperties[index]);
- mPointerGesture.lastGestureCoords[index].copyFrom(
- mPointerGesture.currentGestureCoords[index]);
- mPointerGesture.lastGestureIdToIndex[id] = index;
- }
- }
-}
-
-void TouchInputMapper::abortPointerGestures(nsecs_t when, uint32_t policyFlags) {
- // Cancel previously dispatches pointers.
- if (!mPointerGesture.lastGestureIdBits.isEmpty()) {
- int32_t metaState = getContext()->getGlobalMetaState();
- int32_t buttonState = mCurrentButtonState;
- dispatchMotion(when, policyFlags, mSource,
- AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
- AMOTION_EVENT_EDGE_FLAG_NONE,
- mPointerGesture.lastGestureProperties,
- mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
- mPointerGesture.lastGestureIdBits, -1,
- 0, 0, mPointerGesture.downTime);
- }
-
- // Reset the current pointer gesture.
- mPointerGesture.reset();
- mPointerVelocityControl.reset();
-
- // Remove any current spots.
- if (mPointerController != NULL) {
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
- mPointerController->clearSpots();
- }
-}
-
-bool TouchInputMapper::preparePointerGestures(nsecs_t when,
- bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) {
- *outCancelPreviousGesture = false;
- *outFinishPreviousGesture = false;
-
- // Handle TAP timeout.
- if (isTimeout) {
-#if DEBUG_GESTURES
- ALOGD("Gestures: Processing timeout");
-#endif
-
- if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
- if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
- // The tap/drag timeout has not yet expired.
- getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime
- + mConfig.pointerGestureTapDragInterval);
- } else {
- // The tap is finished.
-#if DEBUG_GESTURES
- ALOGD("Gestures: TAP finished");
-#endif
- *outFinishPreviousGesture = true;
-
- mPointerGesture.activeGestureId = -1;
- mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
- mPointerGesture.currentGestureIdBits.clear();
-
- mPointerVelocityControl.reset();
- return true;
- }
- }
-
- // We did not handle this timeout.
- return false;
- }
-
- const uint32_t currentFingerCount = mCurrentFingerIdBits.count();
- const uint32_t lastFingerCount = mLastFingerIdBits.count();
-
- // Update the velocity tracker.
- {
- VelocityTracker::Position positions[MAX_POINTERS];
- uint32_t count = 0;
- for (BitSet32 idBits(mCurrentFingerIdBits); !idBits.isEmpty(); count++) {
- uint32_t id = idBits.clearFirstMarkedBit();
- const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
- positions[count].x = pointer.x * mPointerXMovementScale;
- positions[count].y = pointer.y * mPointerYMovementScale;
- }
- mPointerGesture.velocityTracker.addMovement(when,
- mCurrentFingerIdBits, positions);
- }
-
- // If the gesture ever enters a mode other than TAP, HOVER or TAP_DRAG, without first returning
- // to NEUTRAL, then we should not generate tap event.
- if (mPointerGesture.lastGestureMode != PointerGesture::HOVER
- && mPointerGesture.lastGestureMode != PointerGesture::TAP
- && mPointerGesture.lastGestureMode != PointerGesture::TAP_DRAG) {
- mPointerGesture.resetTap();
- }
-
- // Pick a new active touch id if needed.
- // Choose an arbitrary pointer that just went down, if there is one.
- // Otherwise choose an arbitrary remaining pointer.
- // This guarantees we always have an active touch id when there is at least one pointer.
- // We keep the same active touch id for as long as possible.
- bool activeTouchChanged = false;
- int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
- int32_t activeTouchId = lastActiveTouchId;
- if (activeTouchId < 0) {
- if (!mCurrentFingerIdBits.isEmpty()) {
- activeTouchChanged = true;
- activeTouchId = mPointerGesture.activeTouchId =
- mCurrentFingerIdBits.firstMarkedBit();
- mPointerGesture.firstTouchTime = when;
- }
- } else if (!mCurrentFingerIdBits.hasBit(activeTouchId)) {
- activeTouchChanged = true;
- if (!mCurrentFingerIdBits.isEmpty()) {
- activeTouchId = mPointerGesture.activeTouchId =
- mCurrentFingerIdBits.firstMarkedBit();
- } else {
- activeTouchId = mPointerGesture.activeTouchId = -1;
- }
- }
-
- // Determine whether we are in quiet time.
- bool isQuietTime = false;
- if (activeTouchId < 0) {
- mPointerGesture.resetQuietTime();
- } else {
- isQuietTime = when < mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval;
- if (!isQuietTime) {
- if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS
- || mPointerGesture.lastGestureMode == PointerGesture::SWIPE
- || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)
- && currentFingerCount < 2) {
- // Enter quiet time when exiting swipe or freeform state.
- // This is to prevent accidentally entering the hover state and flinging the
- // pointer when finishing a swipe and there is still one pointer left onscreen.
- isQuietTime = true;
- } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
- && currentFingerCount >= 2
- && !isPointerDown(mCurrentButtonState)) {
- // Enter quiet time when releasing the button and there are still two or more
- // fingers down. This may indicate that one finger was used to press the button
- // but it has not gone up yet.
- isQuietTime = true;
- }
- if (isQuietTime) {
- mPointerGesture.quietTime = when;
- }
- }
- }
-
- // Switch states based on button and pointer state.
- if (isQuietTime) {
- // Case 1: Quiet time. (QUIET)
-#if DEBUG_GESTURES
- ALOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime
- + mConfig.pointerGestureQuietInterval - when) * 0.000001f);
-#endif
- if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) {
- *outFinishPreviousGesture = true;
- }
-
- mPointerGesture.activeGestureId = -1;
- mPointerGesture.currentGestureMode = PointerGesture::QUIET;
- mPointerGesture.currentGestureIdBits.clear();
-
- mPointerVelocityControl.reset();
- } else if (isPointerDown(mCurrentButtonState)) {
- // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
- // The pointer follows the active touch point.
- // Emit DOWN, MOVE, UP events at the pointer location.
- //
- // Only the active touch matters; other fingers are ignored. This policy helps
- // to handle the case where the user places a second finger on the touch pad
- // to apply the necessary force to depress an integrated button below the surface.
- // We don't want the second finger to be delivered to applications.
- //
- // For this to work well, we need to make sure to track the pointer that is really
- // active. If the user first puts one finger down to click then adds another
- // finger to drag then the active pointer should switch to the finger that is
- // being dragged.
-#if DEBUG_GESTURES
- ALOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
- "currentFingerCount=%d", activeTouchId, currentFingerCount);
-#endif
- // Reset state when just starting.
- if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
- *outFinishPreviousGesture = true;
- mPointerGesture.activeGestureId = 0;
- }
-
- // Switch pointers if needed.
- // Find the fastest pointer and follow it.
- if (activeTouchId >= 0 && currentFingerCount > 1) {
- int32_t bestId = -1;
- float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed;
- for (BitSet32 idBits(mCurrentFingerIdBits); !idBits.isEmpty(); ) {
- uint32_t id = idBits.clearFirstMarkedBit();
- float vx, vy;
- if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
- float speed = hypotf(vx, vy);
- if (speed > bestSpeed) {
- bestId = id;
- bestSpeed = speed;
- }
- }
- }
- if (bestId >= 0 && bestId != activeTouchId) {
- mPointerGesture.activeTouchId = activeTouchId = bestId;
- activeTouchChanged = true;
-#if DEBUG_GESTURES
- ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
- "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
-#endif
- }
- }
-
- if (activeTouchId >= 0 && mLastFingerIdBits.hasBit(activeTouchId)) {
- const RawPointerData::Pointer& currentPointer =
- mCurrentRawPointerData.pointerForId(activeTouchId);
- const RawPointerData::Pointer& lastPointer =
- mLastRawPointerData.pointerForId(activeTouchId);
- float deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
- float deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
-
- rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
- mPointerVelocityControl.move(when, &deltaX, &deltaY);
-
- // Move the pointer using a relative motion.
- // When using spots, the click will occur at the position of the anchor
- // spot and all other spots will move there.
- mPointerController->move(deltaX, deltaY);
- } else {
- mPointerVelocityControl.reset();
- }
-
- float x, y;
- mPointerController->getPosition(&x, &y);
-
- mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG;
- mPointerGesture.currentGestureIdBits.clear();
- mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
- mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
- mPointerGesture.currentGestureProperties[0].clear();
- mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
- mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
- mPointerGesture.currentGestureCoords[0].clear();
- mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
- mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
- mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
- } else if (currentFingerCount == 0) {
- // Case 3. No fingers down and button is not pressed. (NEUTRAL)
- if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) {
- *outFinishPreviousGesture = true;
- }
-
- // Watch for taps coming out of HOVER or TAP_DRAG mode.
- // Checking for taps after TAP_DRAG allows us to detect double-taps.
- bool tapped = false;
- if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
- || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
- && lastFingerCount == 1) {
- if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) {
- float x, y;
- mPointerController->getPosition(&x, &y);
- if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
- && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
-#if DEBUG_GESTURES
- ALOGD("Gestures: TAP");
-#endif
-
- mPointerGesture.tapUpTime = when;
- getContext()->requestTimeoutAtTime(when
- + mConfig.pointerGestureTapDragInterval);
-
- mPointerGesture.activeGestureId = 0;
- mPointerGesture.currentGestureMode = PointerGesture::TAP;
- mPointerGesture.currentGestureIdBits.clear();
- mPointerGesture.currentGestureIdBits.markBit(
- mPointerGesture.activeGestureId);
- mPointerGesture.currentGestureIdToIndex[
- mPointerGesture.activeGestureId] = 0;
- mPointerGesture.currentGestureProperties[0].clear();
- mPointerGesture.currentGestureProperties[0].id =
- mPointerGesture.activeGestureId;
- mPointerGesture.currentGestureProperties[0].toolType =
- AMOTION_EVENT_TOOL_TYPE_FINGER;
- mPointerGesture.currentGestureCoords[0].clear();
- mPointerGesture.currentGestureCoords[0].setAxisValue(
- AMOTION_EVENT_AXIS_X, mPointerGesture.tapX);
- mPointerGesture.currentGestureCoords[0].setAxisValue(
- AMOTION_EVENT_AXIS_Y, mPointerGesture.tapY);
- mPointerGesture.currentGestureCoords[0].setAxisValue(
- AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
-
- tapped = true;
- } else {
-#if DEBUG_GESTURES
- ALOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f",
- x - mPointerGesture.tapX,
- y - mPointerGesture.tapY);
-#endif
- }
- } else {
-#if DEBUG_GESTURES
- if (mPointerGesture.tapDownTime != LLONG_MIN) {
- ALOGD("Gestures: Not a TAP, %0.3fms since down",
- (when - mPointerGesture.tapDownTime) * 0.000001f);
- } else {
- ALOGD("Gestures: Not a TAP, incompatible mode transitions");
- }
-#endif
- }
- }
-
- mPointerVelocityControl.reset();
-
- if (!tapped) {
-#if DEBUG_GESTURES
- ALOGD("Gestures: NEUTRAL");
-#endif
- mPointerGesture.activeGestureId = -1;
- mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
- mPointerGesture.currentGestureIdBits.clear();
- }
- } else if (currentFingerCount == 1) {
- // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
- // The pointer follows the active touch point.
- // When in HOVER, emit HOVER_MOVE events at the pointer location.
- // When in TAP_DRAG, emit MOVE events at the pointer location.
- ALOG_ASSERT(activeTouchId >= 0);
-
- mPointerGesture.currentGestureMode = PointerGesture::HOVER;
- if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
- if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
- float x, y;
- mPointerController->getPosition(&x, &y);
- if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
- && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
- mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
- } else {
-#if DEBUG_GESTURES
- ALOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
- x - mPointerGesture.tapX,
- y - mPointerGesture.tapY);
-#endif
- }
- } else {
-#if DEBUG_GESTURES
- ALOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
- (when - mPointerGesture.tapUpTime) * 0.000001f);
-#endif
- }
- } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) {
- mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
- }
-
- if (mLastFingerIdBits.hasBit(activeTouchId)) {
- const RawPointerData::Pointer& currentPointer =
- mCurrentRawPointerData.pointerForId(activeTouchId);
- const RawPointerData::Pointer& lastPointer =
- mLastRawPointerData.pointerForId(activeTouchId);
- float deltaX = (currentPointer.x - lastPointer.x)
- * mPointerXMovementScale;
- float deltaY = (currentPointer.y - lastPointer.y)
- * mPointerYMovementScale;
-
- rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
- mPointerVelocityControl.move(when, &deltaX, &deltaY);
-
- // Move the pointer using a relative motion.
- // When using spots, the hover or drag will occur at the position of the anchor spot.
- mPointerController->move(deltaX, deltaY);
- } else {
- mPointerVelocityControl.reset();
- }
-
- bool down;
- if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) {
-#if DEBUG_GESTURES
- ALOGD("Gestures: TAP_DRAG");
-#endif
- down = true;
- } else {
-#if DEBUG_GESTURES
- ALOGD("Gestures: HOVER");
-#endif
- if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) {
- *outFinishPreviousGesture = true;
- }
- mPointerGesture.activeGestureId = 0;
- down = false;
- }
-
- float x, y;
- mPointerController->getPosition(&x, &y);
-
- mPointerGesture.currentGestureIdBits.clear();
- mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
- mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
- mPointerGesture.currentGestureProperties[0].clear();
- mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
- mPointerGesture.currentGestureProperties[0].toolType =
- AMOTION_EVENT_TOOL_TYPE_FINGER;
- mPointerGesture.currentGestureCoords[0].clear();
- mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
- mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
- mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
- down ? 1.0f : 0.0f);
-
- if (lastFingerCount == 0 && currentFingerCount != 0) {
- mPointerGesture.resetTap();
- mPointerGesture.tapDownTime = when;
- mPointerGesture.tapX = x;
- mPointerGesture.tapY = y;
- }
- } else {
- // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
- // We need to provide feedback for each finger that goes down so we cannot wait
- // for the fingers to move before deciding what to do.
- //
- // The ambiguous case is deciding what to do when there are two fingers down but they
- // have not moved enough to determine whether they are part of a drag or part of a
- // freeform gesture, or just a press or long-press at the pointer location.
- //
- // When there are two fingers we start with the PRESS hypothesis and we generate a
- // down at the pointer location.
- //
- // When the two fingers move enough or when additional fingers are added, we make
- // a decision to transition into SWIPE or FREEFORM mode accordingly.
- ALOG_ASSERT(activeTouchId >= 0);
-
- bool settled = when >= mPointerGesture.firstTouchTime
- + mConfig.pointerGestureMultitouchSettleInterval;
- if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
- && mPointerGesture.lastGestureMode != PointerGesture::SWIPE
- && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
- *outFinishPreviousGesture = true;
- } else if (!settled && currentFingerCount > lastFingerCount) {
- // Additional pointers have gone down but not yet settled.
- // Reset the gesture.
-#if DEBUG_GESTURES
- ALOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
- "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
- + mConfig.pointerGestureMultitouchSettleInterval - when)
- * 0.000001f);
-#endif
- *outCancelPreviousGesture = true;
- } else {
- // Continue previous gesture.
- mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
- }
-
- if (*outFinishPreviousGesture || *outCancelPreviousGesture) {
- mPointerGesture.currentGestureMode = PointerGesture::PRESS;
- mPointerGesture.activeGestureId = 0;
- mPointerGesture.referenceIdBits.clear();
- mPointerVelocityControl.reset();
-
- // Use the centroid and pointer location as the reference points for the gesture.
-#if DEBUG_GESTURES
- ALOGD("Gestures: Using centroid as reference for MULTITOUCH, "
- "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
- + mConfig.pointerGestureMultitouchSettleInterval - when)
- * 0.000001f);
-#endif
- mCurrentRawPointerData.getCentroidOfTouchingPointers(
- &mPointerGesture.referenceTouchX,
- &mPointerGesture.referenceTouchY);
- mPointerController->getPosition(&mPointerGesture.referenceGestureX,
- &mPointerGesture.referenceGestureY);
- }
-
- // Clear the reference deltas for fingers not yet included in the reference calculation.
- for (BitSet32 idBits(mCurrentFingerIdBits.value
- & ~mPointerGesture.referenceIdBits.value); !idBits.isEmpty(); ) {
- uint32_t id = idBits.clearFirstMarkedBit();
- mPointerGesture.referenceDeltas[id].dx = 0;
- mPointerGesture.referenceDeltas[id].dy = 0;
- }
- mPointerGesture.referenceIdBits = mCurrentFingerIdBits;
-
- // Add delta for all fingers and calculate a common movement delta.
- float commonDeltaX = 0, commonDeltaY = 0;
- BitSet32 commonIdBits(mLastFingerIdBits.value
- & mCurrentFingerIdBits.value);
- for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
- bool first = (idBits == commonIdBits);
- uint32_t id = idBits.clearFirstMarkedBit();
- const RawPointerData::Pointer& cpd = mCurrentRawPointerData.pointerForId(id);
- const RawPointerData::Pointer& lpd = mLastRawPointerData.pointerForId(id);
- PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
- delta.dx += cpd.x - lpd.x;
- delta.dy += cpd.y - lpd.y;
-
- if (first) {
- commonDeltaX = delta.dx;
- commonDeltaY = delta.dy;
- } else {
- commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
- commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
- }
- }
-
- // Consider transitions from PRESS to SWIPE or MULTITOUCH.
- if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
- float dist[MAX_POINTER_ID + 1];
- int32_t distOverThreshold = 0;
- for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
- uint32_t id = idBits.clearFirstMarkedBit();
- PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
- dist[id] = hypotf(delta.dx * mPointerXZoomScale,
- delta.dy * mPointerYZoomScale);
- if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) {
- distOverThreshold += 1;
- }
- }
-
- // Only transition when at least two pointers have moved further than
- // the minimum distance threshold.
- if (distOverThreshold >= 2) {
- if (currentFingerCount > 2) {
- // There are more than two pointers, switch to FREEFORM.
-#if DEBUG_GESTURES
- ALOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
- currentFingerCount);
-#endif
- *outCancelPreviousGesture = true;
- mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
- } else {
- // There are exactly two pointers.
- BitSet32 idBits(mCurrentFingerIdBits);
- uint32_t id1 = idBits.clearFirstMarkedBit();
- uint32_t id2 = idBits.firstMarkedBit();
- const RawPointerData::Pointer& p1 = mCurrentRawPointerData.pointerForId(id1);
- const RawPointerData::Pointer& p2 = mCurrentRawPointerData.pointerForId(id2);
- float mutualDistance = distance(p1.x, p1.y, p2.x, p2.y);
- if (mutualDistance > mPointerGestureMaxSwipeWidth) {
- // There are two pointers but they are too far apart for a SWIPE,
- // switch to FREEFORM.
-#if DEBUG_GESTURES
- ALOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
- mutualDistance, mPointerGestureMaxSwipeWidth);
-#endif
- *outCancelPreviousGesture = true;
- mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
- } else {
- // There are two pointers. Wait for both pointers to start moving
- // before deciding whether this is a SWIPE or FREEFORM gesture.
- float dist1 = dist[id1];
- float dist2 = dist[id2];
- if (dist1 >= mConfig.pointerGestureMultitouchMinDistance
- && dist2 >= mConfig.pointerGestureMultitouchMinDistance) {
- // Calculate the dot product of the displacement vectors.
- // When the vectors are oriented in approximately the same direction,
- // the angle betweeen them is near zero and the cosine of the angle
- // approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
- PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1];
- PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2];
- float dx1 = delta1.dx * mPointerXZoomScale;
- float dy1 = delta1.dy * mPointerYZoomScale;
- float dx2 = delta2.dx * mPointerXZoomScale;
- float dy2 = delta2.dy * mPointerYZoomScale;
- float dot = dx1 * dx2 + dy1 * dy2;
- float cosine = dot / (dist1 * dist2); // denominator always > 0
- if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) {
- // Pointers are moving in the same direction. Switch to SWIPE.
-#if DEBUG_GESTURES
- ALOGD("Gestures: PRESS transitioned to SWIPE, "
- "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
- "cosine %0.3f >= %0.3f",
- dist1, mConfig.pointerGestureMultitouchMinDistance,
- dist2, mConfig.pointerGestureMultitouchMinDistance,
- cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
-#endif
- mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
- } else {
- // Pointers are moving in different directions. Switch to FREEFORM.
-#if DEBUG_GESTURES
- ALOGD("Gestures: PRESS transitioned to FREEFORM, "
- "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
- "cosine %0.3f < %0.3f",
- dist1, mConfig.pointerGestureMultitouchMinDistance,
- dist2, mConfig.pointerGestureMultitouchMinDistance,
- cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
-#endif
- *outCancelPreviousGesture = true;
- mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
- }
- }
- }
- }
- }
- } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
- // Switch from SWIPE to FREEFORM if additional pointers go down.
- // Cancel previous gesture.
- if (currentFingerCount > 2) {
-#if DEBUG_GESTURES
- ALOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
- currentFingerCount);
-#endif
- *outCancelPreviousGesture = true;
- mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
- }
- }
-
- // Move the reference points based on the overall group motion of the fingers
- // except in PRESS mode while waiting for a transition to occur.
- if (mPointerGesture.currentGestureMode != PointerGesture::PRESS
- && (commonDeltaX || commonDeltaY)) {
- for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
- uint32_t id = idBits.clearFirstMarkedBit();
- PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
- delta.dx = 0;
- delta.dy = 0;
- }
-
- mPointerGesture.referenceTouchX += commonDeltaX;
- mPointerGesture.referenceTouchY += commonDeltaY;
-
- commonDeltaX *= mPointerXMovementScale;
- commonDeltaY *= mPointerYMovementScale;
-
- rotateDelta(mSurfaceOrientation, &commonDeltaX, &commonDeltaY);
- mPointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
-
- mPointerGesture.referenceGestureX += commonDeltaX;
- mPointerGesture.referenceGestureY += commonDeltaY;
- }
-
- // Report gestures.
- if (mPointerGesture.currentGestureMode == PointerGesture::PRESS
- || mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
- // PRESS or SWIPE mode.
-#if DEBUG_GESTURES
- ALOGD("Gestures: PRESS or SWIPE activeTouchId=%d,"
- "activeGestureId=%d, currentTouchPointerCount=%d",
- activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
-#endif
- ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
-
- mPointerGesture.currentGestureIdBits.clear();
- mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
- mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
- mPointerGesture.currentGestureProperties[0].clear();
- mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
- mPointerGesture.currentGestureProperties[0].toolType =
- AMOTION_EVENT_TOOL_TYPE_FINGER;
- mPointerGesture.currentGestureCoords[0].clear();
- mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
- mPointerGesture.referenceGestureX);
- mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
- mPointerGesture.referenceGestureY);
- mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
- } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
- // FREEFORM mode.
-#if DEBUG_GESTURES
- ALOGD("Gestures: FREEFORM activeTouchId=%d,"
- "activeGestureId=%d, currentTouchPointerCount=%d",
- activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
-#endif
- ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
-
- mPointerGesture.currentGestureIdBits.clear();
-
- BitSet32 mappedTouchIdBits;
- BitSet32 usedGestureIdBits;
- if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
- // Initially, assign the active gesture id to the active touch point
- // if there is one. No other touch id bits are mapped yet.
- if (!*outCancelPreviousGesture) {
- mappedTouchIdBits.markBit(activeTouchId);
- usedGestureIdBits.markBit(mPointerGesture.activeGestureId);
- mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] =
- mPointerGesture.activeGestureId;
- } else {
- mPointerGesture.activeGestureId = -1;
- }
- } else {
- // Otherwise, assume we mapped all touches from the previous frame.
- // Reuse all mappings that are still applicable.
- mappedTouchIdBits.value = mLastFingerIdBits.value
- & mCurrentFingerIdBits.value;
- usedGestureIdBits = mPointerGesture.lastGestureIdBits;
-
- // Check whether we need to choose a new active gesture id because the
- // current went went up.
- for (BitSet32 upTouchIdBits(mLastFingerIdBits.value
- & ~mCurrentFingerIdBits.value);
- !upTouchIdBits.isEmpty(); ) {
- uint32_t upTouchId = upTouchIdBits.clearFirstMarkedBit();
- uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
- if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) {
- mPointerGesture.activeGestureId = -1;
- break;
- }
- }
- }
-
-#if DEBUG_GESTURES
- ALOGD("Gestures: FREEFORM follow up "
- "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
- "activeGestureId=%d",
- mappedTouchIdBits.value, usedGestureIdBits.value,
- mPointerGesture.activeGestureId);
-#endif
-
- BitSet32 idBits(mCurrentFingerIdBits);
- for (uint32_t i = 0; i < currentFingerCount; i++) {
- uint32_t touchId = idBits.clearFirstMarkedBit();
- uint32_t gestureId;
- if (!mappedTouchIdBits.hasBit(touchId)) {
- gestureId = usedGestureIdBits.markFirstUnmarkedBit();
- mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId;
-#if DEBUG_GESTURES
- ALOGD("Gestures: FREEFORM "
- "new mapping for touch id %d -> gesture id %d",
- touchId, gestureId);
-#endif
- } else {
- gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId];
-#if DEBUG_GESTURES
- ALOGD("Gestures: FREEFORM "
- "existing mapping for touch id %d -> gesture id %d",
- touchId, gestureId);
-#endif
- }
- mPointerGesture.currentGestureIdBits.markBit(gestureId);
- mPointerGesture.currentGestureIdToIndex[gestureId] = i;
-
- const RawPointerData::Pointer& pointer =
- mCurrentRawPointerData.pointerForId(touchId);
- float deltaX = (pointer.x - mPointerGesture.referenceTouchX)
- * mPointerXZoomScale;
- float deltaY = (pointer.y - mPointerGesture.referenceTouchY)
- * mPointerYZoomScale;
- rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
-
- mPointerGesture.currentGestureProperties[i].clear();
- mPointerGesture.currentGestureProperties[i].id = gestureId;
- mPointerGesture.currentGestureProperties[i].toolType =
- AMOTION_EVENT_TOOL_TYPE_FINGER;
- mPointerGesture.currentGestureCoords[i].clear();
- mPointerGesture.currentGestureCoords[i].setAxisValue(
- AMOTION_EVENT_AXIS_X, mPointerGesture.referenceGestureX + deltaX);
- mPointerGesture.currentGestureCoords[i].setAxisValue(
- AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY + deltaY);
- mPointerGesture.currentGestureCoords[i].setAxisValue(
- AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
- }
-
- if (mPointerGesture.activeGestureId < 0) {
- mPointerGesture.activeGestureId =
- mPointerGesture.currentGestureIdBits.firstMarkedBit();
-#if DEBUG_GESTURES
- ALOGD("Gestures: FREEFORM new "
- "activeGestureId=%d", mPointerGesture.activeGestureId);
-#endif
- }
- }
- }
-
- mPointerController->setButtonState(mCurrentButtonState);
-
-#if DEBUG_GESTURES
- ALOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
- "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
- "lastGestureMode=%d, lastGestureIdBits=0x%08x",
- toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
- mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
- mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
- for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty(); ) {
- uint32_t id = idBits.clearFirstMarkedBit();
- uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
- const PointerProperties& properties = mPointerGesture.currentGestureProperties[index];
- const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
- ALOGD(" currentGesture[%d]: index=%d, toolType=%d, "
- "x=%0.3f, y=%0.3f, pressure=%0.3f",
- id, index, properties.toolType,
- coords.getAxisValue(AMOTION_EVENT_AXIS_X),
- coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
- coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
- }
- for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty(); ) {
- uint32_t id = idBits.clearFirstMarkedBit();
- uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
- const PointerProperties& properties = mPointerGesture.lastGestureProperties[index];
- const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
- ALOGD(" lastGesture[%d]: index=%d, toolType=%d, "
- "x=%0.3f, y=%0.3f, pressure=%0.3f",
- id, index, properties.toolType,
- coords.getAxisValue(AMOTION_EVENT_AXIS_X),
- coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
- coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
- }
-#endif
- return true;
-}
-
-void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) {
- mPointerSimple.currentCoords.clear();
- mPointerSimple.currentProperties.clear();
-
- bool down, hovering;
- if (!mCurrentStylusIdBits.isEmpty()) {
- uint32_t id = mCurrentStylusIdBits.firstMarkedBit();
- uint32_t index = mCurrentCookedPointerData.idToIndex[id];
- float x = mCurrentCookedPointerData.pointerCoords[index].getX();
- float y = mCurrentCookedPointerData.pointerCoords[index].getY();
- mPointerController->setPosition(x, y);
-
- hovering = mCurrentCookedPointerData.hoveringIdBits.hasBit(id);
- down = !hovering;
-
- mPointerController->getPosition(&x, &y);
- mPointerSimple.currentCoords.copyFrom(mCurrentCookedPointerData.pointerCoords[index]);
- mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
- mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
- mPointerSimple.currentProperties.id = 0;
- mPointerSimple.currentProperties.toolType =
- mCurrentCookedPointerData.pointerProperties[index].toolType;
- } else {
- down = false;
- hovering = false;
- }
-
- dispatchPointerSimple(when, policyFlags, down, hovering);
-}
-
-void TouchInputMapper::abortPointerStylus(nsecs_t when, uint32_t policyFlags) {
- abortPointerSimple(when, policyFlags);
-}
-
-void TouchInputMapper::dispatchPointerMouse(nsecs_t when, uint32_t policyFlags) {
- mPointerSimple.currentCoords.clear();
- mPointerSimple.currentProperties.clear();
-
- bool down, hovering;
- if (!mCurrentMouseIdBits.isEmpty()) {
- uint32_t id = mCurrentMouseIdBits.firstMarkedBit();
- uint32_t currentIndex = mCurrentRawPointerData.idToIndex[id];
- if (mLastMouseIdBits.hasBit(id)) {
- uint32_t lastIndex = mCurrentRawPointerData.idToIndex[id];
- float deltaX = (mCurrentRawPointerData.pointers[currentIndex].x
- - mLastRawPointerData.pointers[lastIndex].x)
- * mPointerXMovementScale;
- float deltaY = (mCurrentRawPointerData.pointers[currentIndex].y
- - mLastRawPointerData.pointers[lastIndex].y)
- * mPointerYMovementScale;
-
- rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
- mPointerVelocityControl.move(when, &deltaX, &deltaY);
-
- mPointerController->move(deltaX, deltaY);
- } else {
- mPointerVelocityControl.reset();
- }
-
- down = isPointerDown(mCurrentButtonState);
- hovering = !down;
-
- float x, y;
- mPointerController->getPosition(&x, &y);
- mPointerSimple.currentCoords.copyFrom(
- mCurrentCookedPointerData.pointerCoords[currentIndex]);
- mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
- mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
- mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
- hovering ? 0.0f : 1.0f);
- mPointerSimple.currentProperties.id = 0;
- mPointerSimple.currentProperties.toolType =
- mCurrentCookedPointerData.pointerProperties[currentIndex].toolType;
- } else {
- mPointerVelocityControl.reset();
-
- down = false;
- hovering = false;
- }
-
- dispatchPointerSimple(when, policyFlags, down, hovering);
-}
-
-void TouchInputMapper::abortPointerMouse(nsecs_t when, uint32_t policyFlags) {
- abortPointerSimple(when, policyFlags);
-
- mPointerVelocityControl.reset();
-}
-
-void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
- bool down, bool hovering) {
- int32_t metaState = getContext()->getGlobalMetaState();
-
- if (mPointerController != NULL) {
- if (down || hovering) {
- mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
- mPointerController->clearSpots();
- mPointerController->setButtonState(mCurrentButtonState);
- mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
- } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
- }
- }
-
- if (mPointerSimple.down && !down) {
- mPointerSimple.down = false;
-
- // Send up.
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_UP, 0, metaState, mLastButtonState, 0,
- mViewport.displayId,
- 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
- mOrientedXPrecision, mOrientedYPrecision,
- mPointerSimple.downTime);
- getListener()->notifyMotion(&args);
- }
-
- if (mPointerSimple.hovering && !hovering) {
- mPointerSimple.hovering = false;
-
- // Send hover exit.
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0,
- mViewport.displayId,
- 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
- mOrientedXPrecision, mOrientedYPrecision,
- mPointerSimple.downTime);
- getListener()->notifyMotion(&args);
- }
-
- if (down) {
- if (!mPointerSimple.down) {
- mPointerSimple.down = true;
- mPointerSimple.downTime = when;
-
- // Send down.
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_DOWN, 0, metaState, mCurrentButtonState, 0,
- mViewport.displayId,
- 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
- mOrientedXPrecision, mOrientedYPrecision,
- mPointerSimple.downTime);
- getListener()->notifyMotion(&args);
- }
-
- // Send move.
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_MOVE, 0, metaState, mCurrentButtonState, 0,
- mViewport.displayId,
- 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
- mOrientedXPrecision, mOrientedYPrecision,
- mPointerSimple.downTime);
- getListener()->notifyMotion(&args);
- }
-
- if (hovering) {
- if (!mPointerSimple.hovering) {
- mPointerSimple.hovering = true;
-
- // Send hover enter.
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0,
- mViewport.displayId,
- 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
- mOrientedXPrecision, mOrientedYPrecision,
- mPointerSimple.downTime);
- getListener()->notifyMotion(&args);
- }
-
- // Send hover move.
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0,
- mViewport.displayId,
- 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
- mOrientedXPrecision, mOrientedYPrecision,
- mPointerSimple.downTime);
- getListener()->notifyMotion(&args);
- }
-
- if (mCurrentRawVScroll || mCurrentRawHScroll) {
- float vscroll = mCurrentRawVScroll;
- float hscroll = mCurrentRawHScroll;
- mWheelYVelocityControl.move(when, NULL, &vscroll);
- mWheelXVelocityControl.move(when, &hscroll, NULL);
-
- // Send scroll.
- PointerCoords pointerCoords;
- pointerCoords.copyFrom(mPointerSimple.currentCoords);
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
- pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
-
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
- AMOTION_EVENT_ACTION_SCROLL, 0, metaState, mCurrentButtonState, 0,
- mViewport.displayId,
- 1, &mPointerSimple.currentProperties, &pointerCoords,
- mOrientedXPrecision, mOrientedYPrecision,
- mPointerSimple.downTime);
- getListener()->notifyMotion(&args);
- }
-
- // Save state.
- if (down || hovering) {
- mPointerSimple.lastCoords.copyFrom(mPointerSimple.currentCoords);
- mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties);
- } else {
- mPointerSimple.reset();
- }
-}
-
-void TouchInputMapper::abortPointerSimple(nsecs_t when, uint32_t policyFlags) {
- mPointerSimple.currentCoords.clear();
- mPointerSimple.currentProperties.clear();
-
- dispatchPointerSimple(when, policyFlags, false, false);
-}
-
-void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
- int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
- const PointerProperties* properties, const PointerCoords* coords,
- const uint32_t* idToIndex, BitSet32 idBits,
- int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) {
- PointerCoords pointerCoords[MAX_POINTERS];
- PointerProperties pointerProperties[MAX_POINTERS];
- uint32_t pointerCount = 0;
- while (!idBits.isEmpty()) {
- uint32_t id = idBits.clearFirstMarkedBit();
- uint32_t index = idToIndex[id];
- pointerProperties[pointerCount].copyFrom(properties[index]);
- pointerCoords[pointerCount].copyFrom(coords[index]);
-
- if (changedId >= 0 && id == uint32_t(changedId)) {
- action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
- }
-
- pointerCount += 1;
- }
-
- ALOG_ASSERT(pointerCount != 0);
-
- if (changedId >= 0 && pointerCount == 1) {
- // Replace initial down and final up action.
- // We can compare the action without masking off the changed pointer index
- // because we know the index is 0.
- if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
- action = AMOTION_EVENT_ACTION_DOWN;
- } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
- action = AMOTION_EVENT_ACTION_UP;
- } else {
- // Can't happen.
- ALOG_ASSERT(false);
- }
- }
-
- NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,
- action, flags, metaState, buttonState, edgeFlags,
- mViewport.displayId, pointerCount, pointerProperties, pointerCoords,
- xPrecision, yPrecision, downTime);
- getListener()->notifyMotion(&args);
-}
-
-bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties,
- const PointerCoords* inCoords, const uint32_t* inIdToIndex,
- PointerProperties* outProperties, PointerCoords* outCoords, const uint32_t* outIdToIndex,
- BitSet32 idBits) const {
- bool changed = false;
- while (!idBits.isEmpty()) {
- uint32_t id = idBits.clearFirstMarkedBit();
- uint32_t inIndex = inIdToIndex[id];
- uint32_t outIndex = outIdToIndex[id];
-
- const PointerProperties& curInProperties = inProperties[inIndex];
- const PointerCoords& curInCoords = inCoords[inIndex];
- PointerProperties& curOutProperties = outProperties[outIndex];
- PointerCoords& curOutCoords = outCoords[outIndex];
-
- if (curInProperties != curOutProperties) {
- curOutProperties.copyFrom(curInProperties);
- changed = true;
- }
-
- if (curInCoords != curOutCoords) {
- curOutCoords.copyFrom(curInCoords);
- changed = true;
- }
- }
- return changed;
-}
-
-void TouchInputMapper::fadePointer() {
- if (mPointerController != NULL) {
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
- }
-}
-
-bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
- return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue
- && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue;
-}
-
-const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(
- int32_t x, int32_t y) {
- size_t numVirtualKeys = mVirtualKeys.size();
- for (size_t i = 0; i < numVirtualKeys; i++) {
- const VirtualKey& virtualKey = mVirtualKeys[i];
-
-#if DEBUG_VIRTUAL_KEYS
- ALOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
- "left=%d, top=%d, right=%d, bottom=%d",
- x, y,
- virtualKey.keyCode, virtualKey.scanCode,
- virtualKey.hitLeft, virtualKey.hitTop,
- virtualKey.hitRight, virtualKey.hitBottom);
-#endif
-
- if (virtualKey.isHit(x, y)) {
- return & virtualKey;
- }
- }
-
- return NULL;
-}
-
-void TouchInputMapper::assignPointerIds() {
- uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount;
- uint32_t lastPointerCount = mLastRawPointerData.pointerCount;
-
- mCurrentRawPointerData.clearIdBits();
-
- if (currentPointerCount == 0) {
- // No pointers to assign.
- return;
- }
-
- if (lastPointerCount == 0) {
- // All pointers are new.
- for (uint32_t i = 0; i < currentPointerCount; i++) {
- uint32_t id = i;
- mCurrentRawPointerData.pointers[i].id = id;
- mCurrentRawPointerData.idToIndex[id] = i;
- mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(i));
- }
- return;
- }
-
- if (currentPointerCount == 1 && lastPointerCount == 1
- && mCurrentRawPointerData.pointers[0].toolType
- == mLastRawPointerData.pointers[0].toolType) {
- // Only one pointer and no change in count so it must have the same id as before.
- uint32_t id = mLastRawPointerData.pointers[0].id;
- mCurrentRawPointerData.pointers[0].id = id;
- mCurrentRawPointerData.idToIndex[id] = 0;
- mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(0));
- return;
- }
-
- // General case.
- // We build a heap of squared euclidean distances between current and last pointers
- // associated with the current and last pointer indices. Then, we find the best
- // match (by distance) for each current pointer.
- // The pointers must have the same tool type but it is possible for them to
- // transition from hovering to touching or vice-versa while retaining the same id.
- PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
-
- uint32_t heapSize = 0;
- for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
- currentPointerIndex++) {
- for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
- lastPointerIndex++) {
- const RawPointerData::Pointer& currentPointer =
- mCurrentRawPointerData.pointers[currentPointerIndex];
- const RawPointerData::Pointer& lastPointer =
- mLastRawPointerData.pointers[lastPointerIndex];
- if (currentPointer.toolType == lastPointer.toolType) {
- int64_t deltaX = currentPointer.x - lastPointer.x;
- int64_t deltaY = currentPointer.y - lastPointer.y;
-
- uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
-
- // Insert new element into the heap (sift up).
- heap[heapSize].currentPointerIndex = currentPointerIndex;
- heap[heapSize].lastPointerIndex = lastPointerIndex;
- heap[heapSize].distance = distance;
- heapSize += 1;
- }
- }
- }
-
- // Heapify
- for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
- startIndex -= 1;
- for (uint32_t parentIndex = startIndex; ;) {
- uint32_t childIndex = parentIndex * 2 + 1;
- if (childIndex >= heapSize) {
- break;
- }
-
- if (childIndex + 1 < heapSize
- && heap[childIndex + 1].distance < heap[childIndex].distance) {
- childIndex += 1;
- }
-
- if (heap[parentIndex].distance <= heap[childIndex].distance) {
- break;
- }
-
- swap(heap[parentIndex], heap[childIndex]);
- parentIndex = childIndex;
- }
- }
-
-#if DEBUG_POINTER_ASSIGNMENT
- ALOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize);
- for (size_t i = 0; i < heapSize; i++) {
- ALOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
- i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
- heap[i].distance);
- }
-#endif
-
- // Pull matches out by increasing order of distance.
- // To avoid reassigning pointers that have already been matched, the loop keeps track
- // of which last and current pointers have been matched using the matchedXXXBits variables.
- // It also tracks the used pointer id bits.
- BitSet32 matchedLastBits(0);
- BitSet32 matchedCurrentBits(0);
- BitSet32 usedIdBits(0);
- bool first = true;
- for (uint32_t i = min(currentPointerCount, lastPointerCount); heapSize > 0 && i > 0; i--) {
- while (heapSize > 0) {
- if (first) {
- // The first time through the loop, we just consume the root element of
- // the heap (the one with smallest distance).
- first = false;
- } else {
- // Previous iterations consumed the root element of the heap.
- // Pop root element off of the heap (sift down).
- heap[0] = heap[heapSize];
- for (uint32_t parentIndex = 0; ;) {
- uint32_t childIndex = parentIndex * 2 + 1;
- if (childIndex >= heapSize) {
- break;
- }
-
- if (childIndex + 1 < heapSize
- && heap[childIndex + 1].distance < heap[childIndex].distance) {
- childIndex += 1;
- }
-
- if (heap[parentIndex].distance <= heap[childIndex].distance) {
- break;
- }
-
- swap(heap[parentIndex], heap[childIndex]);
- parentIndex = childIndex;
- }
-
-#if DEBUG_POINTER_ASSIGNMENT
- ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize);
- for (size_t i = 0; i < heapSize; i++) {
- ALOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
- i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
- heap[i].distance);
- }
-#endif
- }
-
- heapSize -= 1;
-
- uint32_t currentPointerIndex = heap[0].currentPointerIndex;
- if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
-
- uint32_t lastPointerIndex = heap[0].lastPointerIndex;
- if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
-
- matchedCurrentBits.markBit(currentPointerIndex);
- matchedLastBits.markBit(lastPointerIndex);
-
- uint32_t id = mLastRawPointerData.pointers[lastPointerIndex].id;
- mCurrentRawPointerData.pointers[currentPointerIndex].id = id;
- mCurrentRawPointerData.idToIndex[id] = currentPointerIndex;
- mCurrentRawPointerData.markIdBit(id,
- mCurrentRawPointerData.isHovering(currentPointerIndex));
- usedIdBits.markBit(id);
-
-#if DEBUG_POINTER_ASSIGNMENT
- ALOGD("assignPointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
- lastPointerIndex, currentPointerIndex, id, heap[0].distance);
-#endif
- break;
- }
- }
-
- // Assign fresh ids to pointers that were not matched in the process.
- for (uint32_t i = currentPointerCount - matchedCurrentBits.count(); i != 0; i--) {
- uint32_t currentPointerIndex = matchedCurrentBits.markFirstUnmarkedBit();
- uint32_t id = usedIdBits.markFirstUnmarkedBit();
-
- mCurrentRawPointerData.pointers[currentPointerIndex].id = id;
- mCurrentRawPointerData.idToIndex[id] = currentPointerIndex;
- mCurrentRawPointerData.markIdBit(id,
- mCurrentRawPointerData.isHovering(currentPointerIndex));
-
-#if DEBUG_POINTER_ASSIGNMENT
- ALOGD("assignPointerIds - assigned: cur=%d, id=%d",
- currentPointerIndex, id);
-#endif
- }
-}
-
-int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
- if (mCurrentVirtualKey.down && mCurrentVirtualKey.keyCode == keyCode) {
- return AKEY_STATE_VIRTUAL;
- }
-
- size_t numVirtualKeys = mVirtualKeys.size();
- for (size_t i = 0; i < numVirtualKeys; i++) {
- const VirtualKey& virtualKey = mVirtualKeys[i];
- if (virtualKey.keyCode == keyCode) {
- return AKEY_STATE_UP;
- }
- }
-
- return AKEY_STATE_UNKNOWN;
-}
-
-int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
- if (mCurrentVirtualKey.down && mCurrentVirtualKey.scanCode == scanCode) {
- return AKEY_STATE_VIRTUAL;
- }
-
- size_t numVirtualKeys = mVirtualKeys.size();
- for (size_t i = 0; i < numVirtualKeys; i++) {
- const VirtualKey& virtualKey = mVirtualKeys[i];
- if (virtualKey.scanCode == scanCode) {
- return AKEY_STATE_UP;
- }
- }
-
- return AKEY_STATE_UNKNOWN;
-}
-
-bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) {
- size_t numVirtualKeys = mVirtualKeys.size();
- for (size_t i = 0; i < numVirtualKeys; i++) {
- const VirtualKey& virtualKey = mVirtualKeys[i];
-
- for (size_t i = 0; i < numCodes; i++) {
- if (virtualKey.keyCode == keyCodes[i]) {
- outFlags[i] = 1;
- }
- }
- }
-
- return true;
-}
-
-
-// --- SingleTouchInputMapper ---
-
-SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
- TouchInputMapper(device) {
-}
-
-SingleTouchInputMapper::~SingleTouchInputMapper() {
-}
-
-void SingleTouchInputMapper::reset(nsecs_t when) {
- mSingleTouchMotionAccumulator.reset(getDevice());
-
- TouchInputMapper::reset(when);
-}
-
-void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
- TouchInputMapper::process(rawEvent);
-
- mSingleTouchMotionAccumulator.process(rawEvent);
-}
-
-void SingleTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) {
- if (mTouchButtonAccumulator.isToolActive()) {
- mCurrentRawPointerData.pointerCount = 1;
- mCurrentRawPointerData.idToIndex[0] = 0;
-
- bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
- && (mTouchButtonAccumulator.isHovering()
- || (mRawPointerAxes.pressure.valid
- && mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0));
- mCurrentRawPointerData.markIdBit(0, isHovering);
-
- RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[0];
- outPointer.id = 0;
- outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX();
- outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY();
- outPointer.pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
- outPointer.touchMajor = 0;
- outPointer.touchMinor = 0;
- outPointer.toolMajor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
- outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
- outPointer.orientation = 0;
- outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance();
- outPointer.tiltX = mSingleTouchMotionAccumulator.getAbsoluteTiltX();
- outPointer.tiltY = mSingleTouchMotionAccumulator.getAbsoluteTiltY();
- outPointer.toolType = mTouchButtonAccumulator.getToolType();
- if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
- outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
- }
- outPointer.isHovering = isHovering;
- }
-}
-
-void SingleTouchInputMapper::configureRawPointerAxes() {
- TouchInputMapper::configureRawPointerAxes();
-
- getAbsoluteAxisInfo(ABS_X, &mRawPointerAxes.x);
- getAbsoluteAxisInfo(ABS_Y, &mRawPointerAxes.y);
- getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPointerAxes.pressure);
- getAbsoluteAxisInfo(ABS_TOOL_WIDTH, &mRawPointerAxes.toolMajor);
- getAbsoluteAxisInfo(ABS_DISTANCE, &mRawPointerAxes.distance);
- getAbsoluteAxisInfo(ABS_TILT_X, &mRawPointerAxes.tiltX);
- getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY);
-}
-
-bool SingleTouchInputMapper::hasStylus() const {
- return mTouchButtonAccumulator.hasStylus();
-}
-
-
-// --- MultiTouchInputMapper ---
-
-MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
- TouchInputMapper(device) {
-}
-
-MultiTouchInputMapper::~MultiTouchInputMapper() {
-}
-
-void MultiTouchInputMapper::reset(nsecs_t when) {
- mMultiTouchMotionAccumulator.reset(getDevice());
-
- mPointerIdBits.clear();
-
- TouchInputMapper::reset(when);
-}
-
-void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
- TouchInputMapper::process(rawEvent);
-
- mMultiTouchMotionAccumulator.process(rawEvent);
-}
-
-void MultiTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) {
- size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
- size_t outCount = 0;
- BitSet32 newPointerIdBits;
-
- for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
- const MultiTouchMotionAccumulator::Slot* inSlot =
- mMultiTouchMotionAccumulator.getSlot(inIndex);
- if (!inSlot->isInUse()) {
- continue;
- }
-
- if (outCount >= MAX_POINTERS) {
-#if DEBUG_POINTERS
- ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
- "ignoring the rest.",
- getDeviceName().string(), MAX_POINTERS);
-#endif
- break; // too many fingers!
- }
-
- RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[outCount];
- outPointer.x = inSlot->getX();
- outPointer.y = inSlot->getY();
- outPointer.pressure = inSlot->getPressure();
- outPointer.touchMajor = inSlot->getTouchMajor();
- outPointer.touchMinor = inSlot->getTouchMinor();
- outPointer.toolMajor = inSlot->getToolMajor();
- outPointer.toolMinor = inSlot->getToolMinor();
- outPointer.orientation = inSlot->getOrientation();
- outPointer.distance = inSlot->getDistance();
- outPointer.tiltX = 0;
- outPointer.tiltY = 0;
-
- outPointer.toolType = inSlot->getToolType();
- if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
- outPointer.toolType = mTouchButtonAccumulator.getToolType();
- if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
- outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
- }
- }
-
- bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
- && (mTouchButtonAccumulator.isHovering()
- || (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));
- outPointer.isHovering = isHovering;
-
- // Assign pointer id using tracking id if available.
- if (*outHavePointerIds) {
- int32_t trackingId = inSlot->getTrackingId();
- int32_t id = -1;
- if (trackingId >= 0) {
- for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {
- uint32_t n = idBits.clearFirstMarkedBit();
- if (mPointerTrackingIdMap[n] == trackingId) {
- id = n;
- }
- }
-
- if (id < 0 && !mPointerIdBits.isFull()) {
- id = mPointerIdBits.markFirstUnmarkedBit();
- mPointerTrackingIdMap[id] = trackingId;
- }
- }
- if (id < 0) {
- *outHavePointerIds = false;
- mCurrentRawPointerData.clearIdBits();
- newPointerIdBits.clear();
- } else {
- outPointer.id = id;
- mCurrentRawPointerData.idToIndex[id] = outCount;
- mCurrentRawPointerData.markIdBit(id, isHovering);
- newPointerIdBits.markBit(id);
- }
- }
-
- outCount += 1;
- }
-
- mCurrentRawPointerData.pointerCount = outCount;
- mPointerIdBits = newPointerIdBits;
-
- mMultiTouchMotionAccumulator.finishSync();
-}
-
-void MultiTouchInputMapper::configureRawPointerAxes() {
- TouchInputMapper::configureRawPointerAxes();
-
- getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mRawPointerAxes.x);
- getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mRawPointerAxes.y);
- getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &mRawPointerAxes.touchMajor);
- getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR, &mRawPointerAxes.touchMinor);
- getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &mRawPointerAxes.toolMajor);
- getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR, &mRawPointerAxes.toolMinor);
- getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &mRawPointerAxes.orientation);
- getAbsoluteAxisInfo(ABS_MT_PRESSURE, &mRawPointerAxes.pressure);
- getAbsoluteAxisInfo(ABS_MT_DISTANCE, &mRawPointerAxes.distance);
- getAbsoluteAxisInfo(ABS_MT_TRACKING_ID, &mRawPointerAxes.trackingId);
- getAbsoluteAxisInfo(ABS_MT_SLOT, &mRawPointerAxes.slot);
-
- if (mRawPointerAxes.trackingId.valid
- && mRawPointerAxes.slot.valid
- && mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) {
- size_t slotCount = mRawPointerAxes.slot.maxValue + 1;
- if (slotCount > MAX_SLOTS) {
- ALOGW("MultiTouch Device %s reported %d slots but the framework "
- "only supports a maximum of %d slots at this time.",
- getDeviceName().string(), slotCount, MAX_SLOTS);
- slotCount = MAX_SLOTS;
- }
- mMultiTouchMotionAccumulator.configure(getDevice(),
- slotCount, true /*usingSlotsProtocol*/);
- } else {
- mMultiTouchMotionAccumulator.configure(getDevice(),
- MAX_POINTERS, false /*usingSlotsProtocol*/);
- }
-}
-
-bool MultiTouchInputMapper::hasStylus() const {
- return mMultiTouchMotionAccumulator.hasStylus()
- || mTouchButtonAccumulator.hasStylus();
-}
-
-
-// --- JoystickInputMapper ---
-
-JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
- InputMapper(device) {
-}
-
-JoystickInputMapper::~JoystickInputMapper() {
-}
-
-uint32_t JoystickInputMapper::getSources() {
- return AINPUT_SOURCE_JOYSTICK;
-}
-
-void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
- InputMapper::populateDeviceInfo(info);
-
- for (size_t i = 0; i < mAxes.size(); i++) {
- const Axis& axis = mAxes.valueAt(i);
- addMotionRange(axis.axisInfo.axis, axis, info);
-
- if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
- addMotionRange(axis.axisInfo.highAxis, axis, info);
-
- }
- }
-}
-
-void JoystickInputMapper::addMotionRange(int32_t axisId, const Axis& axis,
- InputDeviceInfo* info) {
- info->addMotionRange(axisId, AINPUT_SOURCE_JOYSTICK,
- axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
- /* In order to ease the transition for developers from using the old axes
- * to the newer, more semantically correct axes, we'll continue to register
- * the old axes as duplicates of their corresponding new ones. */
- int32_t compatAxis = getCompatAxis(axisId);
- if (compatAxis >= 0) {
- info->addMotionRange(compatAxis, AINPUT_SOURCE_JOYSTICK,
- axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
- }
-}
-
-/* A mapping from axes the joystick actually has to the axes that should be
- * artificially created for compatibility purposes.
- * Returns -1 if no compatibility axis is needed. */
-int32_t JoystickInputMapper::getCompatAxis(int32_t axis) {
- switch(axis) {
- case AMOTION_EVENT_AXIS_LTRIGGER:
- return AMOTION_EVENT_AXIS_BRAKE;
- case AMOTION_EVENT_AXIS_RTRIGGER:
- return AMOTION_EVENT_AXIS_GAS;
- }
- return -1;
-}
-
-void JoystickInputMapper::dump(String8& dump) {
- dump.append(INDENT2 "Joystick Input Mapper:\n");
-
- dump.append(INDENT3 "Axes:\n");
- size_t numAxes = mAxes.size();
- for (size_t i = 0; i < numAxes; i++) {
- const Axis& axis = mAxes.valueAt(i);
- const char* label = getAxisLabel(axis.axisInfo.axis);
- if (label) {
- dump.appendFormat(INDENT4 "%s", label);
- } else {
- dump.appendFormat(INDENT4 "%d", axis.axisInfo.axis);
- }
- if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
- label = getAxisLabel(axis.axisInfo.highAxis);
- if (label) {
- dump.appendFormat(" / %s (split at %d)", label, axis.axisInfo.splitValue);
- } else {
- dump.appendFormat(" / %d (split at %d)", axis.axisInfo.highAxis,
- axis.axisInfo.splitValue);
- }
- } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
- dump.append(" (invert)");
- }
-
- dump.appendFormat(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f, resolution=%0.5f\n",
- axis.min, axis.max, axis.flat, axis.fuzz, axis.resolution);
- dump.appendFormat(INDENT4 " scale=%0.5f, offset=%0.5f, "
- "highScale=%0.5f, highOffset=%0.5f\n",
- axis.scale, axis.offset, axis.highScale, axis.highOffset);
- dump.appendFormat(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, "
- "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n",
- mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
- axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz, axis.rawAxisInfo.resolution);
- }
-}
-
-void JoystickInputMapper::configure(nsecs_t when,
- const InputReaderConfiguration* config, uint32_t changes) {
- InputMapper::configure(when, config, changes);
-
- if (!changes) { // first time only
- // Collect all axes.
- for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
- if (!(getAbsAxisUsage(abs, getDevice()->getClasses())
- & INPUT_DEVICE_CLASS_JOYSTICK)) {
- continue; // axis must be claimed by a different device
- }
-
- RawAbsoluteAxisInfo rawAxisInfo;
- getAbsoluteAxisInfo(abs, &rawAxisInfo);
- if (rawAxisInfo.valid) {
- // Map axis.
- AxisInfo axisInfo;
- bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
- if (!explicitlyMapped) {
- // Axis is not explicitly mapped, will choose a generic axis later.
- axisInfo.mode = AxisInfo::MODE_NORMAL;
- axisInfo.axis = -1;
- }
-
- // Apply flat override.
- int32_t rawFlat = axisInfo.flatOverride < 0
- ? rawAxisInfo.flat : axisInfo.flatOverride;
-
- // Calculate scaling factors and limits.
- Axis axis;
- if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
- float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
- float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
- axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
- scale, 0.0f, highScale, 0.0f,
- 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
- rawAxisInfo.resolution * scale);
- } else if (isCenteredAxis(axisInfo.axis)) {
- float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
- float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
- axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
- scale, offset, scale, offset,
- -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
- rawAxisInfo.resolution * scale);
- } else {
- float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
- axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
- scale, 0.0f, scale, 0.0f,
- 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale,
- rawAxisInfo.resolution * scale);
- }
-
- // To eliminate noise while the joystick is at rest, filter out small variations
- // in axis values up front.
- axis.filter = axis.fuzz ? axis.fuzz : axis.flat * 0.25f;
-
- mAxes.add(abs, axis);
- }
- }
-
- // If there are too many axes, start dropping them.
- // Prefer to keep explicitly mapped axes.
- if (mAxes.size() > PointerCoords::MAX_AXES) {
- ALOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
- getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
- pruneAxes(true);
- pruneAxes(false);
- }
-
- // Assign generic axis ids to remaining axes.
- int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
- size_t numAxes = mAxes.size();
- for (size_t i = 0; i < numAxes; i++) {
- Axis& axis = mAxes.editValueAt(i);
- if (axis.axisInfo.axis < 0) {
- while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
- && haveAxis(nextGenericAxisId)) {
- nextGenericAxisId += 1;
- }
-
- if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
- axis.axisInfo.axis = nextGenericAxisId;
- nextGenericAxisId += 1;
- } else {
- ALOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
- "have already been assigned to other axes.",
- getDeviceName().string(), mAxes.keyAt(i));
- mAxes.removeItemsAt(i--);
- numAxes -= 1;
- }
- }
- }
- }
-}
-
-bool JoystickInputMapper::haveAxis(int32_t axisId) {
- size_t numAxes = mAxes.size();
- for (size_t i = 0; i < numAxes; i++) {
- const Axis& axis = mAxes.valueAt(i);
- if (axis.axisInfo.axis == axisId
- || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
- && axis.axisInfo.highAxis == axisId)) {
- return true;
- }
- }
- return false;
-}
-
-void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
- size_t i = mAxes.size();
- while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
- if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
- continue;
- }
- ALOGI("Discarding joystick '%s' axis %d because there are too many axes.",
- getDeviceName().string(), mAxes.keyAt(i));
- mAxes.removeItemsAt(i);
- }
-}
-
-bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
- switch (axis) {
- case AMOTION_EVENT_AXIS_X:
- case AMOTION_EVENT_AXIS_Y:
- case AMOTION_EVENT_AXIS_Z:
- case AMOTION_EVENT_AXIS_RX:
- case AMOTION_EVENT_AXIS_RY:
- case AMOTION_EVENT_AXIS_RZ:
- case AMOTION_EVENT_AXIS_HAT_X:
- case AMOTION_EVENT_AXIS_HAT_Y:
- case AMOTION_EVENT_AXIS_ORIENTATION:
- case AMOTION_EVENT_AXIS_RUDDER:
- case AMOTION_EVENT_AXIS_WHEEL:
- return true;
- default:
- return false;
- }
-}
-
-void JoystickInputMapper::reset(nsecs_t when) {
- // Recenter all axes.
- size_t numAxes = mAxes.size();
- for (size_t i = 0; i < numAxes; i++) {
- Axis& axis = mAxes.editValueAt(i);
- axis.resetValue();
- }
-
- InputMapper::reset(when);
-}
-
-void JoystickInputMapper::process(const RawEvent* rawEvent) {
- switch (rawEvent->type) {
- case EV_ABS: {
- ssize_t index = mAxes.indexOfKey(rawEvent->code);
- if (index >= 0) {
- Axis& axis = mAxes.editValueAt(index);
- float newValue, highNewValue;
- switch (axis.axisInfo.mode) {
- case AxisInfo::MODE_INVERT:
- newValue = (axis.rawAxisInfo.maxValue - rawEvent->value)
- * axis.scale + axis.offset;
- highNewValue = 0.0f;
- break;
- case AxisInfo::MODE_SPLIT:
- if (rawEvent->value < axis.axisInfo.splitValue) {
- newValue = (axis.axisInfo.splitValue - rawEvent->value)
- * axis.scale + axis.offset;
- highNewValue = 0.0f;
- } else if (rawEvent->value > axis.axisInfo.splitValue) {
- newValue = 0.0f;
- highNewValue = (rawEvent->value - axis.axisInfo.splitValue)
- * axis.highScale + axis.highOffset;
- } else {
- newValue = 0.0f;
- highNewValue = 0.0f;
- }
- break;
- default:
- newValue = rawEvent->value * axis.scale + axis.offset;
- highNewValue = 0.0f;
- break;
- }
- axis.newValue = newValue;
- axis.highNewValue = highNewValue;
- }
- break;
- }
-
- case EV_SYN:
- switch (rawEvent->code) {
- case SYN_REPORT:
- sync(rawEvent->when, false /*force*/);
- break;
- }
- break;
- }
-}
-
-void JoystickInputMapper::sync(nsecs_t when, bool force) {
- if (!filterAxes(force)) {
- return;
- }
-
- int32_t metaState = mContext->getGlobalMetaState();
- int32_t buttonState = 0;
-
- PointerProperties pointerProperties;
- pointerProperties.clear();
- pointerProperties.id = 0;
- pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
-
- PointerCoords pointerCoords;
- pointerCoords.clear();
-
- size_t numAxes = mAxes.size();
- for (size_t i = 0; i < numAxes; i++) {
- const Axis& axis = mAxes.valueAt(i);
- setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.axis, axis.currentValue);
- if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
- setPointerCoordsAxisValue(&pointerCoords, axis.axisInfo.highAxis,
- axis.highCurrentValue);
- }
- }
-
- // Moving a joystick axis should not wake the device because joysticks can
- // be fairly noisy even when not in use. On the other hand, pushing a gamepad
- // button will likely wake the device.
- // TODO: Use the input device configuration to control this behavior more finely.
- uint32_t policyFlags = 0;
-
- NotifyMotionArgs args(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
- AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- ADISPLAY_ID_NONE, 1, &pointerProperties, &pointerCoords, 0, 0, 0);
- getListener()->notifyMotion(&args);
-}
-
-void JoystickInputMapper::setPointerCoordsAxisValue(PointerCoords* pointerCoords,
- int32_t axis, float value) {
- pointerCoords->setAxisValue(axis, value);
- /* In order to ease the transition for developers from using the old axes
- * to the newer, more semantically correct axes, we'll continue to produce
- * values for the old axes as mirrors of the value of their corresponding
- * new axes. */
- int32_t compatAxis = getCompatAxis(axis);
- if (compatAxis >= 0) {
- pointerCoords->setAxisValue(compatAxis, value);
- }
-}
-
-bool JoystickInputMapper::filterAxes(bool force) {
- bool atLeastOneSignificantChange = force;
- size_t numAxes = mAxes.size();
- for (size_t i = 0; i < numAxes; i++) {
- Axis& axis = mAxes.editValueAt(i);
- if (force || hasValueChangedSignificantly(axis.filter,
- axis.newValue, axis.currentValue, axis.min, axis.max)) {
- axis.currentValue = axis.newValue;
- atLeastOneSignificantChange = true;
- }
- if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
- if (force || hasValueChangedSignificantly(axis.filter,
- axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) {
- axis.highCurrentValue = axis.highNewValue;
- atLeastOneSignificantChange = true;
- }
- }
- }
- return atLeastOneSignificantChange;
-}
-
-bool JoystickInputMapper::hasValueChangedSignificantly(
- float filter, float newValue, float currentValue, float min, float max) {
- if (newValue != currentValue) {
- // Filter out small changes in value unless the value is converging on the axis
- // bounds or center point. This is intended to reduce the amount of information
- // sent to applications by particularly noisy joysticks (such as PS3).
- if (fabs(newValue - currentValue) > filter
- || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min)
- || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max)
- || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
- return true;
- }
- }
- return false;
-}
-
-bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(
- float filter, float newValue, float currentValue, float thresholdValue) {
- float newDistance = fabs(newValue - thresholdValue);
- if (newDistance < filter) {
- float oldDistance = fabs(currentValue - thresholdValue);
- if (newDistance < oldDistance) {
- return true;
- }
- }
- return false;
-}
-
-} // namespace android
diff --git a/libs/input/InputReader.h b/libs/input/InputReader.h
deleted file mode 100644
index 674f67d..0000000
--- a/libs/input/InputReader.h
+++ /dev/null
@@ -1,1817 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_READER_H
-#define _UI_INPUT_READER_H
-
-#include "EventHub.h"
-#include "PointerController.h"
-#include "InputListener.h"
-
-#include <input/Input.h>
-#include <input/VelocityControl.h>
-#include <input/VelocityTracker.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-#include <utils/Timers.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <utils/BitSet.h>
-
-#include <stddef.h>
-#include <unistd.h>
-
-// Maximum supported size of a vibration pattern.
-// Must be at least 2.
-#define MAX_VIBRATE_PATTERN_SIZE 100
-
-// Maximum allowable delay value in a vibration pattern before
-// which the delay will be truncated.
-#define MAX_VIBRATE_PATTERN_DELAY_NSECS (1000000 * 1000000000LL)
-
-namespace android {
-
-class InputDevice;
-class InputMapper;
-
-/*
- * Describes how coordinates are mapped on a physical display.
- * See com.android.server.display.DisplayViewport.
- */
-struct DisplayViewport {
- int32_t displayId; // -1 if invalid
- int32_t orientation;
- int32_t logicalLeft;
- int32_t logicalTop;
- int32_t logicalRight;
- int32_t logicalBottom;
- int32_t physicalLeft;
- int32_t physicalTop;
- int32_t physicalRight;
- int32_t physicalBottom;
- int32_t deviceWidth;
- int32_t deviceHeight;
-
- DisplayViewport() :
- displayId(ADISPLAY_ID_NONE), orientation(DISPLAY_ORIENTATION_0),
- logicalLeft(0), logicalTop(0), logicalRight(0), logicalBottom(0),
- physicalLeft(0), physicalTop(0), physicalRight(0), physicalBottom(0),
- deviceWidth(0), deviceHeight(0) {
- }
-
- bool operator==(const DisplayViewport& other) const {
- return displayId == other.displayId
- && orientation == other.orientation
- && logicalLeft == other.logicalLeft
- && logicalTop == other.logicalTop
- && logicalRight == other.logicalRight
- && logicalBottom == other.logicalBottom
- && physicalLeft == other.physicalLeft
- && physicalTop == other.physicalTop
- && physicalRight == other.physicalRight
- && physicalBottom == other.physicalBottom
- && deviceWidth == other.deviceWidth
- && deviceHeight == other.deviceHeight;
- }
-
- bool operator!=(const DisplayViewport& other) const {
- return !(*this == other);
- }
-
- inline bool isValid() const {
- return displayId >= 0;
- }
-
- void setNonDisplayViewport(int32_t width, int32_t height) {
- displayId = ADISPLAY_ID_NONE;
- orientation = DISPLAY_ORIENTATION_0;
- logicalLeft = 0;
- logicalTop = 0;
- logicalRight = width;
- logicalBottom = height;
- physicalLeft = 0;
- physicalTop = 0;
- physicalRight = width;
- physicalBottom = height;
- deviceWidth = width;
- deviceHeight = height;
- }
-};
-
-/*
- * Input reader configuration.
- *
- * Specifies various options that modify the behavior of the input reader.
- */
-struct InputReaderConfiguration {
- // Describes changes that have occurred.
- enum {
- // The pointer speed changed.
- CHANGE_POINTER_SPEED = 1 << 0,
-
- // The pointer gesture control changed.
- CHANGE_POINTER_GESTURE_ENABLEMENT = 1 << 1,
-
- // The display size or orientation changed.
- CHANGE_DISPLAY_INFO = 1 << 2,
-
- // The visible touches option changed.
- CHANGE_SHOW_TOUCHES = 1 << 3,
-
- // The keyboard layouts must be reloaded.
- CHANGE_KEYBOARD_LAYOUTS = 1 << 4,
-
- // The device name alias supplied by the may have changed for some devices.
- CHANGE_DEVICE_ALIAS = 1 << 5,
-
- // All devices must be reopened.
- CHANGE_MUST_REOPEN = 1 << 31,
- };
-
- // Gets the amount of time to disable virtual keys after the screen is touched
- // in order to filter out accidental virtual key presses due to swiping gestures
- // or taps near the edge of the display. May be 0 to disable the feature.
- nsecs_t virtualKeyQuietTime;
-
- // The excluded device names for the platform.
- // Devices with these names will be ignored.
- Vector<String8> excludedDeviceNames;
-
- // Velocity control parameters for mouse pointer movements.
- VelocityControlParameters pointerVelocityControlParameters;
-
- // Velocity control parameters for mouse wheel movements.
- VelocityControlParameters wheelVelocityControlParameters;
-
- // True if pointer gestures are enabled.
- bool pointerGesturesEnabled;
-
- // Quiet time between certain pointer gesture transitions.
- // Time to allow for all fingers or buttons to settle into a stable state before
- // starting a new gesture.
- nsecs_t pointerGestureQuietInterval;
-
- // The minimum speed that a pointer must travel for us to consider switching the active
- // touch pointer to it during a drag. This threshold is set to avoid switching due
- // to noise from a finger resting on the touch pad (perhaps just pressing it down).
- float pointerGestureDragMinSwitchSpeed; // in pixels per second
-
- // Tap gesture delay time.
- // The time between down and up must be less than this to be considered a tap.
- nsecs_t pointerGestureTapInterval;
-
- // Tap drag gesture delay time.
- // The time between the previous tap's up and the next down must be less than
- // this to be considered a drag. Otherwise, the previous tap is finished and a
- // new tap begins.
- //
- // Note that the previous tap will be held down for this entire duration so this
- // interval must be shorter than the long press timeout.
- nsecs_t pointerGestureTapDragInterval;
-
- // The distance in pixels that the pointer is allowed to move from initial down
- // to up and still be called a tap.
- float pointerGestureTapSlop; // in pixels
-
- // Time after the first touch points go down to settle on an initial centroid.
- // This is intended to be enough time to handle cases where the user puts down two
- // fingers at almost but not quite exactly the same time.
- nsecs_t pointerGestureMultitouchSettleInterval;
-
- // The transition from PRESS to SWIPE or FREEFORM gesture mode is made when
- // at least two pointers have moved at least this far from their starting place.
- float pointerGestureMultitouchMinDistance; // in pixels
-
- // The transition from PRESS to SWIPE gesture mode can only occur when the
- // cosine of the angle between the two vectors is greater than or equal to than this value
- // which indicates that the vectors are oriented in the same direction.
- // When the vectors are oriented in the exactly same direction, the cosine is 1.0.
- // (In exactly opposite directions, the cosine is -1.0.)
- float pointerGestureSwipeTransitionAngleCosine;
-
- // The transition from PRESS to SWIPE gesture mode can only occur when the
- // fingers are no more than this far apart relative to the diagonal size of
- // the touch pad. For example, a ratio of 0.5 means that the fingers must be
- // no more than half the diagonal size of the touch pad apart.
- float pointerGestureSwipeMaxWidthRatio;
-
- // The gesture movement speed factor relative to the size of the display.
- // Movement speed applies when the fingers are moving in the same direction.
- // Without acceleration, a full swipe of the touch pad diagonal in movement mode
- // will cover this portion of the display diagonal.
- float pointerGestureMovementSpeedRatio;
-
- // The gesture zoom speed factor relative to the size of the display.
- // Zoom speed applies when the fingers are mostly moving relative to each other
- // to execute a scale gesture or similar.
- // Without acceleration, a full swipe of the touch pad diagonal in zoom mode
- // will cover this portion of the display diagonal.
- float pointerGestureZoomSpeedRatio;
-
- // True to show the location of touches on the touch screen as spots.
- bool showTouches;
-
- InputReaderConfiguration() :
- virtualKeyQuietTime(0),
- pointerVelocityControlParameters(1.0f, 500.0f, 3000.0f, 3.0f),
- wheelVelocityControlParameters(1.0f, 15.0f, 50.0f, 4.0f),
- pointerGesturesEnabled(true),
- pointerGestureQuietInterval(100 * 1000000LL), // 100 ms
- pointerGestureDragMinSwitchSpeed(50), // 50 pixels per second
- pointerGestureTapInterval(150 * 1000000LL), // 150 ms
- pointerGestureTapDragInterval(150 * 1000000LL), // 150 ms
- pointerGestureTapSlop(10.0f), // 10 pixels
- pointerGestureMultitouchSettleInterval(100 * 1000000LL), // 100 ms
- pointerGestureMultitouchMinDistance(15), // 15 pixels
- pointerGestureSwipeTransitionAngleCosine(0.2588f), // cosine of 75 degrees
- pointerGestureSwipeMaxWidthRatio(0.25f),
- pointerGestureMovementSpeedRatio(0.8f),
- pointerGestureZoomSpeedRatio(0.3f),
- showTouches(false) { }
-
- bool getDisplayInfo(bool external, DisplayViewport* outViewport) const;
- void setDisplayInfo(bool external, const DisplayViewport& viewport);
-
-private:
- DisplayViewport mInternalDisplay;
- DisplayViewport mExternalDisplay;
-};
-
-
-/*
- * Input reader policy interface.
- *
- * The input reader policy is used by the input reader to interact with the Window Manager
- * and other system components.
- *
- * The actual implementation is partially supported by callbacks into the DVM
- * via JNI. This interface is also mocked in the unit tests.
- *
- * These methods must NOT re-enter the input reader since they may be called while
- * holding the input reader lock.
- */
-class InputReaderPolicyInterface : public virtual RefBase {
-protected:
- InputReaderPolicyInterface() { }
- virtual ~InputReaderPolicyInterface() { }
-
-public:
- /* Gets the input reader configuration. */
- virtual void getReaderConfiguration(InputReaderConfiguration* outConfig) = 0;
-
- /* Gets a pointer controller associated with the specified cursor device (ie. a mouse). */
- virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) = 0;
-
- /* Notifies the input reader policy that some input devices have changed
- * and provides information about all current input devices.
- */
- virtual void notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices) = 0;
-
- /* Gets the keyboard layout for a particular input device. */
- virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(
- const InputDeviceIdentifier& identifier) = 0;
-
- /* Gets a user-supplied alias for a particular input device, or an empty string if none. */
- virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier) = 0;
-};
-
-
-/* Processes raw input events and sends cooked event data to an input listener. */
-class InputReaderInterface : public virtual RefBase {
-protected:
- InputReaderInterface() { }
- virtual ~InputReaderInterface() { }
-
-public:
- /* Dumps the state of the input reader.
- *
- * This method may be called on any thread (usually by the input manager). */
- virtual void dump(String8& dump) = 0;
-
- /* Called by the heatbeat to ensures that the reader has not deadlocked. */
- virtual void monitor() = 0;
-
- /* Runs a single iteration of the processing loop.
- * Nominally reads and processes one incoming message from the EventHub.
- *
- * This method should be called on the input reader thread.
- */
- virtual void loopOnce() = 0;
-
- /* Gets information about all input devices.
- *
- * This method may be called on any thread (usually by the input manager).
- */
- virtual void getInputDevices(Vector<InputDeviceInfo>& outInputDevices) = 0;
-
- /* Query current input state. */
- virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
- int32_t scanCode) = 0;
- virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
- int32_t keyCode) = 0;
- virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
- int32_t sw) = 0;
-
- /* Determine whether physical keys exist for the given framework-domain key codes. */
- virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
- size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0;
-
- /* Requests that a reconfiguration of all input devices.
- * The changes flag is a bitfield that indicates what has changed and whether
- * the input devices must all be reopened. */
- virtual void requestRefreshConfiguration(uint32_t changes) = 0;
-
- /* Controls the vibrator of a particular input device. */
- virtual void vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
- ssize_t repeat, int32_t token) = 0;
- virtual void cancelVibrate(int32_t deviceId, int32_t token) = 0;
-};
-
-
-/* Internal interface used by individual input devices to access global input device state
- * and parameters maintained by the input reader.
- */
-class InputReaderContext {
-public:
- InputReaderContext() { }
- virtual ~InputReaderContext() { }
-
- virtual void updateGlobalMetaState() = 0;
- virtual int32_t getGlobalMetaState() = 0;
-
- virtual void disableVirtualKeysUntil(nsecs_t time) = 0;
- virtual bool shouldDropVirtualKey(nsecs_t now,
- InputDevice* device, int32_t keyCode, int32_t scanCode) = 0;
-
- virtual void fadePointer() = 0;
-
- virtual void requestTimeoutAtTime(nsecs_t when) = 0;
- virtual int32_t bumpGeneration() = 0;
-
- virtual InputReaderPolicyInterface* getPolicy() = 0;
- virtual InputListenerInterface* getListener() = 0;
- virtual EventHubInterface* getEventHub() = 0;
-};
-
-
-/* The input reader reads raw event data from the event hub and processes it into input events
- * that it sends to the input listener. Some functions of the input reader, such as early
- * event filtering in low power states, are controlled by a separate policy object.
- *
- * The InputReader owns a collection of InputMappers. Most of the work it does happens
- * on the input reader thread but the InputReader can receive queries from other system
- * components running on arbitrary threads. To keep things manageable, the InputReader
- * uses a single Mutex to guard its state. The Mutex may be held while calling into the
- * EventHub or the InputReaderPolicy but it is never held while calling into the
- * InputListener.
- */
-class InputReader : public InputReaderInterface {
-public:
- InputReader(const sp<EventHubInterface>& eventHub,
- const sp<InputReaderPolicyInterface>& policy,
- const sp<InputListenerInterface>& listener);
- virtual ~InputReader();
-
- virtual void dump(String8& dump);
- virtual void monitor();
-
- virtual void loopOnce();
-
- virtual void getInputDevices(Vector<InputDeviceInfo>& outInputDevices);
-
- virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
- int32_t scanCode);
- virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
- int32_t keyCode);
- virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
- int32_t sw);
-
- virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
- size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags);
-
- virtual void requestRefreshConfiguration(uint32_t changes);
-
- virtual void vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
- ssize_t repeat, int32_t token);
- virtual void cancelVibrate(int32_t deviceId, int32_t token);
-
-protected:
- // These members are protected so they can be instrumented by test cases.
- virtual InputDevice* createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
- const InputDeviceIdentifier& identifier, uint32_t classes);
-
- class ContextImpl : public InputReaderContext {
- InputReader* mReader;
-
- public:
- ContextImpl(InputReader* reader);
-
- virtual void updateGlobalMetaState();
- virtual int32_t getGlobalMetaState();
- virtual void disableVirtualKeysUntil(nsecs_t time);
- virtual bool shouldDropVirtualKey(nsecs_t now,
- InputDevice* device, int32_t keyCode, int32_t scanCode);
- virtual void fadePointer();
- virtual void requestTimeoutAtTime(nsecs_t when);
- virtual int32_t bumpGeneration();
- virtual InputReaderPolicyInterface* getPolicy();
- virtual InputListenerInterface* getListener();
- virtual EventHubInterface* getEventHub();
- } mContext;
-
- friend class ContextImpl;
-
-private:
- Mutex mLock;
-
- Condition mReaderIsAliveCondition;
-
- sp<EventHubInterface> mEventHub;
- sp<InputReaderPolicyInterface> mPolicy;
- sp<QueuedInputListener> mQueuedListener;
-
- InputReaderConfiguration mConfig;
-
- // The event queue.
- static const int EVENT_BUFFER_SIZE = 256;
- RawEvent mEventBuffer[EVENT_BUFFER_SIZE];
-
- KeyedVector<int32_t, InputDevice*> mDevices;
-
- // low-level input event decoding and device management
- void processEventsLocked(const RawEvent* rawEvents, size_t count);
-
- void addDeviceLocked(nsecs_t when, int32_t deviceId);
- void removeDeviceLocked(nsecs_t when, int32_t deviceId);
- void processEventsForDeviceLocked(int32_t deviceId, const RawEvent* rawEvents, size_t count);
- void timeoutExpiredLocked(nsecs_t when);
-
- void handleConfigurationChangedLocked(nsecs_t when);
-
- int32_t mGlobalMetaState;
- void updateGlobalMetaStateLocked();
- int32_t getGlobalMetaStateLocked();
-
- void fadePointerLocked();
-
- int32_t mGeneration;
- int32_t bumpGenerationLocked();
-
- void getInputDevicesLocked(Vector<InputDeviceInfo>& outInputDevices);
-
- nsecs_t mDisableVirtualKeysTimeout;
- void disableVirtualKeysUntilLocked(nsecs_t time);
- bool shouldDropVirtualKeyLocked(nsecs_t now,
- InputDevice* device, int32_t keyCode, int32_t scanCode);
-
- nsecs_t mNextTimeout;
- void requestTimeoutAtTimeLocked(nsecs_t when);
-
- uint32_t mConfigurationChangesToRefresh;
- void refreshConfigurationLocked(uint32_t changes);
-
- // state queries
- typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code);
- int32_t getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code,
- GetStateFunc getStateFunc);
- bool markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags);
-};
-
-
-/* Reads raw events from the event hub and processes them, endlessly. */
-class InputReaderThread : public Thread {
-public:
- InputReaderThread(const sp<InputReaderInterface>& reader);
- virtual ~InputReaderThread();
-
-private:
- sp<InputReaderInterface> mReader;
-
- virtual bool threadLoop();
-};
-
-
-/* Represents the state of a single input device. */
-class InputDevice {
-public:
- InputDevice(InputReaderContext* context, int32_t id, int32_t generation, int32_t
- controllerNumber, const InputDeviceIdentifier& identifier, uint32_t classes);
- ~InputDevice();
-
- inline InputReaderContext* getContext() { return mContext; }
- inline int32_t getId() const { return mId; }
- inline int32_t getControllerNumber() const { return mControllerNumber; }
- inline int32_t getGeneration() const { return mGeneration; }
- inline const String8& getName() const { return mIdentifier.name; }
- inline uint32_t getClasses() const { return mClasses; }
- inline uint32_t getSources() const { return mSources; }
-
- inline bool isExternal() { return mIsExternal; }
- inline void setExternal(bool external) { mIsExternal = external; }
-
- inline bool isIgnored() { return mMappers.isEmpty(); }
-
- void dump(String8& dump);
- void addMapper(InputMapper* mapper);
- void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
- void reset(nsecs_t when);
- void process(const RawEvent* rawEvents, size_t count);
- void timeoutExpired(nsecs_t when);
-
- void getDeviceInfo(InputDeviceInfo* outDeviceInfo);
- int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
- int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
- int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
- bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags);
- void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat, int32_t token);
- void cancelVibrate(int32_t token);
-
- int32_t getMetaState();
-
- void fadePointer();
-
- void bumpGeneration();
-
- void notifyReset(nsecs_t when);
-
- inline const PropertyMap& getConfiguration() { return mConfiguration; }
- inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
-
- bool hasKey(int32_t code) {
- return getEventHub()->hasScanCode(mId, code);
- }
-
- bool hasAbsoluteAxis(int32_t code) {
- RawAbsoluteAxisInfo info;
- getEventHub()->getAbsoluteAxisInfo(mId, code, &info);
- return info.valid;
- }
-
- bool isKeyPressed(int32_t code) {
- return getEventHub()->getScanCodeState(mId, code) == AKEY_STATE_DOWN;
- }
-
- int32_t getAbsoluteAxisValue(int32_t code) {
- int32_t value;
- getEventHub()->getAbsoluteAxisValue(mId, code, &value);
- return value;
- }
-
-private:
- InputReaderContext* mContext;
- int32_t mId;
- int32_t mGeneration;
- int32_t mControllerNumber;
- InputDeviceIdentifier mIdentifier;
- String8 mAlias;
- uint32_t mClasses;
-
- Vector<InputMapper*> mMappers;
-
- uint32_t mSources;
- bool mIsExternal;
- bool mDropUntilNextSync;
-
- typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code);
- int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc);
-
- PropertyMap mConfiguration;
-};
-
-
-/* Keeps track of the state of mouse or touch pad buttons. */
-class CursorButtonAccumulator {
-public:
- CursorButtonAccumulator();
- void reset(InputDevice* device);
-
- void process(const RawEvent* rawEvent);
-
- uint32_t getButtonState() const;
-
-private:
- bool mBtnLeft;
- bool mBtnRight;
- bool mBtnMiddle;
- bool mBtnBack;
- bool mBtnSide;
- bool mBtnForward;
- bool mBtnExtra;
- bool mBtnTask;
-
- void clearButtons();
-};
-
-
-/* Keeps track of cursor movements. */
-
-class CursorMotionAccumulator {
-public:
- CursorMotionAccumulator();
- void reset(InputDevice* device);
-
- void process(const RawEvent* rawEvent);
- void finishSync();
-
- inline int32_t getRelativeX() const { return mRelX; }
- inline int32_t getRelativeY() const { return mRelY; }
-
-private:
- int32_t mRelX;
- int32_t mRelY;
-
- void clearRelativeAxes();
-};
-
-
-/* Keeps track of cursor scrolling motions. */
-
-class CursorScrollAccumulator {
-public:
- CursorScrollAccumulator();
- void configure(InputDevice* device);
- void reset(InputDevice* device);
-
- void process(const RawEvent* rawEvent);
- void finishSync();
-
- inline bool haveRelativeVWheel() const { return mHaveRelWheel; }
- inline bool haveRelativeHWheel() const { return mHaveRelHWheel; }
-
- inline int32_t getRelativeX() const { return mRelX; }
- inline int32_t getRelativeY() const { return mRelY; }
- inline int32_t getRelativeVWheel() const { return mRelWheel; }
- inline int32_t getRelativeHWheel() const { return mRelHWheel; }
-
-private:
- bool mHaveRelWheel;
- bool mHaveRelHWheel;
-
- int32_t mRelX;
- int32_t mRelY;
- int32_t mRelWheel;
- int32_t mRelHWheel;
-
- void clearRelativeAxes();
-};
-
-
-/* Keeps track of the state of touch, stylus and tool buttons. */
-class TouchButtonAccumulator {
-public:
- TouchButtonAccumulator();
- void configure(InputDevice* device);
- void reset(InputDevice* device);
-
- void process(const RawEvent* rawEvent);
-
- uint32_t getButtonState() const;
- int32_t getToolType() const;
- bool isToolActive() const;
- bool isHovering() const;
- bool hasStylus() const;
-
-private:
- bool mHaveBtnTouch;
- bool mHaveStylus;
-
- bool mBtnTouch;
- bool mBtnStylus;
- bool mBtnStylus2;
- bool mBtnToolFinger;
- bool mBtnToolPen;
- bool mBtnToolRubber;
- bool mBtnToolBrush;
- bool mBtnToolPencil;
- bool mBtnToolAirbrush;
- bool mBtnToolMouse;
- bool mBtnToolLens;
- bool mBtnToolDoubleTap;
- bool mBtnToolTripleTap;
- bool mBtnToolQuadTap;
-
- void clearButtons();
-};
-
-
-/* Raw axis information from the driver. */
-struct RawPointerAxes {
- RawAbsoluteAxisInfo x;
- RawAbsoluteAxisInfo y;
- RawAbsoluteAxisInfo pressure;
- RawAbsoluteAxisInfo touchMajor;
- RawAbsoluteAxisInfo touchMinor;
- RawAbsoluteAxisInfo toolMajor;
- RawAbsoluteAxisInfo toolMinor;
- RawAbsoluteAxisInfo orientation;
- RawAbsoluteAxisInfo distance;
- RawAbsoluteAxisInfo tiltX;
- RawAbsoluteAxisInfo tiltY;
- RawAbsoluteAxisInfo trackingId;
- RawAbsoluteAxisInfo slot;
-
- RawPointerAxes();
- void clear();
-};
-
-
-/* Raw data for a collection of pointers including a pointer id mapping table. */
-struct RawPointerData {
- struct Pointer {
- uint32_t id;
- int32_t x;
- int32_t y;
- int32_t pressure;
- int32_t touchMajor;
- int32_t touchMinor;
- int32_t toolMajor;
- int32_t toolMinor;
- int32_t orientation;
- int32_t distance;
- int32_t tiltX;
- int32_t tiltY;
- int32_t toolType; // a fully decoded AMOTION_EVENT_TOOL_TYPE constant
- bool isHovering;
- };
-
- uint32_t pointerCount;
- Pointer pointers[MAX_POINTERS];
- BitSet32 hoveringIdBits, touchingIdBits;
- uint32_t idToIndex[MAX_POINTER_ID + 1];
-
- RawPointerData();
- void clear();
- void copyFrom(const RawPointerData& other);
- void getCentroidOfTouchingPointers(float* outX, float* outY) const;
-
- inline void markIdBit(uint32_t id, bool isHovering) {
- if (isHovering) {
- hoveringIdBits.markBit(id);
- } else {
- touchingIdBits.markBit(id);
- }
- }
-
- inline void clearIdBits() {
- hoveringIdBits.clear();
- touchingIdBits.clear();
- }
-
- inline const Pointer& pointerForId(uint32_t id) const {
- return pointers[idToIndex[id]];
- }
-
- inline bool isHovering(uint32_t pointerIndex) {
- return pointers[pointerIndex].isHovering;
- }
-};
-
-
-/* Cooked data for a collection of pointers including a pointer id mapping table. */
-struct CookedPointerData {
- uint32_t pointerCount;
- PointerProperties pointerProperties[MAX_POINTERS];
- PointerCoords pointerCoords[MAX_POINTERS];
- BitSet32 hoveringIdBits, touchingIdBits;
- uint32_t idToIndex[MAX_POINTER_ID + 1];
-
- CookedPointerData();
- void clear();
- void copyFrom(const CookedPointerData& other);
-
- inline const PointerCoords& pointerCoordsForId(uint32_t id) const {
- return pointerCoords[idToIndex[id]];
- }
-
- inline bool isHovering(uint32_t pointerIndex) {
- return hoveringIdBits.hasBit(pointerProperties[pointerIndex].id);
- }
-};
-
-
-/* Keeps track of the state of single-touch protocol. */
-class SingleTouchMotionAccumulator {
-public:
- SingleTouchMotionAccumulator();
-
- void process(const RawEvent* rawEvent);
- void reset(InputDevice* device);
-
- inline int32_t getAbsoluteX() const { return mAbsX; }
- inline int32_t getAbsoluteY() const { return mAbsY; }
- inline int32_t getAbsolutePressure() const { return mAbsPressure; }
- inline int32_t getAbsoluteToolWidth() const { return mAbsToolWidth; }
- inline int32_t getAbsoluteDistance() const { return mAbsDistance; }
- inline int32_t getAbsoluteTiltX() const { return mAbsTiltX; }
- inline int32_t getAbsoluteTiltY() const { return mAbsTiltY; }
-
-private:
- int32_t mAbsX;
- int32_t mAbsY;
- int32_t mAbsPressure;
- int32_t mAbsToolWidth;
- int32_t mAbsDistance;
- int32_t mAbsTiltX;
- int32_t mAbsTiltY;
-
- void clearAbsoluteAxes();
-};
-
-
-/* Keeps track of the state of multi-touch protocol. */
-class MultiTouchMotionAccumulator {
-public:
- class Slot {
- public:
- inline bool isInUse() const { return mInUse; }
- inline int32_t getX() const { return mAbsMTPositionX; }
- inline int32_t getY() const { return mAbsMTPositionY; }
- inline int32_t getTouchMajor() const { return mAbsMTTouchMajor; }
- inline int32_t getTouchMinor() const {
- return mHaveAbsMTTouchMinor ? mAbsMTTouchMinor : mAbsMTTouchMajor; }
- inline int32_t getToolMajor() const { return mAbsMTWidthMajor; }
- inline int32_t getToolMinor() const {
- return mHaveAbsMTWidthMinor ? mAbsMTWidthMinor : mAbsMTWidthMajor; }
- inline int32_t getOrientation() const { return mAbsMTOrientation; }
- inline int32_t getTrackingId() const { return mAbsMTTrackingId; }
- inline int32_t getPressure() const { return mAbsMTPressure; }
- inline int32_t getDistance() const { return mAbsMTDistance; }
- inline int32_t getToolType() const;
-
- private:
- friend class MultiTouchMotionAccumulator;
-
- bool mInUse;
- bool mHaveAbsMTTouchMinor;
- bool mHaveAbsMTWidthMinor;
- bool mHaveAbsMTToolType;
-
- int32_t mAbsMTPositionX;
- int32_t mAbsMTPositionY;
- int32_t mAbsMTTouchMajor;
- int32_t mAbsMTTouchMinor;
- int32_t mAbsMTWidthMajor;
- int32_t mAbsMTWidthMinor;
- int32_t mAbsMTOrientation;
- int32_t mAbsMTTrackingId;
- int32_t mAbsMTPressure;
- int32_t mAbsMTDistance;
- int32_t mAbsMTToolType;
-
- Slot();
- void clear();
- };
-
- MultiTouchMotionAccumulator();
- ~MultiTouchMotionAccumulator();
-
- void configure(InputDevice* device, size_t slotCount, bool usingSlotsProtocol);
- void reset(InputDevice* device);
- void process(const RawEvent* rawEvent);
- void finishSync();
- bool hasStylus() const;
-
- inline size_t getSlotCount() const { return mSlotCount; }
- inline const Slot* getSlot(size_t index) const { return &mSlots[index]; }
-
-private:
- int32_t mCurrentSlot;
- Slot* mSlots;
- size_t mSlotCount;
- bool mUsingSlotsProtocol;
- bool mHaveStylus;
-
- void clearSlots(int32_t initialSlot);
-};
-
-
-/* An input mapper transforms raw input events into cooked event data.
- * A single input device can have multiple associated input mappers in order to interpret
- * different classes of events.
- *
- * InputMapper lifecycle:
- * - create
- * - configure with 0 changes
- * - reset
- * - process, process, process (may occasionally reconfigure with non-zero changes or reset)
- * - reset
- * - destroy
- */
-class InputMapper {
-public:
- InputMapper(InputDevice* device);
- virtual ~InputMapper();
-
- inline InputDevice* getDevice() { return mDevice; }
- inline int32_t getDeviceId() { return mDevice->getId(); }
- inline const String8 getDeviceName() { return mDevice->getName(); }
- inline InputReaderContext* getContext() { return mContext; }
- inline InputReaderPolicyInterface* getPolicy() { return mContext->getPolicy(); }
- inline InputListenerInterface* getListener() { return mContext->getListener(); }
- inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
-
- virtual uint32_t getSources() = 0;
- virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
- virtual void dump(String8& dump);
- virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
- virtual void reset(nsecs_t when);
- virtual void process(const RawEvent* rawEvent) = 0;
- virtual void timeoutExpired(nsecs_t when);
-
- virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
- virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
- virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
- virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags);
- virtual void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
- int32_t token);
- virtual void cancelVibrate(int32_t token);
-
- virtual int32_t getMetaState();
-
- virtual void fadePointer();
-
-protected:
- InputDevice* mDevice;
- InputReaderContext* mContext;
-
- status_t getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo);
- void bumpGeneration();
-
- static void dumpRawAbsoluteAxisInfo(String8& dump,
- const RawAbsoluteAxisInfo& axis, const char* name);
-};
-
-
-class SwitchInputMapper : public InputMapper {
-public:
- SwitchInputMapper(InputDevice* device);
- virtual ~SwitchInputMapper();
-
- virtual uint32_t getSources();
- virtual void process(const RawEvent* rawEvent);
-
- virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
-
-private:
- uint32_t mUpdatedSwitchValues;
- uint32_t mUpdatedSwitchMask;
-
- void processSwitch(int32_t switchCode, int32_t switchValue);
- void sync(nsecs_t when);
-};
-
-
-class VibratorInputMapper : public InputMapper {
-public:
- VibratorInputMapper(InputDevice* device);
- virtual ~VibratorInputMapper();
-
- virtual uint32_t getSources();
- virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
- virtual void process(const RawEvent* rawEvent);
-
- virtual void vibrate(const nsecs_t* pattern, size_t patternSize, ssize_t repeat,
- int32_t token);
- virtual void cancelVibrate(int32_t token);
- virtual void timeoutExpired(nsecs_t when);
- virtual void dump(String8& dump);
-
-private:
- bool mVibrating;
- nsecs_t mPattern[MAX_VIBRATE_PATTERN_SIZE];
- size_t mPatternSize;
- ssize_t mRepeat;
- int32_t mToken;
- ssize_t mIndex;
- nsecs_t mNextStepTime;
-
- void nextStep();
- void stopVibrating();
-};
-
-
-class KeyboardInputMapper : public InputMapper {
-public:
- KeyboardInputMapper(InputDevice* device, uint32_t source, int32_t keyboardType);
- virtual ~KeyboardInputMapper();
-
- virtual uint32_t getSources();
- virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
- virtual void dump(String8& dump);
- virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
- virtual void reset(nsecs_t when);
- virtual void process(const RawEvent* rawEvent);
-
- virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
- virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
- virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags);
-
- virtual int32_t getMetaState();
-
-private:
- struct KeyDown {
- int32_t keyCode;
- int32_t scanCode;
- };
-
- uint32_t mSource;
- int32_t mKeyboardType;
-
- int32_t mOrientation; // orientation for dpad keys
-
- Vector<KeyDown> mKeyDowns; // keys that are down
- int32_t mMetaState;
- nsecs_t mDownTime; // time of most recent key down
-
- int32_t mCurrentHidUsage; // most recent HID usage seen this packet, or 0 if none
-
- struct LedState {
- bool avail; // led is available
- bool on; // we think the led is currently on
- };
- LedState mCapsLockLedState;
- LedState mNumLockLedState;
- LedState mScrollLockLedState;
-
- // Immutable configuration parameters.
- struct Parameters {
- bool hasAssociatedDisplay;
- bool orientationAware;
- } mParameters;
-
- void configureParameters();
- void dumpParameters(String8& dump);
-
- bool isKeyboardOrGamepadKey(int32_t scanCode);
-
- void processKey(nsecs_t when, bool down, int32_t keyCode, int32_t scanCode,
- uint32_t policyFlags);
-
- ssize_t findKeyDown(int32_t scanCode);
-
- void resetLedState();
- void initializeLedState(LedState& ledState, int32_t led);
- void updateLedState(bool reset);
- void updateLedStateForModifier(LedState& ledState, int32_t led,
- int32_t modifier, bool reset);
-};
-
-
-class CursorInputMapper : public InputMapper {
-public:
- CursorInputMapper(InputDevice* device);
- virtual ~CursorInputMapper();
-
- virtual uint32_t getSources();
- virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
- virtual void dump(String8& dump);
- virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
- virtual void reset(nsecs_t when);
- virtual void process(const RawEvent* rawEvent);
-
- virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
-
- virtual void fadePointer();
-
-private:
- // Amount that trackball needs to move in order to generate a key event.
- static const int32_t TRACKBALL_MOVEMENT_THRESHOLD = 6;
-
- // Immutable configuration parameters.
- struct Parameters {
- enum Mode {
- MODE_POINTER,
- MODE_NAVIGATION,
- };
-
- Mode mode;
- bool hasAssociatedDisplay;
- bool orientationAware;
- } mParameters;
-
- CursorButtonAccumulator mCursorButtonAccumulator;
- CursorMotionAccumulator mCursorMotionAccumulator;
- CursorScrollAccumulator mCursorScrollAccumulator;
-
- int32_t mSource;
- float mXScale;
- float mYScale;
- float mXPrecision;
- float mYPrecision;
-
- float mVWheelScale;
- float mHWheelScale;
-
- // Velocity controls for mouse pointer and wheel movements.
- // The controls for X and Y wheel movements are separate to keep them decoupled.
- VelocityControl mPointerVelocityControl;
- VelocityControl mWheelXVelocityControl;
- VelocityControl mWheelYVelocityControl;
-
- int32_t mOrientation;
-
- sp<PointerControllerInterface> mPointerController;
-
- int32_t mButtonState;
- nsecs_t mDownTime;
-
- void configureParameters();
- void dumpParameters(String8& dump);
-
- void sync(nsecs_t when);
-};
-
-
-class TouchInputMapper : public InputMapper {
-public:
- TouchInputMapper(InputDevice* device);
- virtual ~TouchInputMapper();
-
- virtual uint32_t getSources();
- virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
- virtual void dump(String8& dump);
- virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
- virtual void reset(nsecs_t when);
- virtual void process(const RawEvent* rawEvent);
-
- virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
- virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
- virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags);
-
- virtual void fadePointer();
- virtual void timeoutExpired(nsecs_t when);
-
-protected:
- CursorButtonAccumulator mCursorButtonAccumulator;
- CursorScrollAccumulator mCursorScrollAccumulator;
- TouchButtonAccumulator mTouchButtonAccumulator;
-
- struct VirtualKey {
- int32_t keyCode;
- int32_t scanCode;
- uint32_t flags;
-
- // computed hit box, specified in touch screen coords based on known display size
- int32_t hitLeft;
- int32_t hitTop;
- int32_t hitRight;
- int32_t hitBottom;
-
- inline bool isHit(int32_t x, int32_t y) const {
- return x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom;
- }
- };
-
- // Input sources and device mode.
- uint32_t mSource;
-
- enum DeviceMode {
- DEVICE_MODE_DISABLED, // input is disabled
- DEVICE_MODE_DIRECT, // direct mapping (touchscreen)
- DEVICE_MODE_UNSCALED, // unscaled mapping (touchpad)
- DEVICE_MODE_NAVIGATION, // unscaled mapping with assist gesture (touch navigation)
- DEVICE_MODE_POINTER, // pointer mapping (pointer)
- };
- DeviceMode mDeviceMode;
-
- // The reader's configuration.
- InputReaderConfiguration mConfig;
-
- // Immutable configuration parameters.
- struct Parameters {
- enum DeviceType {
- DEVICE_TYPE_TOUCH_SCREEN,
- DEVICE_TYPE_TOUCH_PAD,
- DEVICE_TYPE_TOUCH_NAVIGATION,
- DEVICE_TYPE_POINTER,
- };
-
- DeviceType deviceType;
- bool hasAssociatedDisplay;
- bool associatedDisplayIsExternal;
- bool orientationAware;
- bool hasButtonUnderPad;
-
- enum GestureMode {
- GESTURE_MODE_POINTER,
- GESTURE_MODE_SPOTS,
- };
- GestureMode gestureMode;
- } mParameters;
-
- // Immutable calibration parameters in parsed form.
- struct Calibration {
- // Size
- enum SizeCalibration {
- SIZE_CALIBRATION_DEFAULT,
- SIZE_CALIBRATION_NONE,
- SIZE_CALIBRATION_GEOMETRIC,
- SIZE_CALIBRATION_DIAMETER,
- SIZE_CALIBRATION_BOX,
- SIZE_CALIBRATION_AREA,
- };
-
- SizeCalibration sizeCalibration;
-
- bool haveSizeScale;
- float sizeScale;
- bool haveSizeBias;
- float sizeBias;
- bool haveSizeIsSummed;
- bool sizeIsSummed;
-
- // Pressure
- enum PressureCalibration {
- PRESSURE_CALIBRATION_DEFAULT,
- PRESSURE_CALIBRATION_NONE,
- PRESSURE_CALIBRATION_PHYSICAL,
- PRESSURE_CALIBRATION_AMPLITUDE,
- };
-
- PressureCalibration pressureCalibration;
- bool havePressureScale;
- float pressureScale;
-
- // Orientation
- enum OrientationCalibration {
- ORIENTATION_CALIBRATION_DEFAULT,
- ORIENTATION_CALIBRATION_NONE,
- ORIENTATION_CALIBRATION_INTERPOLATED,
- ORIENTATION_CALIBRATION_VECTOR,
- };
-
- OrientationCalibration orientationCalibration;
-
- // Distance
- enum DistanceCalibration {
- DISTANCE_CALIBRATION_DEFAULT,
- DISTANCE_CALIBRATION_NONE,
- DISTANCE_CALIBRATION_SCALED,
- };
-
- DistanceCalibration distanceCalibration;
- bool haveDistanceScale;
- float distanceScale;
-
- enum CoverageCalibration {
- COVERAGE_CALIBRATION_DEFAULT,
- COVERAGE_CALIBRATION_NONE,
- COVERAGE_CALIBRATION_BOX,
- };
-
- CoverageCalibration coverageCalibration;
-
- inline void applySizeScaleAndBias(float* outSize) const {
- if (haveSizeScale) {
- *outSize *= sizeScale;
- }
- if (haveSizeBias) {
- *outSize += sizeBias;
- }
- if (*outSize < 0) {
- *outSize = 0;
- }
- }
- } mCalibration;
-
- // Raw pointer axis information from the driver.
- RawPointerAxes mRawPointerAxes;
-
- // Raw pointer sample data.
- RawPointerData mCurrentRawPointerData;
- RawPointerData mLastRawPointerData;
-
- // Cooked pointer sample data.
- CookedPointerData mCurrentCookedPointerData;
- CookedPointerData mLastCookedPointerData;
-
- // Button state.
- int32_t mCurrentButtonState;
- int32_t mLastButtonState;
-
- // Scroll state.
- int32_t mCurrentRawVScroll;
- int32_t mCurrentRawHScroll;
-
- // Id bits used to differentiate fingers, stylus and mouse tools.
- BitSet32 mCurrentFingerIdBits; // finger or unknown
- BitSet32 mLastFingerIdBits;
- BitSet32 mCurrentStylusIdBits; // stylus or eraser
- BitSet32 mLastStylusIdBits;
- BitSet32 mCurrentMouseIdBits; // mouse or lens
- BitSet32 mLastMouseIdBits;
-
- // True if we sent a HOVER_ENTER event.
- bool mSentHoverEnter;
-
- // The time the primary pointer last went down.
- nsecs_t mDownTime;
-
- // The pointer controller, or null if the device is not a pointer.
- sp<PointerControllerInterface> mPointerController;
-
- Vector<VirtualKey> mVirtualKeys;
-
- virtual void configureParameters();
- virtual void dumpParameters(String8& dump);
- virtual void configureRawPointerAxes();
- virtual void dumpRawPointerAxes(String8& dump);
- virtual void configureSurface(nsecs_t when, bool* outResetNeeded);
- virtual void dumpSurface(String8& dump);
- virtual void configureVirtualKeys();
- virtual void dumpVirtualKeys(String8& dump);
- virtual void parseCalibration();
- virtual void resolveCalibration();
- virtual void dumpCalibration(String8& dump);
- virtual bool hasStylus() const = 0;
-
- virtual void syncTouch(nsecs_t when, bool* outHavePointerIds) = 0;
-
-private:
- // The current viewport.
- // The components of the viewport are specified in the display's rotated orientation.
- DisplayViewport mViewport;
-
- // The surface orientation, width and height set by configureSurface().
- // The width and height are derived from the viewport but are specified
- // in the natural orientation.
- // The surface origin specifies how the surface coordinates should be translated
- // to align with the logical display coordinate space.
- // The orientation may be different from the viewport orientation as it specifies
- // the rotation of the surface coordinates required to produce the viewport's
- // requested orientation, so it will depend on whether the device is orientation aware.
- int32_t mSurfaceWidth;
- int32_t mSurfaceHeight;
- int32_t mSurfaceLeft;
- int32_t mSurfaceTop;
- int32_t mSurfaceOrientation;
-
- // Translation and scaling factors, orientation-independent.
- float mXTranslate;
- float mXScale;
- float mXPrecision;
-
- float mYTranslate;
- float mYScale;
- float mYPrecision;
-
- float mGeometricScale;
-
- float mPressureScale;
-
- float mSizeScale;
-
- float mOrientationScale;
-
- float mDistanceScale;
-
- bool mHaveTilt;
- float mTiltXCenter;
- float mTiltXScale;
- float mTiltYCenter;
- float mTiltYScale;
-
- // Oriented motion ranges for input device info.
- struct OrientedRanges {
- InputDeviceInfo::MotionRange x;
- InputDeviceInfo::MotionRange y;
- InputDeviceInfo::MotionRange pressure;
-
- bool haveSize;
- InputDeviceInfo::MotionRange size;
-
- bool haveTouchSize;
- InputDeviceInfo::MotionRange touchMajor;
- InputDeviceInfo::MotionRange touchMinor;
-
- bool haveToolSize;
- InputDeviceInfo::MotionRange toolMajor;
- InputDeviceInfo::MotionRange toolMinor;
-
- bool haveOrientation;
- InputDeviceInfo::MotionRange orientation;
-
- bool haveDistance;
- InputDeviceInfo::MotionRange distance;
-
- bool haveTilt;
- InputDeviceInfo::MotionRange tilt;
-
- OrientedRanges() {
- clear();
- }
-
- void clear() {
- haveSize = false;
- haveTouchSize = false;
- haveToolSize = false;
- haveOrientation = false;
- haveDistance = false;
- haveTilt = false;
- }
- } mOrientedRanges;
-
- // Oriented dimensions and precision.
- float mOrientedXPrecision;
- float mOrientedYPrecision;
-
- struct CurrentVirtualKeyState {
- bool down;
- bool ignored;
- nsecs_t downTime;
- int32_t keyCode;
- int32_t scanCode;
- } mCurrentVirtualKey;
-
- // Scale factor for gesture or mouse based pointer movements.
- float mPointerXMovementScale;
- float mPointerYMovementScale;
-
- // Scale factor for gesture based zooming and other freeform motions.
- float mPointerXZoomScale;
- float mPointerYZoomScale;
-
- // The maximum swipe width.
- float mPointerGestureMaxSwipeWidth;
-
- struct PointerDistanceHeapElement {
- uint32_t currentPointerIndex : 8;
- uint32_t lastPointerIndex : 8;
- uint64_t distance : 48; // squared distance
- };
-
- enum PointerUsage {
- POINTER_USAGE_NONE,
- POINTER_USAGE_GESTURES,
- POINTER_USAGE_STYLUS,
- POINTER_USAGE_MOUSE,
- };
- PointerUsage mPointerUsage;
-
- struct PointerGesture {
- enum Mode {
- // No fingers, button is not pressed.
- // Nothing happening.
- NEUTRAL,
-
- // No fingers, button is not pressed.
- // Tap detected.
- // Emits DOWN and UP events at the pointer location.
- TAP,
-
- // Exactly one finger dragging following a tap.
- // Pointer follows the active finger.
- // Emits DOWN, MOVE and UP events at the pointer location.
- //
- // Detect double-taps when the finger goes up while in TAP_DRAG mode.
- TAP_DRAG,
-
- // Button is pressed.
- // Pointer follows the active finger if there is one. Other fingers are ignored.
- // Emits DOWN, MOVE and UP events at the pointer location.
- BUTTON_CLICK_OR_DRAG,
-
- // Exactly one finger, button is not pressed.
- // Pointer follows the active finger.
- // Emits HOVER_MOVE events at the pointer location.
- //
- // Detect taps when the finger goes up while in HOVER mode.
- HOVER,
-
- // Exactly two fingers but neither have moved enough to clearly indicate
- // whether a swipe or freeform gesture was intended. We consider the
- // pointer to be pressed so this enables clicking or long-pressing on buttons.
- // Pointer does not move.
- // Emits DOWN, MOVE and UP events with a single stationary pointer coordinate.
- PRESS,
-
- // Exactly two fingers moving in the same direction, button is not pressed.
- // Pointer does not move.
- // Emits DOWN, MOVE and UP events with a single pointer coordinate that
- // follows the midpoint between both fingers.
- SWIPE,
-
- // Two or more fingers moving in arbitrary directions, button is not pressed.
- // Pointer does not move.
- // Emits DOWN, POINTER_DOWN, MOVE, POINTER_UP and UP events that follow
- // each finger individually relative to the initial centroid of the finger.
- FREEFORM,
-
- // Waiting for quiet time to end before starting the next gesture.
- QUIET,
- };
-
- // Time the first finger went down.
- nsecs_t firstTouchTime;
-
- // The active pointer id from the raw touch data.
- int32_t activeTouchId; // -1 if none
-
- // The active pointer id from the gesture last delivered to the application.
- int32_t activeGestureId; // -1 if none
-
- // Pointer coords and ids for the current and previous pointer gesture.
- Mode currentGestureMode;
- BitSet32 currentGestureIdBits;
- uint32_t currentGestureIdToIndex[MAX_POINTER_ID + 1];
- PointerProperties currentGestureProperties[MAX_POINTERS];
- PointerCoords currentGestureCoords[MAX_POINTERS];
-
- Mode lastGestureMode;
- BitSet32 lastGestureIdBits;
- uint32_t lastGestureIdToIndex[MAX_POINTER_ID + 1];
- PointerProperties lastGestureProperties[MAX_POINTERS];
- PointerCoords lastGestureCoords[MAX_POINTERS];
-
- // Time the pointer gesture last went down.
- nsecs_t downTime;
-
- // Time when the pointer went down for a TAP.
- nsecs_t tapDownTime;
-
- // Time when the pointer went up for a TAP.
- nsecs_t tapUpTime;
-
- // Location of initial tap.
- float tapX, tapY;
-
- // Time we started waiting for quiescence.
- nsecs_t quietTime;
-
- // Reference points for multitouch gestures.
- float referenceTouchX; // reference touch X/Y coordinates in surface units
- float referenceTouchY;
- float referenceGestureX; // reference gesture X/Y coordinates in pixels
- float referenceGestureY;
-
- // Distance that each pointer has traveled which has not yet been
- // subsumed into the reference gesture position.
- BitSet32 referenceIdBits;
- struct Delta {
- float dx, dy;
- };
- Delta referenceDeltas[MAX_POINTER_ID + 1];
-
- // Describes how touch ids are mapped to gesture ids for freeform gestures.
- uint32_t freeformTouchToGestureIdMap[MAX_POINTER_ID + 1];
-
- // A velocity tracker for determining whether to switch active pointers during drags.
- VelocityTracker velocityTracker;
-
- void reset() {
- firstTouchTime = LLONG_MIN;
- activeTouchId = -1;
- activeGestureId = -1;
- currentGestureMode = NEUTRAL;
- currentGestureIdBits.clear();
- lastGestureMode = NEUTRAL;
- lastGestureIdBits.clear();
- downTime = 0;
- velocityTracker.clear();
- resetTap();
- resetQuietTime();
- }
-
- void resetTap() {
- tapDownTime = LLONG_MIN;
- tapUpTime = LLONG_MIN;
- }
-
- void resetQuietTime() {
- quietTime = LLONG_MIN;
- }
- } mPointerGesture;
-
- struct PointerSimple {
- PointerCoords currentCoords;
- PointerProperties currentProperties;
- PointerCoords lastCoords;
- PointerProperties lastProperties;
-
- // True if the pointer is down.
- bool down;
-
- // True if the pointer is hovering.
- bool hovering;
-
- // Time the pointer last went down.
- nsecs_t downTime;
-
- void reset() {
- currentCoords.clear();
- currentProperties.clear();
- lastCoords.clear();
- lastProperties.clear();
- down = false;
- hovering = false;
- downTime = 0;
- }
- } mPointerSimple;
-
- // The pointer and scroll velocity controls.
- VelocityControl mPointerVelocityControl;
- VelocityControl mWheelXVelocityControl;
- VelocityControl mWheelYVelocityControl;
-
- void sync(nsecs_t when);
-
- bool consumeRawTouches(nsecs_t when, uint32_t policyFlags);
- void dispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
- int32_t keyEventAction, int32_t keyEventFlags);
-
- void dispatchTouches(nsecs_t when, uint32_t policyFlags);
- void dispatchHoverExit(nsecs_t when, uint32_t policyFlags);
- void dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags);
- void cookPointerData();
-
- void dispatchPointerUsage(nsecs_t when, uint32_t policyFlags, PointerUsage pointerUsage);
- void abortPointerUsage(nsecs_t when, uint32_t policyFlags);
-
- void dispatchPointerGestures(nsecs_t when, uint32_t policyFlags, bool isTimeout);
- void abortPointerGestures(nsecs_t when, uint32_t policyFlags);
- bool preparePointerGestures(nsecs_t when,
- bool* outCancelPreviousGesture, bool* outFinishPreviousGesture,
- bool isTimeout);
-
- void dispatchPointerStylus(nsecs_t when, uint32_t policyFlags);
- void abortPointerStylus(nsecs_t when, uint32_t policyFlags);
-
- void dispatchPointerMouse(nsecs_t when, uint32_t policyFlags);
- void abortPointerMouse(nsecs_t when, uint32_t policyFlags);
-
- void dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
- bool down, bool hovering);
- void abortPointerSimple(nsecs_t when, uint32_t policyFlags);
-
- // Dispatches a motion event.
- // If the changedId is >= 0 and the action is POINTER_DOWN or POINTER_UP, the
- // method will take care of setting the index and transmuting the action to DOWN or UP
- // it is the first / last pointer to go down / up.
- void dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
- int32_t action, int32_t flags, int32_t metaState, int32_t buttonState,
- int32_t edgeFlags,
- const PointerProperties* properties, const PointerCoords* coords,
- const uint32_t* idToIndex, BitSet32 idBits,
- int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime);
-
- // Updates pointer coords and properties for pointers with specified ids that have moved.
- // Returns true if any of them changed.
- bool updateMovedPointers(const PointerProperties* inProperties,
- const PointerCoords* inCoords, const uint32_t* inIdToIndex,
- PointerProperties* outProperties, PointerCoords* outCoords,
- const uint32_t* outIdToIndex, BitSet32 idBits) const;
-
- bool isPointInsideSurface(int32_t x, int32_t y);
- const VirtualKey* findVirtualKeyHit(int32_t x, int32_t y);
-
- void assignPointerIds();
-};
-
-
-class SingleTouchInputMapper : public TouchInputMapper {
-public:
- SingleTouchInputMapper(InputDevice* device);
- virtual ~SingleTouchInputMapper();
-
- virtual void reset(nsecs_t when);
- virtual void process(const RawEvent* rawEvent);
-
-protected:
- virtual void syncTouch(nsecs_t when, bool* outHavePointerIds);
- virtual void configureRawPointerAxes();
- virtual bool hasStylus() const;
-
-private:
- SingleTouchMotionAccumulator mSingleTouchMotionAccumulator;
-};
-
-
-class MultiTouchInputMapper : public TouchInputMapper {
-public:
- MultiTouchInputMapper(InputDevice* device);
- virtual ~MultiTouchInputMapper();
-
- virtual void reset(nsecs_t when);
- virtual void process(const RawEvent* rawEvent);
-
-protected:
- virtual void syncTouch(nsecs_t when, bool* outHavePointerIds);
- virtual void configureRawPointerAxes();
- virtual bool hasStylus() const;
-
-private:
- MultiTouchMotionAccumulator mMultiTouchMotionAccumulator;
-
- // Specifies the pointer id bits that are in use, and their associated tracking id.
- BitSet32 mPointerIdBits;
- int32_t mPointerTrackingIdMap[MAX_POINTER_ID + 1];
-};
-
-
-class JoystickInputMapper : public InputMapper {
-public:
- JoystickInputMapper(InputDevice* device);
- virtual ~JoystickInputMapper();
-
- virtual uint32_t getSources();
- virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
- virtual void dump(String8& dump);
- virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
- virtual void reset(nsecs_t when);
- virtual void process(const RawEvent* rawEvent);
-
-private:
- struct Axis {
- RawAbsoluteAxisInfo rawAxisInfo;
- AxisInfo axisInfo;
-
- bool explicitlyMapped; // true if the axis was explicitly assigned an axis id
-
- float scale; // scale factor from raw to normalized values
- float offset; // offset to add after scaling for normalization
- float highScale; // scale factor from raw to normalized values of high split
- float highOffset; // offset to add after scaling for normalization of high split
-
- float min; // normalized inclusive minimum
- float max; // normalized inclusive maximum
- float flat; // normalized flat region size
- float fuzz; // normalized error tolerance
- float resolution; // normalized resolution in units/mm
-
- float filter; // filter out small variations of this size
- float currentValue; // current value
- float newValue; // most recent value
- float highCurrentValue; // current value of high split
- float highNewValue; // most recent value of high split
-
- void initialize(const RawAbsoluteAxisInfo& rawAxisInfo, const AxisInfo& axisInfo,
- bool explicitlyMapped, float scale, float offset,
- float highScale, float highOffset,
- float min, float max, float flat, float fuzz, float resolution) {
- this->rawAxisInfo = rawAxisInfo;
- this->axisInfo = axisInfo;
- this->explicitlyMapped = explicitlyMapped;
- this->scale = scale;
- this->offset = offset;
- this->highScale = highScale;
- this->highOffset = highOffset;
- this->min = min;
- this->max = max;
- this->flat = flat;
- this->fuzz = fuzz;
- this->resolution = resolution;
- this->filter = 0;
- resetValue();
- }
-
- void resetValue() {
- this->currentValue = 0;
- this->newValue = 0;
- this->highCurrentValue = 0;
- this->highNewValue = 0;
- }
- };
-
- // Axes indexed by raw ABS_* axis index.
- KeyedVector<int32_t, Axis> mAxes;
-
- void sync(nsecs_t when, bool force);
-
- bool haveAxis(int32_t axisId);
- void pruneAxes(bool ignoreExplicitlyMappedAxes);
- bool filterAxes(bool force);
-
- static bool hasValueChangedSignificantly(float filter,
- float newValue, float currentValue, float min, float max);
- static bool hasMovedNearerToValueWithinFilteredRange(float filter,
- float newValue, float currentValue, float thresholdValue);
-
- static bool isCenteredAxis(int32_t axis);
- static int32_t getCompatAxis(int32_t axis);
-
- static void addMotionRange(int32_t axisId, const Axis& axis, InputDeviceInfo* info);
- static void setPointerCoordsAxisValue(PointerCoords* pointerCoords, int32_t axis,
- float value);
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_READER_H
diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp
deleted file mode 100644
index fe61918..0000000
--- a/libs/input/InputWindow.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "InputWindow"
-
-#include "InputWindow.h"
-
-#include <cutils/log.h>
-
-namespace android {
-
-// --- InputWindowInfo ---
-
-bool InputWindowInfo::touchableRegionContainsPoint(int32_t x, int32_t y) const {
- return touchableRegion.contains(x, y);
-}
-
-bool InputWindowInfo::frameContainsPoint(int32_t x, int32_t y) const {
- return x >= frameLeft && x <= frameRight
- && y >= frameTop && y <= frameBottom;
-}
-
-bool InputWindowInfo::isTrustedOverlay() const {
- return layoutParamsType == TYPE_INPUT_METHOD
- || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
- || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
-}
-
-bool InputWindowInfo::supportsSplitTouch() const {
- return layoutParamsFlags & FLAG_SPLIT_TOUCH;
-}
-
-
-// --- InputWindowHandle ---
-
-InputWindowHandle::InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle) :
- inputApplicationHandle(inputApplicationHandle), mInfo(NULL) {
-}
-
-InputWindowHandle::~InputWindowHandle() {
- delete mInfo;
-}
-
-void InputWindowHandle::releaseInfo() {
- if (mInfo) {
- delete mInfo;
- mInfo = NULL;
- }
-}
-
-} // namespace android
diff --git a/libs/input/InputWindow.h b/libs/input/InputWindow.h
deleted file mode 100644
index 28fa7ab..0000000
--- a/libs/input/InputWindow.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_WINDOW_H
-#define _UI_INPUT_WINDOW_H
-
-#include <input/Input.h>
-#include <input/InputTransport.h>
-#include <utils/RefBase.h>
-#include <utils/Timers.h>
-#include <utils/String8.h>
-
-#include <SkRegion.h>
-
-#include "InputApplication.h"
-
-namespace android {
-
-/*
- * Describes the properties of a window that can receive input.
- */
-struct InputWindowInfo {
- // Window flags from WindowManager.LayoutParams
- enum {
- FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 0x00000001,
- FLAG_DIM_BEHIND = 0x00000002,
- FLAG_BLUR_BEHIND = 0x00000004,
- FLAG_NOT_FOCUSABLE = 0x00000008,
- FLAG_NOT_TOUCHABLE = 0x00000010,
- FLAG_NOT_TOUCH_MODAL = 0x00000020,
- FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040,
- FLAG_KEEP_SCREEN_ON = 0x00000080,
- FLAG_LAYOUT_IN_SCREEN = 0x00000100,
- FLAG_LAYOUT_NO_LIMITS = 0x00000200,
- FLAG_FULLSCREEN = 0x00000400,
- FLAG_FORCE_NOT_FULLSCREEN = 0x00000800,
- FLAG_DITHER = 0x00001000,
- FLAG_SECURE = 0x00002000,
- FLAG_SCALED = 0x00004000,
- FLAG_IGNORE_CHEEK_PRESSES = 0x00008000,
- FLAG_LAYOUT_INSET_DECOR = 0x00010000,
- FLAG_ALT_FOCUSABLE_IM = 0x00020000,
- FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000,
- FLAG_SHOW_WHEN_LOCKED = 0x00080000,
- FLAG_SHOW_WALLPAPER = 0x00100000,
- FLAG_TURN_SCREEN_ON = 0x00200000,
- FLAG_DISMISS_KEYGUARD = 0x00400000,
- FLAG_SPLIT_TOUCH = 0x00800000,
- FLAG_SLIPPERY = 0x20000000,
- FLAG_NEEDS_MENU_KEY = 0x40000000,
- };
-
- // Private Window flags from WindowManager.LayoutParams
- enum {
- PRIVATE_FLAG_SYSTEM_ERROR = 0x00000100,
- };
-
- // Window types from WindowManager.LayoutParams
- enum {
- FIRST_APPLICATION_WINDOW = 1,
- TYPE_BASE_APPLICATION = 1,
- TYPE_APPLICATION = 2,
- TYPE_APPLICATION_STARTING = 3,
- LAST_APPLICATION_WINDOW = 99,
- FIRST_SUB_WINDOW = 1000,
- TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW,
- TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1,
- TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2,
- TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3,
- TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4,
- LAST_SUB_WINDOW = 1999,
- FIRST_SYSTEM_WINDOW = 2000,
- TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW,
- TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1,
- TYPE_PHONE = FIRST_SYSTEM_WINDOW+2,
- TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3,
- TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4,
- TYPE_TOAST = FIRST_SYSTEM_WINDOW+5,
- TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6,
- TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7,
- TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8,
- TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9,
- TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10,
- TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11,
- TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
- TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13,
- TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14,
- TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15,
- TYPE_DRAG = FIRST_SYSTEM_WINDOW+16,
- TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17,
- TYPE_POINTER = FIRST_SYSTEM_WINDOW+18,
- TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW+19,
- TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20,
- TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21,
- LAST_SYSTEM_WINDOW = 2999,
- };
-
- enum {
- INPUT_FEATURE_DISABLE_TOUCH_PAD_GESTURES = 0x00000001,
- INPUT_FEATURE_NO_INPUT_CHANNEL = 0x00000002,
- INPUT_FEATURE_DISABLE_USER_ACTIVITY = 0x00000004,
- };
-
- sp<InputChannel> inputChannel;
- String8 name;
- int32_t layoutParamsFlags;
- int32_t layoutParamsPrivateFlags;
- int32_t layoutParamsType;
- nsecs_t dispatchingTimeout;
- int32_t frameLeft;
- int32_t frameTop;
- int32_t frameRight;
- int32_t frameBottom;
- float scaleFactor;
- SkRegion touchableRegion;
- bool visible;
- bool canReceiveKeys;
- bool hasFocus;
- bool hasWallpaper;
- bool paused;
- int32_t layer;
- int32_t ownerPid;
- int32_t ownerUid;
- int32_t inputFeatures;
- int32_t displayId;
-
- bool touchableRegionContainsPoint(int32_t x, int32_t y) const;
- bool frameContainsPoint(int32_t x, int32_t y) const;
-
- /* Returns true if the window is of a trusted type that is allowed to silently
- * overlay other windows for the purpose of implementing the secure views feature.
- * Trusted overlays, such as IME windows, can partly obscure other windows without causing
- * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED.
- */
- bool isTrustedOverlay() const;
-
- bool supportsSplitTouch() const;
-};
-
-
-/*
- * Handle for a window that can receive input.
- *
- * Used by the native input dispatcher to indirectly refer to the window manager objects
- * that describe a window.
- */
-class InputWindowHandle : public RefBase {
-public:
- const sp<InputApplicationHandle> inputApplicationHandle;
-
- inline const InputWindowInfo* getInfo() const {
- return mInfo;
- }
-
- inline sp<InputChannel> getInputChannel() const {
- return mInfo ? mInfo->inputChannel : NULL;
- }
-
- inline String8 getName() const {
- return mInfo ? mInfo->name : String8("<invalid>");
- }
-
- inline nsecs_t getDispatchingTimeout(nsecs_t defaultValue) const {
- return mInfo ? mInfo->dispatchingTimeout : defaultValue;
- }
-
- /**
- * Requests that the state of this object be updated to reflect
- * the most current available information about the application.
- *
- * This method should only be called from within the input dispatcher's
- * critical section.
- *
- * Returns true on success, or false if the handle is no longer valid.
- */
- virtual bool updateInfo() = 0;
-
- /**
- * Releases the storage used by the associated information when it is
- * no longer needed.
- */
- void releaseInfo();
-
-protected:
- InputWindowHandle(const sp<InputApplicationHandle>& inputApplicationHandle);
- virtual ~InputWindowHandle();
-
- InputWindowInfo* mInfo;
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_WINDOW_H
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index 790c0bb..b9e4ce7 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -21,6 +21,7 @@
#include <ui/DisplayInfo.h>
#include <input/Input.h>
+#include <inputflinger/PointerControllerInterface.h>
#include <utils/BitSet.h>
#include <utils/RefBase.h>
#include <utils/Looper.h>
@@ -30,84 +31,6 @@
namespace android {
-/**
- * Interface for tracking a mouse / touch pad pointer and touch pad spots.
- *
- * The spots are sprites on screen that visually represent the positions of
- * fingers
- *
- * The pointer controller is responsible for providing synchronization and for tracking
- * display orientation changes if needed.
- */
-class PointerControllerInterface : public virtual RefBase {
-protected:
- PointerControllerInterface() { }
- virtual ~PointerControllerInterface() { }
-
-public:
- /* Gets the bounds of the region that the pointer can traverse.
- * Returns true if the bounds are available. */
- virtual bool getBounds(float* outMinX, float* outMinY,
- float* outMaxX, float* outMaxY) const = 0;
-
- /* Move the pointer. */
- virtual void move(float deltaX, float deltaY) = 0;
-
- /* Sets a mask that indicates which buttons are pressed. */
- virtual void setButtonState(int32_t buttonState) = 0;
-
- /* Gets a mask that indicates which buttons are pressed. */
- virtual int32_t getButtonState() const = 0;
-
- /* Sets the absolute location of the pointer. */
- virtual void setPosition(float x, float y) = 0;
-
- /* Gets the absolute location of the pointer. */
- virtual void getPosition(float* outX, float* outY) const = 0;
-
- enum Transition {
- // Fade/unfade immediately.
- TRANSITION_IMMEDIATE,
- // Fade/unfade gradually.
- TRANSITION_GRADUAL,
- };
-
- /* Fades the pointer out now. */
- virtual void fade(Transition transition) = 0;
-
- /* Makes the pointer visible if it has faded out.
- * The pointer never unfades itself automatically. This method must be called
- * by the client whenever the pointer is moved or a button is pressed and it
- * wants to ensure that the pointer becomes visible again. */
- virtual void unfade(Transition transition) = 0;
-
- enum Presentation {
- // Show the mouse pointer.
- PRESENTATION_POINTER,
- // Show spots and a spot anchor in place of the mouse pointer.
- PRESENTATION_SPOT,
- };
-
- /* Sets the mode of the pointer controller. */
- virtual void setPresentation(Presentation presentation) = 0;
-
- /* Sets the spots for the current gesture.
- * The spots are not subject to the inactivity timeout like the pointer
- * itself it since they are expected to remain visible for so long as
- * the fingers are on the touch pad.
- *
- * The values of the AMOTION_EVENT_AXIS_PRESSURE axis is significant.
- * For spotCoords, pressure != 0 indicates that the spot's location is being
- * pressed (not hovering).
- */
- virtual void setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
- BitSet32 spotIdBits) = 0;
-
- /* Removes all spots. */
- virtual void clearSpots() = 0;
-};
-
-
/*
* Pointer resources.
*/
diff --git a/libs/input/tests/Android.mk b/libs/input/tests/Android.mk
deleted file mode 100644
index 9278f41..0000000
--- a/libs/input/tests/Android.mk
+++ /dev/null
@@ -1,48 +0,0 @@
-# Build the unit tests.
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# Build the unit tests.
-test_src_files := \
- InputReader_test.cpp \
- InputDispatcher_test.cpp
-
-shared_libraries := \
- libcutils \
- liblog \
- libandroidfw \
- libutils \
- libhardware \
- libhardware_legacy \
- libui \
- libskia \
- libstlport \
- libinput \
- libinputservice
-
-static_libraries := \
- libgtest \
- libgtest_main
-
-c_includes := \
- bionic \
- bionic/libstdc++/include \
- external/gtest/include \
- external/stlport/stlport \
- external/skia/include/core
-
-module_tags := eng tests
-
-$(foreach file,$(test_src_files), \
- $(eval include $(CLEAR_VARS)) \
- $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \
- $(eval LOCAL_STATIC_LIBRARIES := $(static_libraries)) \
- $(eval LOCAL_C_INCLUDES := $(c_includes)) \
- $(eval LOCAL_SRC_FILES := $(file)) \
- $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
- $(eval LOCAL_MODULE_TAGS := $(module_tags)) \
- $(eval include $(BUILD_NATIVE_TEST)) \
-)
-
-# Build the manual test programs.
-include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/libs/input/tests/InputDispatcher_test.cpp b/libs/input/tests/InputDispatcher_test.cpp
deleted file mode 100644
index 26b4fab..0000000
--- a/libs/input/tests/InputDispatcher_test.cpp
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "../InputDispatcher.h"
-
-#include <gtest/gtest.h>
-#include <linux/input.h>
-
-namespace android {
-
-// An arbitrary time value.
-static const nsecs_t ARBITRARY_TIME = 1234;
-
-// An arbitrary device id.
-static const int32_t DEVICE_ID = 1;
-
-// An arbitrary injector pid / uid pair that has permission to inject events.
-static const int32_t INJECTOR_PID = 999;
-static const int32_t INJECTOR_UID = 1001;
-
-
-// --- FakeInputDispatcherPolicy ---
-
-class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
- InputDispatcherConfiguration mConfig;
-
-protected:
- virtual ~FakeInputDispatcherPolicy() {
- }
-
-public:
- FakeInputDispatcherPolicy() {
- }
-
-private:
- virtual void notifyConfigurationChanged(nsecs_t when) {
- }
-
- virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
- const sp<InputWindowHandle>& inputWindowHandle,
- const String8& reason) {
- return 0;
- }
-
- virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) {
- }
-
- virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
- *outConfig = mConfig;
- }
-
- virtual bool isKeyRepeatEnabled() {
- return true;
- }
-
- virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) {
- return true;
- }
-
- virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) {
- }
-
- virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
- }
-
- virtual nsecs_t interceptKeyBeforeDispatching(const sp<InputWindowHandle>& inputWindowHandle,
- const KeyEvent* keyEvent, uint32_t policyFlags) {
- return 0;
- }
-
- virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
- const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
- return false;
- }
-
- virtual void notifySwitch(nsecs_t when,
- uint32_t switchValues, uint32_t switchMask, uint32_t policyFlags) {
- }
-
- virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
- }
-
- virtual bool checkInjectEventsPermissionNonReentrant(
- int32_t injectorPid, int32_t injectorUid) {
- return false;
- }
-};
-
-
-// --- InputDispatcherTest ---
-
-class InputDispatcherTest : public testing::Test {
-protected:
- sp<FakeInputDispatcherPolicy> mFakePolicy;
- sp<InputDispatcher> mDispatcher;
-
- virtual void SetUp() {
- mFakePolicy = new FakeInputDispatcherPolicy();
- mDispatcher = new InputDispatcher(mFakePolicy);
- }
-
- virtual void TearDown() {
- mFakePolicy.clear();
- mDispatcher.clear();
- }
-};
-
-
-TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
- KeyEvent event;
-
- // Rejects undefined key actions.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
- /*action*/ -1, 0,
- AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
- << "Should reject key events with undefined action.";
-
- // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
- AKEY_EVENT_ACTION_MULTIPLE, 0,
- AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
- << "Should reject key events with ACTION_MULTIPLE.";
-}
-
-TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
- MotionEvent event;
- PointerProperties pointerProperties[MAX_POINTERS + 1];
- PointerCoords pointerCoords[MAX_POINTERS + 1];
- for (int i = 0; i <= MAX_POINTERS; i++) {
- pointerProperties[i].clear();
- pointerProperties[i].id = i;
- pointerCoords[i].clear();
- }
-
- // Rejects undefined motion actions.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- /*action*/ -1, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerProperties, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
- << "Should reject motion events with undefined action.";
-
- // Rejects pointer down with invalid index.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerProperties, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
- << "Should reject motion events with pointer down index too large.";
-
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_POINTER_DOWN | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerProperties, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
- << "Should reject motion events with pointer down index too small.";
-
- // Rejects pointer up with invalid index.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerProperties, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
- << "Should reject motion events with pointer up index too large.";
-
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_POINTER_UP | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerProperties, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
- << "Should reject motion events with pointer up index too small.";
-
- // Rejects motion events with invalid number of pointers.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 0, pointerProperties, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
- << "Should reject motion events with 0 pointers.";
-
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
- << "Should reject motion events with more than MAX_POINTERS pointers.";
-
- // Rejects motion events with invalid pointer ids.
- pointerProperties[0].id = -1;
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerProperties, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
- << "Should reject motion events with pointer ids less than 0.";
-
- pointerProperties[0].id = MAX_POINTER_ID + 1;
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 1, pointerProperties, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
- << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
-
- // Rejects motion events with duplicate pointer ids.
- pointerProperties[0].id = 1;
- pointerProperties[1].id = 1;
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
- ARBITRARY_TIME, ARBITRARY_TIME,
- /*pointerCount*/ 2, pointerProperties, pointerCoords);
- ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
- INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
- << "Should reject motion events with duplicate pointer ids.";
-}
-
-} // namespace android
diff --git a/libs/input/tests/InputReader_test.cpp b/libs/input/tests/InputReader_test.cpp
deleted file mode 100644
index aaa973d..0000000
--- a/libs/input/tests/InputReader_test.cpp
+++ /dev/null
@@ -1,5099 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "../InputReader.h"
-
-#include <utils/List.h>
-#include <gtest/gtest.h>
-#include <math.h>
-
-namespace android {
-
-// An arbitrary time value.
-static const nsecs_t ARBITRARY_TIME = 1234;
-
-// Arbitrary display properties.
-static const int32_t DISPLAY_ID = 0;
-static const int32_t DISPLAY_WIDTH = 480;
-static const int32_t DISPLAY_HEIGHT = 800;
-
-// Error tolerance for floating point assertions.
-static const float EPSILON = 0.001f;
-
-template<typename T>
-static inline T min(T a, T b) {
- return a < b ? a : b;
-}
-
-static inline float avg(float x, float y) {
- return (x + y) / 2;
-}
-
-
-// --- FakePointerController ---
-
-class FakePointerController : public PointerControllerInterface {
- bool mHaveBounds;
- float mMinX, mMinY, mMaxX, mMaxY;
- float mX, mY;
- int32_t mButtonState;
-
-protected:
- virtual ~FakePointerController() { }
-
-public:
- FakePointerController() :
- mHaveBounds(false), mMinX(0), mMinY(0), mMaxX(0), mMaxY(0), mX(0), mY(0),
- mButtonState(0) {
- }
-
- void setBounds(float minX, float minY, float maxX, float maxY) {
- mHaveBounds = true;
- mMinX = minX;
- mMinY = minY;
- mMaxX = maxX;
- mMaxY = maxY;
- }
-
- virtual void setPosition(float x, float y) {
- mX = x;
- mY = y;
- }
-
- virtual void setButtonState(int32_t buttonState) {
- mButtonState = buttonState;
- }
-
- virtual int32_t getButtonState() const {
- return mButtonState;
- }
-
- virtual void getPosition(float* outX, float* outY) const {
- *outX = mX;
- *outY = mY;
- }
-
-private:
- virtual bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const {
- *outMinX = mMinX;
- *outMinY = mMinY;
- *outMaxX = mMaxX;
- *outMaxY = mMaxY;
- return mHaveBounds;
- }
-
- virtual void move(float deltaX, float deltaY) {
- mX += deltaX;
- if (mX < mMinX) mX = mMinX;
- if (mX > mMaxX) mX = mMaxX;
- mY += deltaY;
- if (mY < mMinY) mY = mMinY;
- if (mY > mMaxY) mY = mMaxY;
- }
-
- virtual void fade(Transition transition) {
- }
-
- virtual void unfade(Transition transition) {
- }
-
- virtual void setPresentation(Presentation presentation) {
- }
-
- virtual void setSpots(const PointerCoords* spotCoords,
- const uint32_t* spotIdToIndex, BitSet32 spotIdBits) {
- }
-
- virtual void clearSpots() {
- }
-};
-
-
-// --- FakeInputReaderPolicy ---
-
-class FakeInputReaderPolicy : public InputReaderPolicyInterface {
- InputReaderConfiguration mConfig;
- KeyedVector<int32_t, sp<FakePointerController> > mPointerControllers;
- Vector<InputDeviceInfo> mInputDevices;
-
-protected:
- virtual ~FakeInputReaderPolicy() { }
-
-public:
- FakeInputReaderPolicy() {
- }
-
- void setDisplayInfo(int32_t displayId, int32_t width, int32_t height, int32_t orientation) {
- // Set the size of both the internal and external display at the same time.
- bool isRotated = (orientation == DISPLAY_ORIENTATION_90
- || orientation == DISPLAY_ORIENTATION_270);
- DisplayViewport v;
- v.displayId = displayId;
- v.orientation = orientation;
- v.logicalLeft = 0;
- v.logicalTop = 0;
- v.logicalRight = isRotated ? height : width;
- v.logicalBottom = isRotated ? width : height;
- v.physicalLeft = 0;
- v.physicalTop = 0;
- v.physicalRight = isRotated ? height : width;
- v.physicalBottom = isRotated ? width : height;
- v.deviceWidth = isRotated ? height : width;
- v.deviceHeight = isRotated ? width : height;
- mConfig.setDisplayInfo(false /*external*/, v);
- mConfig.setDisplayInfo(true /*external*/, v);
- }
-
- void addExcludedDeviceName(const String8& deviceName) {
- mConfig.excludedDeviceNames.push(deviceName);
- }
-
- void setPointerController(int32_t deviceId, const sp<FakePointerController>& controller) {
- mPointerControllers.add(deviceId, controller);
- }
-
- const InputReaderConfiguration* getReaderConfiguration() const {
- return &mConfig;
- }
-
- const Vector<InputDeviceInfo>& getInputDevices() const {
- return mInputDevices;
- }
-
-private:
- virtual void getReaderConfiguration(InputReaderConfiguration* outConfig) {
- *outConfig = mConfig;
- }
-
- virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) {
- return mPointerControllers.valueFor(deviceId);
- }
-
- virtual void notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices) {
- mInputDevices = inputDevices;
- }
-
- virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier& identifier) {
- return NULL;
- }
-
- virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier) {
- return String8::empty();
- }
-};
-
-
-// --- FakeInputListener ---
-
-class FakeInputListener : public InputListenerInterface {
-private:
- List<NotifyConfigurationChangedArgs> mNotifyConfigurationChangedArgsQueue;
- List<NotifyDeviceResetArgs> mNotifyDeviceResetArgsQueue;
- List<NotifyKeyArgs> mNotifyKeyArgsQueue;
- List<NotifyMotionArgs> mNotifyMotionArgsQueue;
- List<NotifySwitchArgs> mNotifySwitchArgsQueue;
-
-protected:
- virtual ~FakeInputListener() { }
-
-public:
- FakeInputListener() {
- }
-
- void assertNotifyConfigurationChangedWasCalled(
- NotifyConfigurationChangedArgs* outEventArgs = NULL) {
- ASSERT_FALSE(mNotifyConfigurationChangedArgsQueue.empty())
- << "Expected notifyConfigurationChanged() to have been called.";
- if (outEventArgs) {
- *outEventArgs = *mNotifyConfigurationChangedArgsQueue.begin();
- }
- mNotifyConfigurationChangedArgsQueue.erase(mNotifyConfigurationChangedArgsQueue.begin());
- }
-
- void assertNotifyDeviceResetWasCalled(
- NotifyDeviceResetArgs* outEventArgs = NULL) {
- ASSERT_FALSE(mNotifyDeviceResetArgsQueue.empty())
- << "Expected notifyDeviceReset() to have been called.";
- if (outEventArgs) {
- *outEventArgs = *mNotifyDeviceResetArgsQueue.begin();
- }
- mNotifyDeviceResetArgsQueue.erase(mNotifyDeviceResetArgsQueue.begin());
- }
-
- void assertNotifyKeyWasCalled(NotifyKeyArgs* outEventArgs = NULL) {
- ASSERT_FALSE(mNotifyKeyArgsQueue.empty())
- << "Expected notifyKey() to have been called.";
- if (outEventArgs) {
- *outEventArgs = *mNotifyKeyArgsQueue.begin();
- }
- mNotifyKeyArgsQueue.erase(mNotifyKeyArgsQueue.begin());
- }
-
- void assertNotifyKeyWasNotCalled() {
- ASSERT_TRUE(mNotifyKeyArgsQueue.empty())
- << "Expected notifyKey() to not have been called.";
- }
-
- void assertNotifyMotionWasCalled(NotifyMotionArgs* outEventArgs = NULL) {
- ASSERT_FALSE(mNotifyMotionArgsQueue.empty())
- << "Expected notifyMotion() to have been called.";
- if (outEventArgs) {
- *outEventArgs = *mNotifyMotionArgsQueue.begin();
- }
- mNotifyMotionArgsQueue.erase(mNotifyMotionArgsQueue.begin());
- }
-
- void assertNotifyMotionWasNotCalled() {
- ASSERT_TRUE(mNotifyMotionArgsQueue.empty())
- << "Expected notifyMotion() to not have been called.";
- }
-
- void assertNotifySwitchWasCalled(NotifySwitchArgs* outEventArgs = NULL) {
- ASSERT_FALSE(mNotifySwitchArgsQueue.empty())
- << "Expected notifySwitch() to have been called.";
- if (outEventArgs) {
- *outEventArgs = *mNotifySwitchArgsQueue.begin();
- }
- mNotifySwitchArgsQueue.erase(mNotifySwitchArgsQueue.begin());
- }
-
-private:
- virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
- mNotifyConfigurationChangedArgsQueue.push_back(*args);
- }
-
- virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) {
- mNotifyDeviceResetArgsQueue.push_back(*args);
- }
-
- virtual void notifyKey(const NotifyKeyArgs* args) {
- mNotifyKeyArgsQueue.push_back(*args);
- }
-
- virtual void notifyMotion(const NotifyMotionArgs* args) {
- mNotifyMotionArgsQueue.push_back(*args);
- }
-
- virtual void notifySwitch(const NotifySwitchArgs* args) {
- mNotifySwitchArgsQueue.push_back(*args);
- }
-};
-
-
-// --- FakeEventHub ---
-
-class FakeEventHub : public EventHubInterface {
- struct KeyInfo {
- int32_t keyCode;
- uint32_t flags;
- };
-
- struct Device {
- InputDeviceIdentifier identifier;
- uint32_t classes;
- PropertyMap configuration;
- KeyedVector<int, RawAbsoluteAxisInfo> absoluteAxes;
- KeyedVector<int, bool> relativeAxes;
- KeyedVector<int32_t, int32_t> keyCodeStates;
- KeyedVector<int32_t, int32_t> scanCodeStates;
- KeyedVector<int32_t, int32_t> switchStates;
- KeyedVector<int32_t, int32_t> absoluteAxisValue;
- KeyedVector<int32_t, KeyInfo> keysByScanCode;
- KeyedVector<int32_t, KeyInfo> keysByUsageCode;
- KeyedVector<int32_t, bool> leds;
- Vector<VirtualKeyDefinition> virtualKeys;
-
- Device(uint32_t classes) :
- classes(classes) {
- }
- };
-
- KeyedVector<int32_t, Device*> mDevices;
- Vector<String8> mExcludedDevices;
- List<RawEvent> mEvents;
-
-protected:
- virtual ~FakeEventHub() {
- for (size_t i = 0; i < mDevices.size(); i++) {
- delete mDevices.valueAt(i);
- }
- }
-
-public:
- FakeEventHub() { }
-
- void addDevice(int32_t deviceId, const String8& name, uint32_t classes) {
- Device* device = new Device(classes);
- device->identifier.name = name;
- mDevices.add(deviceId, device);
-
- enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_ADDED, 0, 0);
- }
-
- void removeDevice(int32_t deviceId) {
- delete mDevices.valueFor(deviceId);
- mDevices.removeItem(deviceId);
-
- enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_REMOVED, 0, 0);
- }
-
- void finishDeviceScan() {
- enqueueEvent(ARBITRARY_TIME, 0, EventHubInterface::FINISHED_DEVICE_SCAN, 0, 0);
- }
-
- void addConfigurationProperty(int32_t deviceId, const String8& key, const String8& value) {
- Device* device = getDevice(deviceId);
- device->configuration.addProperty(key, value);
- }
-
- void addConfigurationMap(int32_t deviceId, const PropertyMap* configuration) {
- Device* device = getDevice(deviceId);
- device->configuration.addAll(configuration);
- }
-
- void addAbsoluteAxis(int32_t deviceId, int axis,
- int32_t minValue, int32_t maxValue, int flat, int fuzz, int resolution = 0) {
- Device* device = getDevice(deviceId);
-
- RawAbsoluteAxisInfo info;
- info.valid = true;
- info.minValue = minValue;
- info.maxValue = maxValue;
- info.flat = flat;
- info.fuzz = fuzz;
- info.resolution = resolution;
- device->absoluteAxes.add(axis, info);
- }
-
- void addRelativeAxis(int32_t deviceId, int32_t axis) {
- Device* device = getDevice(deviceId);
- device->relativeAxes.add(axis, true);
- }
-
- void setKeyCodeState(int32_t deviceId, int32_t keyCode, int32_t state) {
- Device* device = getDevice(deviceId);
- device->keyCodeStates.replaceValueFor(keyCode, state);
- }
-
- void setScanCodeState(int32_t deviceId, int32_t scanCode, int32_t state) {
- Device* device = getDevice(deviceId);
- device->scanCodeStates.replaceValueFor(scanCode, state);
- }
-
- void setSwitchState(int32_t deviceId, int32_t switchCode, int32_t state) {
- Device* device = getDevice(deviceId);
- device->switchStates.replaceValueFor(switchCode, state);
- }
-
- void setAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t value) {
- Device* device = getDevice(deviceId);
- device->absoluteAxisValue.replaceValueFor(axis, value);
- }
-
- void addKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,
- int32_t keyCode, uint32_t flags) {
- Device* device = getDevice(deviceId);
- KeyInfo info;
- info.keyCode = keyCode;
- info.flags = flags;
- if (scanCode) {
- device->keysByScanCode.add(scanCode, info);
- }
- if (usageCode) {
- device->keysByUsageCode.add(usageCode, info);
- }
- }
-
- void addLed(int32_t deviceId, int32_t led, bool initialState) {
- Device* device = getDevice(deviceId);
- device->leds.add(led, initialState);
- }
-
- bool getLedState(int32_t deviceId, int32_t led) {
- Device* device = getDevice(deviceId);
- return device->leds.valueFor(led);
- }
-
- Vector<String8>& getExcludedDevices() {
- return mExcludedDevices;
- }
-
- void addVirtualKeyDefinition(int32_t deviceId, const VirtualKeyDefinition& definition) {
- Device* device = getDevice(deviceId);
- device->virtualKeys.push(definition);
- }
-
- void enqueueEvent(nsecs_t when, int32_t deviceId, int32_t type,
- int32_t code, int32_t value) {
- RawEvent event;
- event.when = when;
- event.deviceId = deviceId;
- event.type = type;
- event.code = code;
- event.value = value;
- mEvents.push_back(event);
-
- if (type == EV_ABS) {
- setAbsoluteAxisValue(deviceId, code, value);
- }
- }
-
- void assertQueueIsEmpty() {
- ASSERT_EQ(size_t(0), mEvents.size())
- << "Expected the event queue to be empty (fully consumed).";
- }
-
-private:
- Device* getDevice(int32_t deviceId) const {
- ssize_t index = mDevices.indexOfKey(deviceId);
- return index >= 0 ? mDevices.valueAt(index) : NULL;
- }
-
- virtual uint32_t getDeviceClasses(int32_t deviceId) const {
- Device* device = getDevice(deviceId);
- return device ? device->classes : 0;
- }
-
- virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const {
- Device* device = getDevice(deviceId);
- return device ? device->identifier : InputDeviceIdentifier();
- }
-
- virtual int32_t getDeviceControllerNumber(int32_t deviceId) const {
- return 0;
- }
-
- virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const {
- Device* device = getDevice(deviceId);
- if (device) {
- *outConfiguration = device->configuration;
- }
- }
-
- virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
- RawAbsoluteAxisInfo* outAxisInfo) const {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->absoluteAxes.indexOfKey(axis);
- if (index >= 0) {
- *outAxisInfo = device->absoluteAxes.valueAt(index);
- return OK;
- }
- }
- outAxisInfo->clear();
- return -1;
- }
-
- virtual bool hasRelativeAxis(int32_t deviceId, int axis) const {
- Device* device = getDevice(deviceId);
- if (device) {
- return device->relativeAxes.indexOfKey(axis) >= 0;
- }
- return false;
- }
-
- virtual bool hasInputProperty(int32_t deviceId, int property) const {
- return false;
- }
-
- virtual status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,
- int32_t* outKeycode, uint32_t* outFlags) const {
- Device* device = getDevice(deviceId);
- if (device) {
- const KeyInfo* key = getKey(device, scanCode, usageCode);
- if (key) {
- if (outKeycode) {
- *outKeycode = key->keyCode;
- }
- if (outFlags) {
- *outFlags = key->flags;
- }
- return OK;
- }
- }
- return NAME_NOT_FOUND;
- }
-
- const KeyInfo* getKey(Device* device, int32_t scanCode, int32_t usageCode) const {
- if (usageCode) {
- ssize_t index = device->keysByUsageCode.indexOfKey(usageCode);
- if (index >= 0) {
- return &device->keysByUsageCode.valueAt(index);
- }
- }
- if (scanCode) {
- ssize_t index = device->keysByScanCode.indexOfKey(scanCode);
- if (index >= 0) {
- return &device->keysByScanCode.valueAt(index);
- }
- }
- return NULL;
- }
-
- virtual status_t mapAxis(int32_t deviceId, int32_t scanCode,
- AxisInfo* outAxisInfo) const {
- return NAME_NOT_FOUND;
- }
-
- virtual void setExcludedDevices(const Vector<String8>& devices) {
- mExcludedDevices = devices;
- }
-
- virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
- if (mEvents.empty()) {
- return 0;
- }
-
- *buffer = *mEvents.begin();
- mEvents.erase(mEvents.begin());
- return 1;
- }
-
- virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->scanCodeStates.indexOfKey(scanCode);
- if (index >= 0) {
- return device->scanCodeStates.valueAt(index);
- }
- }
- return AKEY_STATE_UNKNOWN;
- }
-
- virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->keyCodeStates.indexOfKey(keyCode);
- if (index >= 0) {
- return device->keyCodeStates.valueAt(index);
- }
- }
- return AKEY_STATE_UNKNOWN;
- }
-
- virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->switchStates.indexOfKey(sw);
- if (index >= 0) {
- return device->switchStates.valueAt(index);
- }
- }
- return AKEY_STATE_UNKNOWN;
- }
-
- virtual status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
- int32_t* outValue) const {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->absoluteAxisValue.indexOfKey(axis);
- if (index >= 0) {
- *outValue = device->absoluteAxisValue.valueAt(index);
- return OK;
- }
- }
- *outValue = 0;
- return -1;
- }
-
- virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
- uint8_t* outFlags) const {
- bool result = false;
- Device* device = getDevice(deviceId);
- if (device) {
- for (size_t i = 0; i < numCodes; i++) {
- for (size_t j = 0; j < device->keysByScanCode.size(); j++) {
- if (keyCodes[i] == device->keysByScanCode.valueAt(j).keyCode) {
- outFlags[i] = 1;
- result = true;
- }
- }
- for (size_t j = 0; j < device->keysByUsageCode.size(); j++) {
- if (keyCodes[i] == device->keysByUsageCode.valueAt(j).keyCode) {
- outFlags[i] = 1;
- result = true;
- }
- }
- }
- }
- return result;
- }
-
- virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->keysByScanCode.indexOfKey(scanCode);
- return index >= 0;
- }
- return false;
- }
-
- virtual bool hasLed(int32_t deviceId, int32_t led) const {
- Device* device = getDevice(deviceId);
- return device && device->leds.indexOfKey(led) >= 0;
- }
-
- virtual void setLedState(int32_t deviceId, int32_t led, bool on) {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->leds.indexOfKey(led);
- if (index >= 0) {
- device->leds.replaceValueAt(led, on);
- } else {
- ADD_FAILURE()
- << "Attempted to set the state of an LED that the EventHub declared "
- "was not present. led=" << led;
- }
- }
- }
-
- virtual void getVirtualKeyDefinitions(int32_t deviceId,
- Vector<VirtualKeyDefinition>& outVirtualKeys) const {
- outVirtualKeys.clear();
-
- Device* device = getDevice(deviceId);
- if (device) {
- outVirtualKeys.appendVector(device->virtualKeys);
- }
- }
-
- virtual sp<KeyCharacterMap> getKeyCharacterMap(int32_t deviceId) const {
- return NULL;
- }
-
- virtual bool setKeyboardLayoutOverlay(int32_t deviceId, const sp<KeyCharacterMap>& map) {
- return false;
- }
-
- virtual void vibrate(int32_t deviceId, nsecs_t duration) {
- }
-
- virtual void cancelVibrate(int32_t deviceId) {
- }
-
- virtual bool isExternal(int32_t deviceId) const {
- return false;
- }
-
- virtual void dump(String8& dump) {
- }
-
- virtual void monitor() {
- }
-
- virtual void requestReopenDevices() {
- }
-
- virtual void wake() {
- }
-};
-
-
-// --- FakeInputReaderContext ---
-
-class FakeInputReaderContext : public InputReaderContext {
- sp<EventHubInterface> mEventHub;
- sp<InputReaderPolicyInterface> mPolicy;
- sp<InputListenerInterface> mListener;
- int32_t mGlobalMetaState;
- bool mUpdateGlobalMetaStateWasCalled;
- int32_t mGeneration;
-
-public:
- FakeInputReaderContext(const sp<EventHubInterface>& eventHub,
- const sp<InputReaderPolicyInterface>& policy,
- const sp<InputListenerInterface>& listener) :
- mEventHub(eventHub), mPolicy(policy), mListener(listener),
- mGlobalMetaState(0) {
- }
-
- virtual ~FakeInputReaderContext() { }
-
- void assertUpdateGlobalMetaStateWasCalled() {
- ASSERT_TRUE(mUpdateGlobalMetaStateWasCalled)
- << "Expected updateGlobalMetaState() to have been called.";
- mUpdateGlobalMetaStateWasCalled = false;
- }
-
- void setGlobalMetaState(int32_t state) {
- mGlobalMetaState = state;
- }
-
-private:
- virtual void updateGlobalMetaState() {
- mUpdateGlobalMetaStateWasCalled = true;
- }
-
- virtual int32_t getGlobalMetaState() {
- return mGlobalMetaState;
- }
-
- virtual EventHubInterface* getEventHub() {
- return mEventHub.get();
- }
-
- virtual InputReaderPolicyInterface* getPolicy() {
- return mPolicy.get();
- }
-
- virtual InputListenerInterface* getListener() {
- return mListener.get();
- }
-
- virtual void disableVirtualKeysUntil(nsecs_t time) {
- }
-
- virtual bool shouldDropVirtualKey(nsecs_t now,
- InputDevice* device, int32_t keyCode, int32_t scanCode) {
- return false;
- }
-
- virtual void fadePointer() {
- }
-
- virtual void requestTimeoutAtTime(nsecs_t when) {
- }
-
- virtual int32_t bumpGeneration() {
- return ++mGeneration;
- }
-};
-
-
-// --- FakeInputMapper ---
-
-class FakeInputMapper : public InputMapper {
- uint32_t mSources;
- int32_t mKeyboardType;
- int32_t mMetaState;
- KeyedVector<int32_t, int32_t> mKeyCodeStates;
- KeyedVector<int32_t, int32_t> mScanCodeStates;
- KeyedVector<int32_t, int32_t> mSwitchStates;
- Vector<int32_t> mSupportedKeyCodes;
- RawEvent mLastEvent;
-
- bool mConfigureWasCalled;
- bool mResetWasCalled;
- bool mProcessWasCalled;
-
-public:
- FakeInputMapper(InputDevice* device, uint32_t sources) :
- InputMapper(device),
- mSources(sources), mKeyboardType(AINPUT_KEYBOARD_TYPE_NONE),
- mMetaState(0),
- mConfigureWasCalled(false), mResetWasCalled(false), mProcessWasCalled(false) {
- }
-
- virtual ~FakeInputMapper() { }
-
- void setKeyboardType(int32_t keyboardType) {
- mKeyboardType = keyboardType;
- }
-
- void setMetaState(int32_t metaState) {
- mMetaState = metaState;
- }
-
- void assertConfigureWasCalled() {
- ASSERT_TRUE(mConfigureWasCalled)
- << "Expected configure() to have been called.";
- mConfigureWasCalled = false;
- }
-
- void assertResetWasCalled() {
- ASSERT_TRUE(mResetWasCalled)
- << "Expected reset() to have been called.";
- mResetWasCalled = false;
- }
-
- void assertProcessWasCalled(RawEvent* outLastEvent = NULL) {
- ASSERT_TRUE(mProcessWasCalled)
- << "Expected process() to have been called.";
- if (outLastEvent) {
- *outLastEvent = mLastEvent;
- }
- mProcessWasCalled = false;
- }
-
- void setKeyCodeState(int32_t keyCode, int32_t state) {
- mKeyCodeStates.replaceValueFor(keyCode, state);
- }
-
- void setScanCodeState(int32_t scanCode, int32_t state) {
- mScanCodeStates.replaceValueFor(scanCode, state);
- }
-
- void setSwitchState(int32_t switchCode, int32_t state) {
- mSwitchStates.replaceValueFor(switchCode, state);
- }
-
- void addSupportedKeyCode(int32_t keyCode) {
- mSupportedKeyCodes.add(keyCode);
- }
-
-private:
- virtual uint32_t getSources() {
- return mSources;
- }
-
- virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo) {
- InputMapper::populateDeviceInfo(deviceInfo);
-
- if (mKeyboardType != AINPUT_KEYBOARD_TYPE_NONE) {
- deviceInfo->setKeyboardType(mKeyboardType);
- }
- }
-
- virtual void configure(nsecs_t when,
- const InputReaderConfiguration* config, uint32_t changes) {
- mConfigureWasCalled = true;
- }
-
- virtual void reset(nsecs_t when) {
- mResetWasCalled = true;
- }
-
- virtual void process(const RawEvent* rawEvent) {
- mLastEvent = *rawEvent;
- mProcessWasCalled = true;
- }
-
- virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
- ssize_t index = mKeyCodeStates.indexOfKey(keyCode);
- return index >= 0 ? mKeyCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
- }
-
- virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
- ssize_t index = mScanCodeStates.indexOfKey(scanCode);
- return index >= 0 ? mScanCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
- }
-
- virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode) {
- ssize_t index = mSwitchStates.indexOfKey(switchCode);
- return index >= 0 ? mSwitchStates.valueAt(index) : AKEY_STATE_UNKNOWN;
- }
-
- virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) {
- bool result = false;
- for (size_t i = 0; i < numCodes; i++) {
- for (size_t j = 0; j < mSupportedKeyCodes.size(); j++) {
- if (keyCodes[i] == mSupportedKeyCodes[j]) {
- outFlags[i] = 1;
- result = true;
- }
- }
- }
- return result;
- }
-
- virtual int32_t getMetaState() {
- return mMetaState;
- }
-
- virtual void fadePointer() {
- }
-};
-
-
-// --- InstrumentedInputReader ---
-
-class InstrumentedInputReader : public InputReader {
- InputDevice* mNextDevice;
-
-public:
- InstrumentedInputReader(const sp<EventHubInterface>& eventHub,
- const sp<InputReaderPolicyInterface>& policy,
- const sp<InputListenerInterface>& listener) :
- InputReader(eventHub, policy, listener),
- mNextDevice(NULL) {
- }
-
- virtual ~InstrumentedInputReader() {
- if (mNextDevice) {
- delete mNextDevice;
- }
- }
-
- void setNextDevice(InputDevice* device) {
- mNextDevice = device;
- }
-
- InputDevice* newDevice(int32_t deviceId, int32_t controllerNumber, const String8& name,
- uint32_t classes) {
- InputDeviceIdentifier identifier;
- identifier.name = name;
- int32_t generation = deviceId + 1;
- return new InputDevice(&mContext, deviceId, generation, controllerNumber, identifier,
- classes);
- }
-
-protected:
- virtual InputDevice* createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
- const InputDeviceIdentifier& identifier, uint32_t classes) {
- if (mNextDevice) {
- InputDevice* device = mNextDevice;
- mNextDevice = NULL;
- return device;
- }
- return InputReader::createDeviceLocked(deviceId, controllerNumber, identifier, classes);
- }
-
- friend class InputReaderTest;
-};
-
-
-// --- InputReaderTest ---
-
-class InputReaderTest : public testing::Test {
-protected:
- sp<FakeInputListener> mFakeListener;
- sp<FakeInputReaderPolicy> mFakePolicy;
- sp<FakeEventHub> mFakeEventHub;
- sp<InstrumentedInputReader> mReader;
-
- virtual void SetUp() {
- mFakeEventHub = new FakeEventHub();
- mFakePolicy = new FakeInputReaderPolicy();
- mFakeListener = new FakeInputListener();
-
- mReader = new InstrumentedInputReader(mFakeEventHub, mFakePolicy, mFakeListener);
- }
-
- virtual void TearDown() {
- mReader.clear();
-
- mFakeListener.clear();
- mFakePolicy.clear();
- mFakeEventHub.clear();
- }
-
- void addDevice(int32_t deviceId, const String8& name, uint32_t classes,
- const PropertyMap* configuration) {
- mFakeEventHub->addDevice(deviceId, name, classes);
-
- if (configuration) {
- mFakeEventHub->addConfigurationMap(deviceId, configuration);
- }
- mFakeEventHub->finishDeviceScan();
- mReader->loopOnce();
- mReader->loopOnce();
- mFakeEventHub->assertQueueIsEmpty();
- }
-
- FakeInputMapper* addDeviceWithFakeInputMapper(int32_t deviceId, int32_t controllerNumber,
- const String8& name, uint32_t classes, uint32_t sources,
- const PropertyMap* configuration) {
- InputDevice* device = mReader->newDevice(deviceId, controllerNumber, name, classes);
- FakeInputMapper* mapper = new FakeInputMapper(device, sources);
- device->addMapper(mapper);
- mReader->setNextDevice(device);
- addDevice(deviceId, name, classes, configuration);
- return mapper;
- }
-};
-
-TEST_F(InputReaderTest, GetInputDevices) {
- ASSERT_NO_FATAL_FAILURE(addDevice(1, String8("keyboard"),
- INPUT_DEVICE_CLASS_KEYBOARD, NULL));
- ASSERT_NO_FATAL_FAILURE(addDevice(2, String8("ignored"),
- 0, NULL)); // no classes so device will be ignored
-
- Vector<InputDeviceInfo> inputDevices;
- mReader->getInputDevices(inputDevices);
-
- ASSERT_EQ(1U, inputDevices.size());
- ASSERT_EQ(1, inputDevices[0].getId());
- ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.string());
- ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, inputDevices[0].getKeyboardType());
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, inputDevices[0].getSources());
- ASSERT_EQ(size_t(0), inputDevices[0].getMotionRanges().size());
-
- // Should also have received a notification describing the new input devices.
- inputDevices = mFakePolicy->getInputDevices();
- ASSERT_EQ(1U, inputDevices.size());
- ASSERT_EQ(1, inputDevices[0].getId());
- ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.string());
- ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, inputDevices[0].getKeyboardType());
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, inputDevices[0].getSources());
- ASSERT_EQ(size_t(0), inputDevices[0].getMotionRanges().size());
-}
-
-TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) {
- FakeInputMapper* mapper = NULL;
- ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"),
- INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL));
- mapper->setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(0,
- AINPUT_SOURCE_ANY, AKEYCODE_A))
- << "Should return unknown when the device id is >= 0 but unknown.";
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(1,
- AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
- << "Should return unknown when the device id is valid but the sources are not supported by the device.";
-
- ASSERT_EQ(AKEY_STATE_DOWN, mReader->getKeyCodeState(1,
- AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
- << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(-1,
- AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
- << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
-
- ASSERT_EQ(AKEY_STATE_DOWN, mReader->getKeyCodeState(-1,
- AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
- << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
-}
-
-TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) {
- FakeInputMapper* mapper = NULL;
- ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"),
- INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL));
- mapper->setScanCodeState(KEY_A, AKEY_STATE_DOWN);
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(0,
- AINPUT_SOURCE_ANY, KEY_A))
- << "Should return unknown when the device id is >= 0 but unknown.";
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(1,
- AINPUT_SOURCE_TRACKBALL, KEY_A))
- << "Should return unknown when the device id is valid but the sources are not supported by the device.";
-
- ASSERT_EQ(AKEY_STATE_DOWN, mReader->getScanCodeState(1,
- AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, KEY_A))
- << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(-1,
- AINPUT_SOURCE_TRACKBALL, KEY_A))
- << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
-
- ASSERT_EQ(AKEY_STATE_DOWN, mReader->getScanCodeState(-1,
- AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, KEY_A))
- << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
-}
-
-TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) {
- FakeInputMapper* mapper = NULL;
- ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"),
- INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL));
- mapper->setSwitchState(SW_LID, AKEY_STATE_DOWN);
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(0,
- AINPUT_SOURCE_ANY, SW_LID))
- << "Should return unknown when the device id is >= 0 but unknown.";
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(1,
- AINPUT_SOURCE_TRACKBALL, SW_LID))
- << "Should return unknown when the device id is valid but the sources are not supported by the device.";
-
- ASSERT_EQ(AKEY_STATE_DOWN, mReader->getSwitchState(1,
- AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, SW_LID))
- << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(-1,
- AINPUT_SOURCE_TRACKBALL, SW_LID))
- << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
-
- ASSERT_EQ(AKEY_STATE_DOWN, mReader->getSwitchState(-1,
- AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, SW_LID))
- << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
-}
-
-TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) {
- FakeInputMapper* mapper = NULL;
- ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"),
- INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL));
- mapper->addSupportedKeyCode(AKEYCODE_A);
- mapper->addSupportedKeyCode(AKEYCODE_B);
-
- const int32_t keyCodes[4] = { AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2 };
- uint8_t flags[4] = { 0, 0, 0, 1 };
-
- ASSERT_FALSE(mReader->hasKeys(0, AINPUT_SOURCE_ANY, 4, keyCodes, flags))
- << "Should return false when device id is >= 0 but unknown.";
- ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
-
- flags[3] = 1;
- ASSERT_FALSE(mReader->hasKeys(1, AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
- << "Should return false when device id is valid but the sources are not supported by the device.";
- ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
-
- flags[3] = 1;
- ASSERT_TRUE(mReader->hasKeys(1, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
- << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
- ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
-
- flags[3] = 1;
- ASSERT_FALSE(mReader->hasKeys(-1, AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
- << "Should return false when the device id is < 0 but the sources are not supported by any device.";
- ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
-
- flags[3] = 1;
- ASSERT_TRUE(mReader->hasKeys(-1, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
- << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
- ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
-}
-
-TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChanged) {
- addDevice(1, String8("ignored"), INPUT_DEVICE_CLASS_KEYBOARD, NULL);
-
- NotifyConfigurationChangedArgs args;
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(&args));
- ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
-}
-
-TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) {
- FakeInputMapper* mapper = NULL;
- ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"),
- INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, NULL));
-
- mFakeEventHub->enqueueEvent(0, 1, EV_KEY, KEY_A, 1);
- mReader->loopOnce();
- ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty());
-
- RawEvent event;
- ASSERT_NO_FATAL_FAILURE(mapper->assertProcessWasCalled(&event));
- ASSERT_EQ(0, event.when);
- ASSERT_EQ(1, event.deviceId);
- ASSERT_EQ(EV_KEY, event.type);
- ASSERT_EQ(KEY_A, event.code);
- ASSERT_EQ(1, event.value);
-}
-
-
-// --- InputDeviceTest ---
-
-class InputDeviceTest : public testing::Test {
-protected:
- static const char* DEVICE_NAME;
- static const int32_t DEVICE_ID;
- static const int32_t DEVICE_GENERATION;
- static const int32_t DEVICE_CONTROLLER_NUMBER;
- static const uint32_t DEVICE_CLASSES;
-
- sp<FakeEventHub> mFakeEventHub;
- sp<FakeInputReaderPolicy> mFakePolicy;
- sp<FakeInputListener> mFakeListener;
- FakeInputReaderContext* mFakeContext;
-
- InputDevice* mDevice;
-
- virtual void SetUp() {
- mFakeEventHub = new FakeEventHub();
- mFakePolicy = new FakeInputReaderPolicy();
- mFakeListener = new FakeInputListener();
- mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeListener);
-
- mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
- InputDeviceIdentifier identifier;
- identifier.name = DEVICE_NAME;
- mDevice = new InputDevice(mFakeContext, DEVICE_ID, DEVICE_GENERATION,
- DEVICE_CONTROLLER_NUMBER, identifier, DEVICE_CLASSES);
- }
-
- virtual void TearDown() {
- delete mDevice;
-
- delete mFakeContext;
- mFakeListener.clear();
- mFakePolicy.clear();
- mFakeEventHub.clear();
- }
-};
-
-const char* InputDeviceTest::DEVICE_NAME = "device";
-const int32_t InputDeviceTest::DEVICE_ID = 1;
-const int32_t InputDeviceTest::DEVICE_GENERATION = 2;
-const int32_t InputDeviceTest::DEVICE_CONTROLLER_NUMBER = 0;
-const uint32_t InputDeviceTest::DEVICE_CLASSES = INPUT_DEVICE_CLASS_KEYBOARD
- | INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_JOYSTICK;
-
-TEST_F(InputDeviceTest, ImmutableProperties) {
- ASSERT_EQ(DEVICE_ID, mDevice->getId());
- ASSERT_STREQ(DEVICE_NAME, mDevice->getName());
- ASSERT_EQ(DEVICE_CLASSES, mDevice->getClasses());
-}
-
-TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
- // Configuration.
- InputReaderConfiguration config;
- mDevice->configure(ARBITRARY_TIME, &config, 0);
-
- // Reset.
- mDevice->reset(ARBITRARY_TIME);
-
- NotifyDeviceResetArgs resetArgs;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
- ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
-
- // Metadata.
- ASSERT_TRUE(mDevice->isIgnored());
- ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mDevice->getSources());
-
- InputDeviceInfo info;
- mDevice->getDeviceInfo(&info);
- ASSERT_EQ(DEVICE_ID, info.getId());
- ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.string());
- ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NONE, info.getKeyboardType());
- ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, info.getSources());
-
- // State queries.
- ASSERT_EQ(0, mDevice->getMetaState());
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, 0))
- << "Ignored device should return unknown key code state.";
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 0))
- << "Ignored device should return unknown scan code state.";
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 0))
- << "Ignored device should return unknown switch state.";
-
- const int32_t keyCodes[2] = { AKEYCODE_A, AKEYCODE_B };
- uint8_t flags[2] = { 0, 1 };
- ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, 2, keyCodes, flags))
- << "Ignored device should never mark any key codes.";
- ASSERT_EQ(0, flags[0]) << "Flag for unsupported key should be unchanged.";
- ASSERT_EQ(1, flags[1]) << "Flag for unsupported key should be unchanged.";
-}
-
-TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRequestsToMappers) {
- // Configuration.
- mFakeEventHub->addConfigurationProperty(DEVICE_ID, String8("key"), String8("value"));
-
- FakeInputMapper* mapper1 = new FakeInputMapper(mDevice, AINPUT_SOURCE_KEYBOARD);
- mapper1->setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- mapper1->setMetaState(AMETA_ALT_ON);
- mapper1->addSupportedKeyCode(AKEYCODE_A);
- mapper1->addSupportedKeyCode(AKEYCODE_B);
- mapper1->setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
- mapper1->setKeyCodeState(AKEYCODE_B, AKEY_STATE_UP);
- mapper1->setScanCodeState(2, AKEY_STATE_DOWN);
- mapper1->setScanCodeState(3, AKEY_STATE_UP);
- mapper1->setSwitchState(4, AKEY_STATE_DOWN);
- mDevice->addMapper(mapper1);
-
- FakeInputMapper* mapper2 = new FakeInputMapper(mDevice, AINPUT_SOURCE_TOUCHSCREEN);
- mapper2->setMetaState(AMETA_SHIFT_ON);
- mDevice->addMapper(mapper2);
-
- InputReaderConfiguration config;
- mDevice->configure(ARBITRARY_TIME, &config, 0);
-
- String8 propertyValue;
- ASSERT_TRUE(mDevice->getConfiguration().tryGetProperty(String8("key"), propertyValue))
- << "Device should have read configuration during configuration phase.";
- ASSERT_STREQ("value", propertyValue.string());
-
- ASSERT_NO_FATAL_FAILURE(mapper1->assertConfigureWasCalled());
- ASSERT_NO_FATAL_FAILURE(mapper2->assertConfigureWasCalled());
-
- // Reset
- mDevice->reset(ARBITRARY_TIME);
- ASSERT_NO_FATAL_FAILURE(mapper1->assertResetWasCalled());
- ASSERT_NO_FATAL_FAILURE(mapper2->assertResetWasCalled());
-
- NotifyDeviceResetArgs resetArgs;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
- ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, resetArgs.deviceId);
-
- // Metadata.
- ASSERT_FALSE(mDevice->isIgnored());
- ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), mDevice->getSources());
-
- InputDeviceInfo info;
- mDevice->getDeviceInfo(&info);
- ASSERT_EQ(DEVICE_ID, info.getId());
- ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.string());
- ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, info.getKeyboardType());
- ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), info.getSources());
-
- // State queries.
- ASSERT_EQ(AMETA_ALT_ON | AMETA_SHIFT_ON, mDevice->getMetaState())
- << "Should query mappers and combine meta states.";
-
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
- << "Should return unknown key code state when source not supported.";
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
- << "Should return unknown scan code state when source not supported.";
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
- << "Should return unknown switch state when source not supported.";
-
- ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, AKEYCODE_A))
- << "Should query mapper when source is supported.";
- ASSERT_EQ(AKEY_STATE_UP, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 3))
- << "Should query mapper when source is supported.";
- ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 4))
- << "Should query mapper when source is supported.";
-
- const int32_t keyCodes[4] = { AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2 };
- uint8_t flags[4] = { 0, 0, 0, 1 };
- ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
- << "Should do nothing when source is unsupported.";
- ASSERT_EQ(0, flags[0]) << "Flag should be unchanged when source is unsupported.";
- ASSERT_EQ(0, flags[1]) << "Flag should be unchanged when source is unsupported.";
- ASSERT_EQ(0, flags[2]) << "Flag should be unchanged when source is unsupported.";
- ASSERT_EQ(1, flags[3]) << "Flag should be unchanged when source is unsupported.";
-
- ASSERT_TRUE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, 4, keyCodes, flags))
- << "Should query mapper when source is supported.";
- ASSERT_EQ(1, flags[0]) << "Flag for supported key should be set.";
- ASSERT_EQ(1, flags[1]) << "Flag for supported key should be set.";
- ASSERT_EQ(0, flags[2]) << "Flag for unsupported key should be unchanged.";
- ASSERT_EQ(1, flags[3]) << "Flag for unsupported key should be unchanged.";
-
- // Event handling.
- RawEvent event;
- mDevice->process(&event, 1);
-
- ASSERT_NO_FATAL_FAILURE(mapper1->assertProcessWasCalled());
- ASSERT_NO_FATAL_FAILURE(mapper2->assertProcessWasCalled());
-}
-
-
-// --- InputMapperTest ---
-
-class InputMapperTest : public testing::Test {
-protected:
- static const char* DEVICE_NAME;
- static const int32_t DEVICE_ID;
- static const int32_t DEVICE_GENERATION;
- static const int32_t DEVICE_CONTROLLER_NUMBER;
- static const uint32_t DEVICE_CLASSES;
-
- sp<FakeEventHub> mFakeEventHub;
- sp<FakeInputReaderPolicy> mFakePolicy;
- sp<FakeInputListener> mFakeListener;
- FakeInputReaderContext* mFakeContext;
- InputDevice* mDevice;
-
- virtual void SetUp() {
- mFakeEventHub = new FakeEventHub();
- mFakePolicy = new FakeInputReaderPolicy();
- mFakeListener = new FakeInputListener();
- mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeListener);
- InputDeviceIdentifier identifier;
- identifier.name = DEVICE_NAME;
- mDevice = new InputDevice(mFakeContext, DEVICE_ID, DEVICE_GENERATION,
- DEVICE_CONTROLLER_NUMBER, identifier, DEVICE_CLASSES);
-
- mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
- }
-
- virtual void TearDown() {
- delete mDevice;
- delete mFakeContext;
- mFakeListener.clear();
- mFakePolicy.clear();
- mFakeEventHub.clear();
- }
-
- void addConfigurationProperty(const char* key, const char* value) {
- mFakeEventHub->addConfigurationProperty(DEVICE_ID, String8(key), String8(value));
- }
-
- void addMapperAndConfigure(InputMapper* mapper) {
- mDevice->addMapper(mapper);
- mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), 0);
- mDevice->reset(ARBITRARY_TIME);
- }
-
- void setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
- int32_t orientation) {
- mFakePolicy->setDisplayInfo(displayId, width, height, orientation);
- mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
- InputReaderConfiguration::CHANGE_DISPLAY_INFO);
- }
-
- static void process(InputMapper* mapper, nsecs_t when, int32_t deviceId, int32_t type,
- int32_t code, int32_t value) {
- RawEvent event;
- event.when = when;
- event.deviceId = deviceId;
- event.type = type;
- event.code = code;
- event.value = value;
- mapper->process(&event);
- }
-
- static void assertMotionRange(const InputDeviceInfo& info,
- int32_t axis, uint32_t source, float min, float max, float flat, float fuzz) {
- const InputDeviceInfo::MotionRange* range = info.getMotionRange(axis, source);
- ASSERT_TRUE(range != NULL) << "Axis: " << axis << " Source: " << source;
- ASSERT_EQ(axis, range->axis) << "Axis: " << axis << " Source: " << source;
- ASSERT_EQ(source, range->source) << "Axis: " << axis << " Source: " << source;
- ASSERT_NEAR(min, range->min, EPSILON) << "Axis: " << axis << " Source: " << source;
- ASSERT_NEAR(max, range->max, EPSILON) << "Axis: " << axis << " Source: " << source;
- ASSERT_NEAR(flat, range->flat, EPSILON) << "Axis: " << axis << " Source: " << source;
- ASSERT_NEAR(fuzz, range->fuzz, EPSILON) << "Axis: " << axis << " Source: " << source;
- }
-
- static void assertPointerCoords(const PointerCoords& coords,
- float x, float y, float pressure, float size,
- float touchMajor, float touchMinor, float toolMajor, float toolMinor,
- float orientation, float distance) {
- ASSERT_NEAR(x, coords.getAxisValue(AMOTION_EVENT_AXIS_X), 1);
- ASSERT_NEAR(y, coords.getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
- ASSERT_NEAR(pressure, coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), EPSILON);
- ASSERT_NEAR(size, coords.getAxisValue(AMOTION_EVENT_AXIS_SIZE), EPSILON);
- ASSERT_NEAR(touchMajor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR), 1);
- ASSERT_NEAR(touchMinor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR), 1);
- ASSERT_NEAR(toolMajor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR), 1);
- ASSERT_NEAR(toolMinor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR), 1);
- ASSERT_NEAR(orientation, coords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION), EPSILON);
- ASSERT_NEAR(distance, coords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE), EPSILON);
- }
-
- static void assertPosition(const sp<FakePointerController>& controller, float x, float y) {
- float actualX, actualY;
- controller->getPosition(&actualX, &actualY);
- ASSERT_NEAR(x, actualX, 1);
- ASSERT_NEAR(y, actualY, 1);
- }
-};
-
-const char* InputMapperTest::DEVICE_NAME = "device";
-const int32_t InputMapperTest::DEVICE_ID = 1;
-const int32_t InputMapperTest::DEVICE_GENERATION = 2;
-const int32_t InputMapperTest::DEVICE_CONTROLLER_NUMBER = 0;
-const uint32_t InputMapperTest::DEVICE_CLASSES = 0; // not needed for current tests
-
-
-// --- SwitchInputMapperTest ---
-
-class SwitchInputMapperTest : public InputMapperTest {
-protected:
-};
-
-TEST_F(SwitchInputMapperTest, GetSources) {
- SwitchInputMapper* mapper = new SwitchInputMapper(mDevice);
- addMapperAndConfigure(mapper);
-
- ASSERT_EQ(uint32_t(AINPUT_SOURCE_SWITCH), mapper->getSources());
-}
-
-TEST_F(SwitchInputMapperTest, GetSwitchState) {
- SwitchInputMapper* mapper = new SwitchInputMapper(mDevice);
- addMapperAndConfigure(mapper);
-
- mFakeEventHub->setSwitchState(DEVICE_ID, SW_LID, 1);
- ASSERT_EQ(1, mapper->getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
-
- mFakeEventHub->setSwitchState(DEVICE_ID, SW_LID, 0);
- ASSERT_EQ(0, mapper->getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
-}
-
-TEST_F(SwitchInputMapperTest, Process) {
- SwitchInputMapper* mapper = new SwitchInputMapper(mDevice);
- addMapperAndConfigure(mapper);
-
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SW, SW_LID, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SW, SW_JACK_PHYSICAL_INSERT, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SW, SW_HEADPHONE_INSERT, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
-
- NotifySwitchArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySwitchWasCalled(&args));
- ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
- ASSERT_EQ((1 << SW_LID) | (1 << SW_JACK_PHYSICAL_INSERT), args.switchValues);
- ASSERT_EQ((1 << SW_LID) | (1 << SW_JACK_PHYSICAL_INSERT) | (1 << SW_HEADPHONE_INSERT),
- args.switchMask);
- ASSERT_EQ(uint32_t(0), args.policyFlags);
-}
-
-
-// --- KeyboardInputMapperTest ---
-
-class KeyboardInputMapperTest : public InputMapperTest {
-protected:
- void testDPadKeyRotation(KeyboardInputMapper* mapper,
- int32_t originalScanCode, int32_t originalKeyCode, int32_t rotatedKeyCode);
-};
-
-void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper* mapper,
- int32_t originalScanCode, int32_t originalKeyCode, int32_t rotatedKeyCode) {
- NotifyKeyArgs args;
-
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, originalScanCode, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
- ASSERT_EQ(originalScanCode, args.scanCode);
- ASSERT_EQ(rotatedKeyCode, args.keyCode);
-
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, originalScanCode, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(originalScanCode, args.scanCode);
- ASSERT_EQ(rotatedKeyCode, args.keyCode);
-}
-
-
-TEST_F(KeyboardInputMapperTest, GetSources) {
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addMapperAndConfigure(mapper);
-
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, mapper->getSources());
-}
-
-TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) {
- const int32_t USAGE_A = 0x070004;
- const int32_t USAGE_UNKNOWN = 0x07ffff;
- mFakeEventHub->addKey(DEVICE_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
- mFakeEventHub->addKey(DEVICE_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
-
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addMapperAndConfigure(mapper);
-
- // Key down by scan code.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_HOME, 1);
- NotifyKeyArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
- ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
- ASSERT_EQ(KEY_HOME, args.scanCode);
- ASSERT_EQ(AMETA_NONE, args.metaState);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
- ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
- // Key up by scan code.
- process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
- EV_KEY, KEY_HOME, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
- ASSERT_EQ(KEY_HOME, args.scanCode);
- ASSERT_EQ(AMETA_NONE, args.metaState);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
- ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
- // Key down by usage code.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_MSC, MSC_SCAN, USAGE_A);
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, 0, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
- ASSERT_EQ(AKEYCODE_A, args.keyCode);
- ASSERT_EQ(0, args.scanCode);
- ASSERT_EQ(AMETA_NONE, args.metaState);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
- ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
- // Key up by usage code.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_MSC, MSC_SCAN, USAGE_A);
- process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
- EV_KEY, 0, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(AKEYCODE_A, args.keyCode);
- ASSERT_EQ(0, args.scanCode);
- ASSERT_EQ(AMETA_NONE, args.metaState);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
- ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
- // Key down with unknown scan code or usage code.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_UNKNOWN, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
- ASSERT_EQ(0, args.keyCode);
- ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
- ASSERT_EQ(AMETA_NONE, args.metaState);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
- ASSERT_EQ(0U, args.policyFlags);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
- // Key up with unknown scan code or usage code.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_MSC, MSC_SCAN, USAGE_UNKNOWN);
- process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
- EV_KEY, KEY_UNKNOWN, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(0, args.keyCode);
- ASSERT_EQ(KEY_UNKNOWN, args.scanCode);
- ASSERT_EQ(AMETA_NONE, args.metaState);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
- ASSERT_EQ(0U, args.policyFlags);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-}
-
-TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) {
- mFakeEventHub->addKey(DEVICE_ID, KEY_LEFTSHIFT, 0, AKEYCODE_SHIFT_LEFT, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_A, 0, AKEYCODE_A, 0);
-
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addMapperAndConfigure(mapper);
-
- // Initial metastate.
- ASSERT_EQ(AMETA_NONE, mapper->getMetaState());
-
- // Metakey down.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_LEFTSHIFT, 1);
- NotifyKeyArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState());
- ASSERT_NO_FATAL_FAILURE(mFakeContext->assertUpdateGlobalMetaStateWasCalled());
-
- // Key down.
- process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
- EV_KEY, KEY_A, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState());
-
- // Key up.
- process(mapper, ARBITRARY_TIME + 2, DEVICE_ID,
- EV_KEY, KEY_A, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState());
-
- // Metakey up.
- process(mapper, ARBITRARY_TIME + 3, DEVICE_ID,
- EV_KEY, KEY_LEFTSHIFT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AMETA_NONE, args.metaState);
- ASSERT_EQ(AMETA_NONE, mapper->getMetaState());
- ASSERT_NO_FATAL_FAILURE(mFakeContext->assertUpdateGlobalMetaStateWasCalled());
-}
-
-TEST_F(KeyboardInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateDPad) {
- mFakeEventHub->addKey(DEVICE_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
-
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addMapperAndConfigure(mapper);
-
- setDisplayInfoAndReconfigure(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_90);
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
-}
-
-TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
- mFakeEventHub->addKey(DEVICE_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
-
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addConfigurationProperty("keyboard.orientationAware", "1");
- addMapperAndConfigure(mapper);
-
- setDisplayInfoAndReconfigure(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0);
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
-
- setDisplayInfoAndReconfigure(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_90);
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN));
-
- setDisplayInfoAndReconfigure(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_180);
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_LEFT));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_UP));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_RIGHT));
-
- setDisplayInfoAndReconfigure(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_270);
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_RIGHT));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_DOWN));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_LEFT));
- ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
- KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_UP));
-
- // Special case: if orientation changes while key is down, we still emit the same keycode
- // in the key up as we did in the key down.
- NotifyKeyArgs args;
-
- setDisplayInfoAndReconfigure(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_270);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 1);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
- ASSERT_EQ(KEY_UP, args.scanCode);
- ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
-
- setDisplayInfoAndReconfigure(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_180);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(KEY_UP, args.scanCode);
- ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
-}
-
-TEST_F(KeyboardInputMapperTest, GetKeyCodeState) {
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addMapperAndConfigure(mapper);
-
- mFakeEventHub->setKeyCodeState(DEVICE_ID, AKEYCODE_A, 1);
- ASSERT_EQ(1, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
-
- mFakeEventHub->setKeyCodeState(DEVICE_ID, AKEYCODE_A, 0);
- ASSERT_EQ(0, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
-}
-
-TEST_F(KeyboardInputMapperTest, GetScanCodeState) {
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addMapperAndConfigure(mapper);
-
- mFakeEventHub->setScanCodeState(DEVICE_ID, KEY_A, 1);
- ASSERT_EQ(1, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
-
- mFakeEventHub->setScanCodeState(DEVICE_ID, KEY_A, 0);
- ASSERT_EQ(0, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
-}
-
-TEST_F(KeyboardInputMapperTest, MarkSupportedKeyCodes) {
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addMapperAndConfigure(mapper);
-
- mFakeEventHub->addKey(DEVICE_ID, KEY_A, 0, AKEYCODE_A, 0);
-
- const int32_t keyCodes[2] = { AKEYCODE_A, AKEYCODE_B };
- uint8_t flags[2] = { 0, 0 };
- ASSERT_TRUE(mapper->markSupportedKeyCodes(AINPUT_SOURCE_ANY, 1, keyCodes, flags));
- ASSERT_TRUE(flags[0]);
- ASSERT_FALSE(flags[1]);
-}
-
-TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) {
- mFakeEventHub->addLed(DEVICE_ID, LED_CAPSL, true /*initially on*/);
- mFakeEventHub->addLed(DEVICE_ID, LED_NUML, false /*initially off*/);
- mFakeEventHub->addLed(DEVICE_ID, LED_SCROLLL, false /*initially off*/);
- mFakeEventHub->addKey(DEVICE_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
-
- KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice,
- AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- addMapperAndConfigure(mapper);
-
- // Initialization should have turned all of the lights off.
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
-
- // Toggle caps lock on.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_CAPSLOCK, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_CAPSLOCK, 0);
- ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper->getMetaState());
-
- // Toggle num lock on.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_NUMLOCK, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_NUMLOCK, 0);
- ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
- ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper->getMetaState());
-
- // Toggle caps lock off.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_CAPSLOCK, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_CAPSLOCK, 0);
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
- ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper->getMetaState());
-
- // Toggle scroll lock on.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_SCROLLLOCK, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_SCROLLLOCK, 0);
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
- ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
- ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper->getMetaState());
-
- // Toggle num lock off.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_NUMLOCK, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_NUMLOCK, 0);
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
- ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper->getMetaState());
-
- // Toggle scroll lock off.
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_SCROLLLOCK, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID,
- EV_KEY, KEY_SCROLLLOCK, 0);
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
- ASSERT_EQ(AMETA_NONE, mapper->getMetaState());
-}
-
-
-// --- CursorInputMapperTest ---
-
-class CursorInputMapperTest : public InputMapperTest {
-protected:
- static const int32_t TRACKBALL_MOVEMENT_THRESHOLD;
-
- sp<FakePointerController> mFakePointerController;
-
- virtual void SetUp() {
- InputMapperTest::SetUp();
-
- mFakePointerController = new FakePointerController();
- mFakePolicy->setPointerController(DEVICE_ID, mFakePointerController);
- }
-
- void testMotionRotation(CursorInputMapper* mapper,
- int32_t originalX, int32_t originalY, int32_t rotatedX, int32_t rotatedY);
-};
-
-const int32_t CursorInputMapperTest::TRACKBALL_MOVEMENT_THRESHOLD = 6;
-
-void CursorInputMapperTest::testMotionRotation(CursorInputMapper* mapper,
- int32_t originalX, int32_t originalY, int32_t rotatedX, int32_t rotatedY) {
- NotifyMotionArgs args;
-
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, originalX);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, originalY);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- float(rotatedX) / TRACKBALL_MOVEMENT_THRESHOLD,
- float(rotatedY) / TRACKBALL_MOVEMENT_THRESHOLD,
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-}
-
-TEST_F(CursorInputMapperTest, WhenModeIsPointer_GetSources_ReturnsMouse) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "pointer");
- addMapperAndConfigure(mapper);
-
- ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper->getSources());
-}
-
-TEST_F(CursorInputMapperTest, WhenModeIsNavigation_GetSources_ReturnsTrackball) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "navigation");
- addMapperAndConfigure(mapper);
-
- ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, mapper->getSources());
-}
-
-TEST_F(CursorInputMapperTest, WhenModeIsPointer_PopulateDeviceInfo_ReturnsRangeFromPointerController) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "pointer");
- addMapperAndConfigure(mapper);
-
- InputDeviceInfo info;
- mapper->populateDeviceInfo(&info);
-
- // Initially there may not be a valid motion range.
- ASSERT_EQ(NULL, info.getMotionRange(AINPUT_MOTION_RANGE_X, AINPUT_SOURCE_MOUSE));
- ASSERT_EQ(NULL, info.getMotionRange(AINPUT_MOTION_RANGE_Y, AINPUT_SOURCE_MOUSE));
- ASSERT_NO_FATAL_FAILURE(assertMotionRange(info,
- AINPUT_MOTION_RANGE_PRESSURE, AINPUT_SOURCE_MOUSE, 0.0f, 1.0f, 0.0f, 0.0f));
-
- // When the bounds are set, then there should be a valid motion range.
- mFakePointerController->setBounds(1, 2, 800 - 1, 480 - 1);
-
- InputDeviceInfo info2;
- mapper->populateDeviceInfo(&info2);
-
- ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2,
- AINPUT_MOTION_RANGE_X, AINPUT_SOURCE_MOUSE,
- 1, 800 - 1, 0.0f, 0.0f));
- ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2,
- AINPUT_MOTION_RANGE_Y, AINPUT_SOURCE_MOUSE,
- 2, 480 - 1, 0.0f, 0.0f));
- ASSERT_NO_FATAL_FAILURE(assertMotionRange(info2,
- AINPUT_MOTION_RANGE_PRESSURE, AINPUT_SOURCE_MOUSE,
- 0.0f, 1.0f, 0.0f, 0.0f));
-}
-
-TEST_F(CursorInputMapperTest, WhenModeIsNavigation_PopulateDeviceInfo_ReturnsScaledRange) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "navigation");
- addMapperAndConfigure(mapper);
-
- InputDeviceInfo info;
- mapper->populateDeviceInfo(&info);
-
- ASSERT_NO_FATAL_FAILURE(assertMotionRange(info,
- AINPUT_MOTION_RANGE_X, AINPUT_SOURCE_TRACKBALL,
- -1.0f, 1.0f, 0.0f, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD));
- ASSERT_NO_FATAL_FAILURE(assertMotionRange(info,
- AINPUT_MOTION_RANGE_Y, AINPUT_SOURCE_TRACKBALL,
- -1.0f, 1.0f, 0.0f, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD));
- ASSERT_NO_FATAL_FAILURE(assertMotionRange(info,
- AINPUT_MOTION_RANGE_PRESSURE, AINPUT_SOURCE_TRACKBALL,
- 0.0f, 1.0f, 0.0f, 0.0f));
-}
-
-TEST_F(CursorInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaState) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "navigation");
- addMapperAndConfigure(mapper);
-
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
- NotifyMotionArgs args;
-
- // Button press.
- // Mostly testing non x/y behavior here so we don't need to check again elsewhere.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, args.source);
- ASSERT_EQ(uint32_t(0), args.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
- ASSERT_EQ(0, args.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
- ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, args.buttonState);
- ASSERT_EQ(0, args.edgeFlags);
- ASSERT_EQ(uint32_t(1), args.pointerCount);
- ASSERT_EQ(0, args.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_MOUSE, args.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
- ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.xPrecision);
- ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.yPrecision);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
- // Button release. Should have same down time.
- process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_KEY, BTN_MOUSE, 0);
- process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, args.source);
- ASSERT_EQ(uint32_t(0), args.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(0, args.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
- ASSERT_EQ(0, args.buttonState);
- ASSERT_EQ(0, args.edgeFlags);
- ASSERT_EQ(uint32_t(1), args.pointerCount);
- ASSERT_EQ(0, args.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_MOUSE, args.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
- ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.xPrecision);
- ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.yPrecision);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-}
-
-TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentXYUpdates) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "navigation");
- addMapperAndConfigure(mapper);
-
- NotifyMotionArgs args;
-
- // Motion in X but not Y.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 1.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
- // Motion in Y but not X.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, -2);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 0.0f, -2.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-}
-
-TEST_F(CursorInputMapperTest, Process_ShouldHandleIndependentButtonUpdates) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "navigation");
- addMapperAndConfigure(mapper);
-
- NotifyMotionArgs args;
-
- // Button press.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
- // Button release.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-}
-
-TEST_F(CursorInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "navigation");
- addMapperAndConfigure(mapper);
-
- NotifyMotionArgs args;
-
- // Combined X, Y and Button.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, -2);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 1.0f / TRACKBALL_MOVEMENT_THRESHOLD, -2.0f / TRACKBALL_MOVEMENT_THRESHOLD,
- 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
- // Move X, Y a bit while pressed.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 2);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 2.0f / TRACKBALL_MOVEMENT_THRESHOLD, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD,
- 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
- // Release Button.
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-}
-
-TEST_F(CursorInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateMotions) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "navigation");
- addMapperAndConfigure(mapper);
-
- setDisplayInfoAndReconfigure(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_90);
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, 1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, 0, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, -1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, 1));
-}
-
-TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "navigation");
- addConfigurationProperty("cursor.orientationAware", "1");
- addMapperAndConfigure(mapper);
-
- setDisplayInfoAndReconfigure(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0);
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, 1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, 0, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, -1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, 1));
-
- setDisplayInfoAndReconfigure(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_90);
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 0, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, -1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, -1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 0, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, 1, 1));
-
- setDisplayInfoAndReconfigure(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_180);
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, -1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, -1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, -1, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, 0, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, 1, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, 1, -1));
-
- setDisplayInfoAndReconfigure(DISPLAY_ID,
- DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_270);
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, -1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, -1, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 0, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, 1, 1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, 1, 0));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, 1, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 0, -1));
- ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, -1));
-}
-
-TEST_F(CursorInputMapperTest, Process_ShouldHandleAllButtons) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "pointer");
- addMapperAndConfigure(mapper);
-
- mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
- mFakePointerController->setPosition(100, 200);
- mFakePointerController->setButtonState(0);
-
- NotifyMotionArgs motionArgs;
- NotifyKeyArgs keyArgs;
-
- // press BTN_LEFT, release BTN_LEFT
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_LEFT, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, mFakePointerController->getButtonState());
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- 100.0f, 200.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_LEFT, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, mFakePointerController->getButtonState());
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, mFakePointerController->getButtonState());
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
- // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_RIGHT, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MIDDLE, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
- motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
- mFakePointerController->getButtonState());
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- 100.0f, 200.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_RIGHT, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, mFakePointerController->getButtonState());
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- 100.0f, 200.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MIDDLE, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, mFakePointerController->getButtonState());
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, mFakePointerController->getButtonState());
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
- // press BTN_BACK, release BTN_BACK
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_BACK, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
- ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, mFakePointerController->getButtonState());
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_BACK, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, mFakePointerController->getButtonState());
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
- ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
-
- // press BTN_SIDE, release BTN_SIDE
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_SIDE, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
- ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, mFakePointerController->getButtonState());
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_SIDE, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, mFakePointerController->getButtonState());
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
- ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
-
- // press BTN_FORWARD, release BTN_FORWARD
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_FORWARD, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
- ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, mFakePointerController->getButtonState());
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_FORWARD, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, mFakePointerController->getButtonState());
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
- ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
-
- // press BTN_EXTRA, release BTN_EXTRA
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_EXTRA, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
- ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, mFakePointerController->getButtonState());
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
-
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_EXTRA, 0);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, mFakePointerController->getButtonState());
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- 100.0f, 200.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
- ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
-}
-
-TEST_F(CursorInputMapperTest, Process_WhenModeIsPointer_ShouldMoveThePointerAround) {
- CursorInputMapper* mapper = new CursorInputMapper(mDevice);
- addConfigurationProperty("cursor.mode", "pointer");
- addMapperAndConfigure(mapper);
-
- mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
- mFakePointerController->setPosition(100, 200);
- mFakePointerController->setButtonState(0);
-
- NotifyMotionArgs args;
-
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 10);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 20);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 110.0f, 220.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
- ASSERT_NO_FATAL_FAILURE(assertPosition(mFakePointerController, 110.0f, 220.0f));
-}
-
-
-// --- TouchInputMapperTest ---
-
-class TouchInputMapperTest : public InputMapperTest {
-protected:
- static const int32_t RAW_X_MIN;
- static const int32_t RAW_X_MAX;
- static const int32_t RAW_Y_MIN;
- static const int32_t RAW_Y_MAX;
- static const int32_t RAW_TOUCH_MIN;
- static const int32_t RAW_TOUCH_MAX;
- static const int32_t RAW_TOOL_MIN;
- static const int32_t RAW_TOOL_MAX;
- static const int32_t RAW_PRESSURE_MIN;
- static const int32_t RAW_PRESSURE_MAX;
- static const int32_t RAW_ORIENTATION_MIN;
- static const int32_t RAW_ORIENTATION_MAX;
- static const int32_t RAW_DISTANCE_MIN;
- static const int32_t RAW_DISTANCE_MAX;
- static const int32_t RAW_TILT_MIN;
- static const int32_t RAW_TILT_MAX;
- static const int32_t RAW_ID_MIN;
- static const int32_t RAW_ID_MAX;
- static const int32_t RAW_SLOT_MIN;
- static const int32_t RAW_SLOT_MAX;
- static const float X_PRECISION;
- static const float Y_PRECISION;
-
- static const float GEOMETRIC_SCALE;
-
- static const VirtualKeyDefinition VIRTUAL_KEYS[2];
-
- enum Axes {
- POSITION = 1 << 0,
- TOUCH = 1 << 1,
- TOOL = 1 << 2,
- PRESSURE = 1 << 3,
- ORIENTATION = 1 << 4,
- MINOR = 1 << 5,
- ID = 1 << 6,
- DISTANCE = 1 << 7,
- TILT = 1 << 8,
- SLOT = 1 << 9,
- TOOL_TYPE = 1 << 10,
- };
-
- void prepareDisplay(int32_t orientation);
- void prepareVirtualKeys();
- int32_t toRawX(float displayX);
- int32_t toRawY(float displayY);
- float toDisplayX(int32_t rawX);
- float toDisplayY(int32_t rawY);
-};
-
-const int32_t TouchInputMapperTest::RAW_X_MIN = 25;
-const int32_t TouchInputMapperTest::RAW_X_MAX = 1019;
-const int32_t TouchInputMapperTest::RAW_Y_MIN = 30;
-const int32_t TouchInputMapperTest::RAW_Y_MAX = 1009;
-const int32_t TouchInputMapperTest::RAW_TOUCH_MIN = 0;
-const int32_t TouchInputMapperTest::RAW_TOUCH_MAX = 31;
-const int32_t TouchInputMapperTest::RAW_TOOL_MIN = 0;
-const int32_t TouchInputMapperTest::RAW_TOOL_MAX = 15;
-const int32_t TouchInputMapperTest::RAW_PRESSURE_MIN = RAW_TOUCH_MIN;
-const int32_t TouchInputMapperTest::RAW_PRESSURE_MAX = RAW_TOUCH_MAX;
-const int32_t TouchInputMapperTest::RAW_ORIENTATION_MIN = -7;
-const int32_t TouchInputMapperTest::RAW_ORIENTATION_MAX = 7;
-const int32_t TouchInputMapperTest::RAW_DISTANCE_MIN = 0;
-const int32_t TouchInputMapperTest::RAW_DISTANCE_MAX = 7;
-const int32_t TouchInputMapperTest::RAW_TILT_MIN = 0;
-const int32_t TouchInputMapperTest::RAW_TILT_MAX = 150;
-const int32_t TouchInputMapperTest::RAW_ID_MIN = 0;
-const int32_t TouchInputMapperTest::RAW_ID_MAX = 9;
-const int32_t TouchInputMapperTest::RAW_SLOT_MIN = 0;
-const int32_t TouchInputMapperTest::RAW_SLOT_MAX = 9;
-const float TouchInputMapperTest::X_PRECISION = float(RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH;
-const float TouchInputMapperTest::Y_PRECISION = float(RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT;
-
-const float TouchInputMapperTest::GEOMETRIC_SCALE =
- avg(float(DISPLAY_WIDTH) / (RAW_X_MAX - RAW_X_MIN + 1),
- float(DISPLAY_HEIGHT) / (RAW_Y_MAX - RAW_Y_MIN + 1));
-
-const VirtualKeyDefinition TouchInputMapperTest::VIRTUAL_KEYS[2] = {
- { KEY_HOME, 60, DISPLAY_HEIGHT + 15, 20, 20 },
- { KEY_MENU, DISPLAY_HEIGHT - 60, DISPLAY_WIDTH + 15, 20, 20 },
-};
-
-void TouchInputMapperTest::prepareDisplay(int32_t orientation) {
- setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation);
-}
-
-void TouchInputMapperTest::prepareVirtualKeys() {
- mFakeEventHub->addVirtualKeyDefinition(DEVICE_ID, VIRTUAL_KEYS[0]);
- mFakeEventHub->addVirtualKeyDefinition(DEVICE_ID, VIRTUAL_KEYS[1]);
- mFakeEventHub->addKey(DEVICE_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
- mFakeEventHub->addKey(DEVICE_ID, KEY_MENU, 0, AKEYCODE_MENU, POLICY_FLAG_WAKE);
-}
-
-int32_t TouchInputMapperTest::toRawX(float displayX) {
- return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN + 1) / DISPLAY_WIDTH + RAW_X_MIN);
-}
-
-int32_t TouchInputMapperTest::toRawY(float displayY) {
- return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN + 1) / DISPLAY_HEIGHT + RAW_Y_MIN);
-}
-
-float TouchInputMapperTest::toDisplayX(int32_t rawX) {
- return float(rawX - RAW_X_MIN) * DISPLAY_WIDTH / (RAW_X_MAX - RAW_X_MIN + 1);
-}
-
-float TouchInputMapperTest::toDisplayY(int32_t rawY) {
- return float(rawY - RAW_Y_MIN) * DISPLAY_HEIGHT / (RAW_Y_MAX - RAW_Y_MIN + 1);
-}
-
-
-// --- SingleTouchInputMapperTest ---
-
-class SingleTouchInputMapperTest : public TouchInputMapperTest {
-protected:
- void prepareButtons();
- void prepareAxes(int axes);
-
- void processDown(SingleTouchInputMapper* mapper, int32_t x, int32_t y);
- void processMove(SingleTouchInputMapper* mapper, int32_t x, int32_t y);
- void processUp(SingleTouchInputMapper* mappery);
- void processPressure(SingleTouchInputMapper* mapper, int32_t pressure);
- void processToolMajor(SingleTouchInputMapper* mapper, int32_t toolMajor);
- void processDistance(SingleTouchInputMapper* mapper, int32_t distance);
- void processTilt(SingleTouchInputMapper* mapper, int32_t tiltX, int32_t tiltY);
- void processKey(SingleTouchInputMapper* mapper, int32_t code, int32_t value);
- void processSync(SingleTouchInputMapper* mapper);
-};
-
-void SingleTouchInputMapperTest::prepareButtons() {
- mFakeEventHub->addKey(DEVICE_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
-}
-
-void SingleTouchInputMapperTest::prepareAxes(int axes) {
- if (axes & POSITION) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_X,
- RAW_X_MIN, RAW_X_MAX, 0, 0);
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_Y,
- RAW_Y_MIN, RAW_Y_MAX, 0, 0);
- }
- if (axes & PRESSURE) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_PRESSURE,
- RAW_PRESSURE_MIN, RAW_PRESSURE_MAX, 0, 0);
- }
- if (axes & TOOL) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_TOOL_WIDTH,
- RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0);
- }
- if (axes & DISTANCE) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_DISTANCE,
- RAW_DISTANCE_MIN, RAW_DISTANCE_MAX, 0, 0);
- }
- if (axes & TILT) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_TILT_X,
- RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_TILT_Y,
- RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
- }
-}
-
-void SingleTouchInputMapperTest::processDown(SingleTouchInputMapper* mapper, int32_t x, int32_t y) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_TOUCH, 1);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_X, x);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_Y, y);
-}
-
-void SingleTouchInputMapperTest::processMove(SingleTouchInputMapper* mapper, int32_t x, int32_t y) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_X, x);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_Y, y);
-}
-
-void SingleTouchInputMapperTest::processUp(SingleTouchInputMapper* mapper) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_TOUCH, 0);
-}
-
-void SingleTouchInputMapperTest::processPressure(
- SingleTouchInputMapper* mapper, int32_t pressure) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_PRESSURE, pressure);
-}
-
-void SingleTouchInputMapperTest::processToolMajor(
- SingleTouchInputMapper* mapper, int32_t toolMajor) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_TOOL_WIDTH, toolMajor);
-}
-
-void SingleTouchInputMapperTest::processDistance(
- SingleTouchInputMapper* mapper, int32_t distance) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_DISTANCE, distance);
-}
-
-void SingleTouchInputMapperTest::processTilt(
- SingleTouchInputMapper* mapper, int32_t tiltX, int32_t tiltY) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_TILT_X, tiltX);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_TILT_Y, tiltY);
-}
-
-void SingleTouchInputMapperTest::processKey(
- SingleTouchInputMapper* mapper, int32_t code, int32_t value) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, code, value);
-}
-
-void SingleTouchInputMapperTest::processSync(SingleTouchInputMapper* mapper) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
-}
-
-
-TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndNotACursor_ReturnsPointer) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- prepareButtons();
- prepareAxes(POSITION);
- addMapperAndConfigure(mapper);
-
- ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper->getSources());
-}
-
-TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndIsACursor_ReturnsTouchPad) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- mFakeEventHub->addRelativeAxis(DEVICE_ID, REL_X);
- mFakeEventHub->addRelativeAxis(DEVICE_ID, REL_Y);
- prepareButtons();
- prepareAxes(POSITION);
- addMapperAndConfigure(mapper);
-
- ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper->getSources());
-}
-
-TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchPad_ReturnsTouchPad) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- prepareButtons();
- prepareAxes(POSITION);
- addConfigurationProperty("touch.deviceType", "touchPad");
- addMapperAndConfigure(mapper);
-
- ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper->getSources());
-}
-
-TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- prepareButtons();
- prepareAxes(POSITION);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- addMapperAndConfigure(mapper);
-
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper->getSources());
-}
-
-TEST_F(SingleTouchInputMapperTest, GetKeyCodeState) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareButtons();
- prepareAxes(POSITION);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- // Unknown key.
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
-
- // Virtual key is down.
- int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
- int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
- processDown(mapper, x, y);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
-
- ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
-
- // Virtual key is up.
- processUp(mapper);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
-
- ASSERT_EQ(AKEY_STATE_UP, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
-}
-
-TEST_F(SingleTouchInputMapperTest, GetScanCodeState) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareButtons();
- prepareAxes(POSITION);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- // Unknown key.
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
-
- // Virtual key is down.
- int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
- int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
- processDown(mapper, x, y);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
-
- ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
-
- // Virtual key is up.
- processUp(mapper);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled());
-
- ASSERT_EQ(AKEY_STATE_UP, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
-}
-
-TEST_F(SingleTouchInputMapperTest, MarkSupportedKeyCodes) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareButtons();
- prepareAxes(POSITION);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- const int32_t keys[2] = { AKEYCODE_HOME, AKEYCODE_A };
- uint8_t flags[2] = { 0, 0 };
- ASSERT_TRUE(mapper->markSupportedKeyCodes(AINPUT_SOURCE_ANY, 2, keys, flags));
- ASSERT_TRUE(flags[0]);
- ASSERT_FALSE(flags[1]);
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNormally_SendsKeyDownAndKeyUp) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareButtons();
- prepareAxes(POSITION);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
- NotifyKeyArgs args;
-
- // Press virtual key.
- int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
- int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
- processDown(mapper, x, y);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
- ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
- ASSERT_EQ(KEY_HOME, args.scanCode);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
- // Release virtual key.
- processUp(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
- ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
- ASSERT_EQ(DEVICE_ID, args.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
- ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
- ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
- ASSERT_EQ(KEY_HOME, args.scanCode);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
- ASSERT_EQ(ARBITRARY_TIME, args.downTime);
-
- // Should not have sent any motions.
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfBounds_SendsKeyDownAndKeyCancel) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareButtons();
- prepareAxes(POSITION);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
- NotifyKeyArgs keyArgs;
-
- // Press virtual key.
- int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
- int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
- processDown(mapper, x, y);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
- ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, keyArgs.flags);
- ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
- ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
- ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
-
- // Move out of bounds. This should generate a cancel and a pointer down since we moved
- // into the display area.
- y -= 100;
- processMove(mapper, x, y);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
- ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
- ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
- | AKEY_EVENT_FLAG_CANCELED, keyArgs.flags);
- ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
- ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
- ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
-
- NotifyMotionArgs motionArgs;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Keep moving out of bounds. Should generate a pointer move.
- y -= 50;
- processMove(mapper, x, y);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Release out of bounds. Should generate a pointer up.
- processUp(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Should not have sent any more keys or motions.
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMovesIn_SendsDownAsTouchEntersDisplay) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareButtons();
- prepareAxes(POSITION);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
- NotifyMotionArgs motionArgs;
-
- // Initially go down out of bounds.
- int32_t x = -10;
- int32_t y = -10;
- processDown(mapper, x, y);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
-
- // Move into the display area. Should generate a pointer down.
- x = 50;
- y = 75;
- processMove(mapper, x, y);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Release. Should generate a pointer up.
- processUp(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Should not have sent any more keys or motions.
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareButtons();
- prepareAxes(POSITION);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
- NotifyMotionArgs motionArgs;
-
- // Down.
- int32_t x = 100;
- int32_t y = 125;
- processDown(mapper, x, y);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Move.
- x += 50;
- y += 75;
- processMove(mapper, x, y);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Up.
- processUp(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Should not have sent any more keys or motions.
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenNotOrientationAware_DoesNotRotateMotions) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareButtons();
- prepareAxes(POSITION);
- addConfigurationProperty("touch.orientationAware", "0");
- addMapperAndConfigure(mapper);
-
- NotifyMotionArgs args;
-
- // Rotation 90.
- prepareDisplay(DISPLAY_ORIENTATION_90);
- processDown(mapper, toRawX(50), toRawY(75));
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
- ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
-
- processUp(mapper);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenOrientationAware_RotatesMotions) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareButtons();
- prepareAxes(POSITION);
- addMapperAndConfigure(mapper);
-
- NotifyMotionArgs args;
-
- // Rotation 0.
- prepareDisplay(DISPLAY_ORIENTATION_0);
- processDown(mapper, toRawX(50), toRawY(75));
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
- ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
-
- processUp(mapper);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
-
- // Rotation 90.
- prepareDisplay(DISPLAY_ORIENTATION_90);
- processDown(mapper, RAW_X_MAX - toRawX(75) + RAW_X_MIN, toRawY(50));
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
- ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
-
- processUp(mapper);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
-
- // Rotation 180.
- prepareDisplay(DISPLAY_ORIENTATION_180);
- processDown(mapper, RAW_X_MAX - toRawX(50) + RAW_X_MIN, RAW_Y_MAX - toRawY(75) + RAW_Y_MIN);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
- ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
-
- processUp(mapper);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
-
- // Rotation 270.
- prepareDisplay(DISPLAY_ORIENTATION_270);
- processDown(mapper, toRawX(75), RAW_Y_MAX - toRawY(50) + RAW_Y_MIN);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_NEAR(50, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
- ASSERT_NEAR(75, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
-
- processUp(mapper);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled());
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareButtons();
- prepareAxes(POSITION | PRESSURE | TOOL | DISTANCE | TILT);
- addMapperAndConfigure(mapper);
-
- // These calculations are based on the input device calibration documentation.
- int32_t rawX = 100;
- int32_t rawY = 200;
- int32_t rawPressure = 10;
- int32_t rawToolMajor = 12;
- int32_t rawDistance = 2;
- int32_t rawTiltX = 30;
- int32_t rawTiltY = 110;
-
- float x = toDisplayX(rawX);
- float y = toDisplayY(rawY);
- float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
- float size = float(rawToolMajor) / RAW_TOOL_MAX;
- float tool = float(rawToolMajor) * GEOMETRIC_SCALE;
- float distance = float(rawDistance);
-
- float tiltCenter = (RAW_TILT_MAX + RAW_TILT_MIN) * 0.5f;
- float tiltScale = M_PI / 180;
- float tiltXAngle = (rawTiltX - tiltCenter) * tiltScale;
- float tiltYAngle = (rawTiltY - tiltCenter) * tiltScale;
- float orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
- float tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
-
- processDown(mapper, rawX, rawY);
- processPressure(mapper, rawPressure);
- processToolMajor(mapper, rawToolMajor);
- processDistance(mapper, rawDistance);
- processTilt(mapper, rawTiltX, rawTiltY);
- processSync(mapper);
-
- NotifyMotionArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- x, y, pressure, size, tool, tool, tool, tool, orientation, distance));
- ASSERT_EQ(tilt, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_TILT));
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllButtons) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareButtons();
- prepareAxes(POSITION);
- addMapperAndConfigure(mapper);
-
- NotifyMotionArgs motionArgs;
- NotifyKeyArgs keyArgs;
-
- processDown(mapper, 100, 200);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
- ASSERT_EQ(0, motionArgs.buttonState);
-
- // press BTN_LEFT, release BTN_LEFT
- processKey(mapper, BTN_LEFT, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
-
- processKey(mapper, BTN_LEFT, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-
- // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
- processKey(mapper, BTN_RIGHT, 1);
- processKey(mapper, BTN_MIDDLE, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
- motionArgs.buttonState);
-
- processKey(mapper, BTN_RIGHT, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-
- processKey(mapper, BTN_MIDDLE, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-
- // press BTN_BACK, release BTN_BACK
- processKey(mapper, BTN_BACK, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
- ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-
- processKey(mapper, BTN_BACK, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
- ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
-
- // press BTN_SIDE, release BTN_SIDE
- processKey(mapper, BTN_SIDE, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
- ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-
- processKey(mapper, BTN_SIDE, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
- ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
-
- // press BTN_FORWARD, release BTN_FORWARD
- processKey(mapper, BTN_FORWARD, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
- ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-
- processKey(mapper, BTN_FORWARD, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
- ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
-
- // press BTN_EXTRA, release BTN_EXTRA
- processKey(mapper, BTN_EXTRA, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
- ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-
- processKey(mapper, BTN_EXTRA, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
- ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
-
- // press BTN_STYLUS, release BTN_STYLUS
- processKey(mapper, BTN_STYLUS, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY, motionArgs.buttonState);
-
- processKey(mapper, BTN_STYLUS, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-
- // press BTN_STYLUS2, release BTN_STYLUS2
- processKey(mapper, BTN_STYLUS2, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
-
- processKey(mapper, BTN_STYLUS2, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-
- // release touch
- processUp(mapper);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
- ASSERT_EQ(0, motionArgs.buttonState);
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareButtons();
- prepareAxes(POSITION);
- addMapperAndConfigure(mapper);
-
- NotifyMotionArgs motionArgs;
-
- // default tool type is finger
- processDown(mapper, 100, 200);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
-
- // eraser
- processKey(mapper, BTN_TOOL_RUBBER, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_ERASER, motionArgs.pointerProperties[0].toolType);
-
- // stylus
- processKey(mapper, BTN_TOOL_RUBBER, 0);
- processKey(mapper, BTN_TOOL_PEN, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType);
-
- // brush
- processKey(mapper, BTN_TOOL_PEN, 0);
- processKey(mapper, BTN_TOOL_BRUSH, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType);
-
- // pencil
- processKey(mapper, BTN_TOOL_BRUSH, 0);
- processKey(mapper, BTN_TOOL_PENCIL, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType);
-
- // airbrush
- processKey(mapper, BTN_TOOL_PENCIL, 0);
- processKey(mapper, BTN_TOOL_AIRBRUSH, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType);
-
- // mouse
- processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
- processKey(mapper, BTN_TOOL_MOUSE, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_MOUSE, motionArgs.pointerProperties[0].toolType);
-
- // lens
- processKey(mapper, BTN_TOOL_MOUSE, 0);
- processKey(mapper, BTN_TOOL_LENS, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_MOUSE, motionArgs.pointerProperties[0].toolType);
-
- // double-tap
- processKey(mapper, BTN_TOOL_LENS, 0);
- processKey(mapper, BTN_TOOL_DOUBLETAP, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
-
- // triple-tap
- processKey(mapper, BTN_TOOL_DOUBLETAP, 0);
- processKey(mapper, BTN_TOOL_TRIPLETAP, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
-
- // quad-tap
- processKey(mapper, BTN_TOOL_TRIPLETAP, 0);
- processKey(mapper, BTN_TOOL_QUADTAP, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
-
- // finger
- processKey(mapper, BTN_TOOL_QUADTAP, 0);
- processKey(mapper, BTN_TOOL_FINGER, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
-
- // stylus trumps finger
- processKey(mapper, BTN_TOOL_PEN, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType);
-
- // eraser trumps stylus
- processKey(mapper, BTN_TOOL_RUBBER, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_ERASER, motionArgs.pointerProperties[0].toolType);
-
- // mouse trumps eraser
- processKey(mapper, BTN_TOOL_MOUSE, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_MOUSE, motionArgs.pointerProperties[0].toolType);
-
- // back to default tool type
- processKey(mapper, BTN_TOOL_MOUSE, 0);
- processKey(mapper, BTN_TOOL_RUBBER, 0);
- processKey(mapper, BTN_TOOL_PEN, 0);
- processKey(mapper, BTN_TOOL_FINGER, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareButtons();
- prepareAxes(POSITION);
- mFakeEventHub->addKey(DEVICE_ID, BTN_TOOL_FINGER, 0, AKEYCODE_UNKNOWN, 0);
- addMapperAndConfigure(mapper);
-
- NotifyMotionArgs motionArgs;
-
- // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0
- processKey(mapper, BTN_TOOL_FINGER, 1);
- processMove(mapper, 100, 200);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
-
- // move a little
- processMove(mapper, 150, 250);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-
- // down when BTN_TOUCH is pressed, pressure defaults to 1
- processKey(mapper, BTN_TOUCH, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
-
- // up when BTN_TOUCH is released, hover restored
- processKey(mapper, BTN_TOUCH, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-
- // exit hover when pointer goes away
- processKey(mapper, BTN_TOOL_FINGER, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-}
-
-TEST_F(SingleTouchInputMapperTest, Process_WhenAbsPressureIsPresent_HoversIfItsValueIsZero) {
- SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareButtons();
- prepareAxes(POSITION | PRESSURE);
- addMapperAndConfigure(mapper);
-
- NotifyMotionArgs motionArgs;
-
- // initially hovering because pressure is 0
- processDown(mapper, 100, 200);
- processPressure(mapper, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
-
- // move a little
- processMove(mapper, 150, 250);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-
- // down when pressure is non-zero
- processPressure(mapper, RAW_PRESSURE_MAX);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
-
- // up when pressure becomes 0, hover restored
- processPressure(mapper, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-
- // exit hover when pointer goes away
- processUp(mapper);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-}
-
-
-// --- MultiTouchInputMapperTest ---
-
-class MultiTouchInputMapperTest : public TouchInputMapperTest {
-protected:
- void prepareAxes(int axes);
-
- void processPosition(MultiTouchInputMapper* mapper, int32_t x, int32_t y);
- void processTouchMajor(MultiTouchInputMapper* mapper, int32_t touchMajor);
- void processTouchMinor(MultiTouchInputMapper* mapper, int32_t touchMinor);
- void processToolMajor(MultiTouchInputMapper* mapper, int32_t toolMajor);
- void processToolMinor(MultiTouchInputMapper* mapper, int32_t toolMinor);
- void processOrientation(MultiTouchInputMapper* mapper, int32_t orientation);
- void processPressure(MultiTouchInputMapper* mapper, int32_t pressure);
- void processDistance(MultiTouchInputMapper* mapper, int32_t distance);
- void processId(MultiTouchInputMapper* mapper, int32_t id);
- void processSlot(MultiTouchInputMapper* mapper, int32_t slot);
- void processToolType(MultiTouchInputMapper* mapper, int32_t toolType);
- void processKey(MultiTouchInputMapper* mapper, int32_t code, int32_t value);
- void processMTSync(MultiTouchInputMapper* mapper);
- void processSync(MultiTouchInputMapper* mapper);
-};
-
-void MultiTouchInputMapperTest::prepareAxes(int axes) {
- if (axes & POSITION) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_POSITION_X,
- RAW_X_MIN, RAW_X_MAX, 0, 0);
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_POSITION_Y,
- RAW_Y_MIN, RAW_Y_MAX, 0, 0);
- }
- if (axes & TOUCH) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_TOUCH_MAJOR,
- RAW_TOUCH_MIN, RAW_TOUCH_MAX, 0, 0);
- if (axes & MINOR) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_TOUCH_MINOR,
- RAW_TOUCH_MIN, RAW_TOUCH_MAX, 0, 0);
- }
- }
- if (axes & TOOL) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_WIDTH_MAJOR,
- RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0);
- if (axes & MINOR) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_WIDTH_MINOR,
- RAW_TOOL_MAX, RAW_TOOL_MAX, 0, 0);
- }
- }
- if (axes & ORIENTATION) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_ORIENTATION,
- RAW_ORIENTATION_MIN, RAW_ORIENTATION_MAX, 0, 0);
- }
- if (axes & PRESSURE) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_PRESSURE,
- RAW_PRESSURE_MIN, RAW_PRESSURE_MAX, 0, 0);
- }
- if (axes & DISTANCE) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_DISTANCE,
- RAW_DISTANCE_MIN, RAW_DISTANCE_MAX, 0, 0);
- }
- if (axes & ID) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_TRACKING_ID,
- RAW_ID_MIN, RAW_ID_MAX, 0, 0);
- }
- if (axes & SLOT) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_SLOT,
- RAW_SLOT_MIN, RAW_SLOT_MAX, 0, 0);
- mFakeEventHub->setAbsoluteAxisValue(DEVICE_ID, ABS_MT_SLOT, 0);
- }
- if (axes & TOOL_TYPE) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_TOOL_TYPE,
- 0, MT_TOOL_MAX, 0, 0);
- }
-}
-
-void MultiTouchInputMapperTest::processPosition(
- MultiTouchInputMapper* mapper, int32_t x, int32_t y) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_POSITION_X, x);
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_POSITION_Y, y);
-}
-
-void MultiTouchInputMapperTest::processTouchMajor(
- MultiTouchInputMapper* mapper, int32_t touchMajor) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOUCH_MAJOR, touchMajor);
-}
-
-void MultiTouchInputMapperTest::processTouchMinor(
- MultiTouchInputMapper* mapper, int32_t touchMinor) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOUCH_MINOR, touchMinor);
-}
-
-void MultiTouchInputMapperTest::processToolMajor(
- MultiTouchInputMapper* mapper, int32_t toolMajor) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_WIDTH_MAJOR, toolMajor);
-}
-
-void MultiTouchInputMapperTest::processToolMinor(
- MultiTouchInputMapper* mapper, int32_t toolMinor) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_WIDTH_MINOR, toolMinor);
-}
-
-void MultiTouchInputMapperTest::processOrientation(
- MultiTouchInputMapper* mapper, int32_t orientation) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_ORIENTATION, orientation);
-}
-
-void MultiTouchInputMapperTest::processPressure(
- MultiTouchInputMapper* mapper, int32_t pressure) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_PRESSURE, pressure);
-}
-
-void MultiTouchInputMapperTest::processDistance(
- MultiTouchInputMapper* mapper, int32_t distance) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_DISTANCE, distance);
-}
-
-void MultiTouchInputMapperTest::processId(
- MultiTouchInputMapper* mapper, int32_t id) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TRACKING_ID, id);
-}
-
-void MultiTouchInputMapperTest::processSlot(
- MultiTouchInputMapper* mapper, int32_t slot) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_SLOT, slot);
-}
-
-void MultiTouchInputMapperTest::processToolType(
- MultiTouchInputMapper* mapper, int32_t toolType) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOOL_TYPE, toolType);
-}
-
-void MultiTouchInputMapperTest::processKey(
- MultiTouchInputMapper* mapper, int32_t code, int32_t value) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, code, value);
-}
-
-void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper* mapper) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_MT_REPORT, 0);
-}
-
-void MultiTouchInputMapperTest::processSync(MultiTouchInputMapper* mapper) {
- process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
-}
-
-
-TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackingIds) {
- MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareAxes(POSITION);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
- NotifyMotionArgs motionArgs;
-
- // Two fingers down at once.
- int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
- processPosition(mapper, x1, y1);
- processMTSync(mapper);
- processPosition(mapper, x2, y2);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Move.
- x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
- processPosition(mapper, x1, y1);
- processMTSync(mapper);
- processPosition(mapper, x2, y2);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // First finger up.
- x2 += 15; y2 -= 20;
- processPosition(mapper, x2, y2);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Move.
- x2 += 20; y2 -= 25;
- processPosition(mapper, x2, y2);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // New finger down.
- int32_t x3 = 700, y3 = 300;
- processPosition(mapper, x2, y2);
- processMTSync(mapper);
- processPosition(mapper, x3, y3);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Second finger up.
- x3 += 30; y3 -= 20;
- processPosition(mapper, x3, y3);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Last finger up.
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
- ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
- ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
- ASSERT_EQ(0, motionArgs.flags);
- ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(0, motionArgs.edgeFlags);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
- ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
- ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
-
- // Should not have sent any more keys or motions.
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingIds) {
- MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareAxes(POSITION | ID);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
- NotifyMotionArgs motionArgs;
-
- // Two fingers down at once.
- int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
- processPosition(mapper, x1, y1);
- processId(mapper, 1);
- processMTSync(mapper);
- processPosition(mapper, x2, y2);
- processId(mapper, 2);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- motionArgs.action);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
-
- // Move.
- x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
- processPosition(mapper, x1, y1);
- processId(mapper, 1);
- processMTSync(mapper);
- processPosition(mapper, x2, y2);
- processId(mapper, 2);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
-
- // First finger up.
- x2 += 15; y2 -= 20;
- processPosition(mapper, x2, y2);
- processId(mapper, 2);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- motionArgs.action);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
-
- // Move.
- x2 += 20; y2 -= 25;
- processPosition(mapper, x2, y2);
- processId(mapper, 2);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
-
- // New finger down.
- int32_t x3 = 700, y3 = 300;
- processPosition(mapper, x2, y2);
- processId(mapper, 2);
- processMTSync(mapper);
- processPosition(mapper, x3, y3);
- processId(mapper, 3);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- motionArgs.action);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
-
- // Second finger up.
- x3 += 30; y3 -= 20;
- processPosition(mapper, x3, y3);
- processId(mapper, 3);
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- motionArgs.action);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
-
- // Last finger up.
- processMTSync(mapper);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
-
- // Should not have sent any more keys or motions.
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithSlots) {
- MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareAxes(POSITION | ID | SLOT);
- prepareVirtualKeys();
- addMapperAndConfigure(mapper);
-
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
-
- NotifyMotionArgs motionArgs;
-
- // Two fingers down at once.
- int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
- processPosition(mapper, x1, y1);
- processId(mapper, 1);
- processSlot(mapper, 1);
- processPosition(mapper, x2, y2);
- processId(mapper, 2);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- motionArgs.action);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
-
- // Move.
- x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
- processSlot(mapper, 0);
- processPosition(mapper, x1, y1);
- processSlot(mapper, 1);
- processPosition(mapper, x2, y2);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
-
- // First finger up.
- x2 += 15; y2 -= 20;
- processSlot(mapper, 0);
- processId(mapper, -1);
- processSlot(mapper, 1);
- processPosition(mapper, x2, y2);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- motionArgs.action);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
-
- // Move.
- x2 += 20; y2 -= 25;
- processPosition(mapper, x2, y2);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(1, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
-
- // New finger down.
- int32_t x3 = 700, y3 = 300;
- processPosition(mapper, x2, y2);
- processSlot(mapper, 0);
- processId(mapper, 3);
- processPosition(mapper, x3, y3);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- motionArgs.action);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
-
- // Second finger up.
- x3 += 30; y3 -= 20;
- processSlot(mapper, 1);
- processId(mapper, -1);
- processSlot(mapper, 0);
- processPosition(mapper, x3, y3);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- motionArgs.action);
- ASSERT_EQ(size_t(2), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_EQ(1, motionArgs.pointerProperties[1].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[1].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
- toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
-
- // Last finger up.
- processId(mapper, -1);
- processSync(mapper);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
- ASSERT_EQ(size_t(1), motionArgs.pointerCount);
- ASSERT_EQ(0, motionArgs.pointerProperties[0].id);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0, 0));
-
- // Should not have sent any more keys or motions.
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasNotCalled());
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_AllAxes_WithDefaultCalibration) {
- MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareAxes(POSITION | TOUCH | TOOL | PRESSURE | ORIENTATION | ID | MINOR | DISTANCE);
- addMapperAndConfigure(mapper);
-
- // These calculations are based on the input device calibration documentation.
- int32_t rawX = 100;
- int32_t rawY = 200;
- int32_t rawTouchMajor = 7;
- int32_t rawTouchMinor = 6;
- int32_t rawToolMajor = 9;
- int32_t rawToolMinor = 8;
- int32_t rawPressure = 11;
- int32_t rawDistance = 0;
- int32_t rawOrientation = 3;
- int32_t id = 5;
-
- float x = toDisplayX(rawX);
- float y = toDisplayY(rawY);
- float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
- float size = avg(rawTouchMajor, rawTouchMinor) / RAW_TOUCH_MAX;
- float toolMajor = float(rawToolMajor) * GEOMETRIC_SCALE;
- float toolMinor = float(rawToolMinor) * GEOMETRIC_SCALE;
- float touchMajor = float(rawTouchMajor) * GEOMETRIC_SCALE;
- float touchMinor = float(rawTouchMinor) * GEOMETRIC_SCALE;
- float orientation = float(rawOrientation) / RAW_ORIENTATION_MAX * M_PI_2;
- float distance = float(rawDistance);
-
- processPosition(mapper, rawX, rawY);
- processTouchMajor(mapper, rawTouchMajor);
- processTouchMinor(mapper, rawTouchMinor);
- processToolMajor(mapper, rawToolMajor);
- processToolMinor(mapper, rawToolMinor);
- processPressure(mapper, rawPressure);
- processOrientation(mapper, rawOrientation);
- processDistance(mapper, rawDistance);
- processId(mapper, id);
- processMTSync(mapper);
- processSync(mapper);
-
- NotifyMotionArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(0, args.pointerProperties[0].id);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor,
- orientation, distance));
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_GeometricCalibration) {
- MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareAxes(POSITION | TOUCH | TOOL | MINOR);
- addConfigurationProperty("touch.size.calibration", "geometric");
- addMapperAndConfigure(mapper);
-
- // These calculations are based on the input device calibration documentation.
- int32_t rawX = 100;
- int32_t rawY = 200;
- int32_t rawTouchMajor = 140;
- int32_t rawTouchMinor = 120;
- int32_t rawToolMajor = 180;
- int32_t rawToolMinor = 160;
-
- float x = toDisplayX(rawX);
- float y = toDisplayY(rawY);
- float size = avg(rawTouchMajor, rawTouchMinor) / RAW_TOUCH_MAX;
- float toolMajor = float(rawToolMajor) * GEOMETRIC_SCALE;
- float toolMinor = float(rawToolMinor) * GEOMETRIC_SCALE;
- float touchMajor = float(rawTouchMajor) * GEOMETRIC_SCALE;
- float touchMinor = float(rawTouchMinor) * GEOMETRIC_SCALE;
-
- processPosition(mapper, rawX, rawY);
- processTouchMajor(mapper, rawTouchMajor);
- processTouchMinor(mapper, rawTouchMinor);
- processToolMajor(mapper, rawToolMajor);
- processToolMinor(mapper, rawToolMinor);
- processMTSync(mapper);
- processSync(mapper);
-
- NotifyMotionArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- x, y, 1.0f, size, touchMajor, touchMinor, toolMajor, toolMinor, 0, 0));
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_SummedLinearCalibration) {
- MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareAxes(POSITION | TOUCH | TOOL);
- addConfigurationProperty("touch.size.calibration", "diameter");
- addConfigurationProperty("touch.size.scale", "10");
- addConfigurationProperty("touch.size.bias", "160");
- addConfigurationProperty("touch.size.isSummed", "1");
- addMapperAndConfigure(mapper);
-
- // These calculations are based on the input device calibration documentation.
- // Note: We only provide a single common touch/tool value because the device is assumed
- // not to emit separate values for each pointer (isSummed = 1).
- int32_t rawX = 100;
- int32_t rawY = 200;
- int32_t rawX2 = 150;
- int32_t rawY2 = 250;
- int32_t rawTouchMajor = 5;
- int32_t rawToolMajor = 8;
-
- float x = toDisplayX(rawX);
- float y = toDisplayY(rawY);
- float x2 = toDisplayX(rawX2);
- float y2 = toDisplayY(rawY2);
- float size = float(rawTouchMajor) / 2 / RAW_TOUCH_MAX;
- float touch = float(rawTouchMajor) / 2 * 10.0f + 160.0f;
- float tool = float(rawToolMajor) / 2 * 10.0f + 160.0f;
-
- processPosition(mapper, rawX, rawY);
- processTouchMajor(mapper, rawTouchMajor);
- processToolMajor(mapper, rawToolMajor);
- processMTSync(mapper);
- processPosition(mapper, rawX2, rawY2);
- processTouchMajor(mapper, rawTouchMajor);
- processToolMajor(mapper, rawToolMajor);
- processMTSync(mapper);
- processSync(mapper);
-
- NotifyMotionArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
- args.action);
- ASSERT_EQ(size_t(2), args.pointerCount);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- x, y, 1.0f, size, touch, touch, tool, tool, 0, 0));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[1],
- x2, y2, 1.0f, size, touch, touch, tool, tool, 0, 0));
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_AreaCalibration) {
- MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareAxes(POSITION | TOUCH | TOOL);
- addConfigurationProperty("touch.size.calibration", "area");
- addConfigurationProperty("touch.size.scale", "43");
- addConfigurationProperty("touch.size.bias", "3");
- addMapperAndConfigure(mapper);
-
- // These calculations are based on the input device calibration documentation.
- int32_t rawX = 100;
- int32_t rawY = 200;
- int32_t rawTouchMajor = 5;
- int32_t rawToolMajor = 8;
-
- float x = toDisplayX(rawX);
- float y = toDisplayY(rawY);
- float size = float(rawTouchMajor) / RAW_TOUCH_MAX;
- float touch = sqrtf(rawTouchMajor) * 43.0f + 3.0f;
- float tool = sqrtf(rawToolMajor) * 43.0f + 3.0f;
-
- processPosition(mapper, rawX, rawY);
- processTouchMajor(mapper, rawTouchMajor);
- processToolMajor(mapper, rawToolMajor);
- processMTSync(mapper);
- processSync(mapper);
-
- NotifyMotionArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- x, y, 1.0f, size, touch, touch, tool, tool, 0, 0));
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_PressureAxis_AmplitudeCalibration) {
- MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareAxes(POSITION | PRESSURE);
- addConfigurationProperty("touch.pressure.calibration", "amplitude");
- addConfigurationProperty("touch.pressure.scale", "0.01");
- addMapperAndConfigure(mapper);
-
- // These calculations are based on the input device calibration documentation.
- int32_t rawX = 100;
- int32_t rawY = 200;
- int32_t rawPressure = 60;
-
- float x = toDisplayX(rawX);
- float y = toDisplayY(rawY);
- float pressure = float(rawPressure) * 0.01f;
-
- processPosition(mapper, rawX, rawY);
- processPressure(mapper, rawPressure);
- processMTSync(mapper);
- processSync(mapper);
-
- NotifyMotionArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- x, y, pressure, 0, 0, 0, 0, 0, 0, 0));
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllButtons) {
- MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareAxes(POSITION | ID | SLOT);
- addMapperAndConfigure(mapper);
-
- NotifyMotionArgs motionArgs;
- NotifyKeyArgs keyArgs;
-
- processId(mapper, 1);
- processPosition(mapper, 100, 200);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
- ASSERT_EQ(0, motionArgs.buttonState);
-
- // press BTN_LEFT, release BTN_LEFT
- processKey(mapper, BTN_LEFT, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_BUTTON_PRIMARY, motionArgs.buttonState);
-
- processKey(mapper, BTN_LEFT, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-
- // press BTN_RIGHT + BTN_MIDDLE, release BTN_RIGHT, release BTN_MIDDLE
- processKey(mapper, BTN_RIGHT, 1);
- processKey(mapper, BTN_MIDDLE, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY | AMOTION_EVENT_BUTTON_TERTIARY,
- motionArgs.buttonState);
-
- processKey(mapper, BTN_RIGHT, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-
- processKey(mapper, BTN_MIDDLE, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-
- // press BTN_BACK, release BTN_BACK
- processKey(mapper, BTN_BACK, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
- ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-
- processKey(mapper, BTN_BACK, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
- ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
-
- // press BTN_SIDE, release BTN_SIDE
- processKey(mapper, BTN_SIDE, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
- ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_BUTTON_BACK, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-
- processKey(mapper, BTN_SIDE, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
- ASSERT_EQ(AKEYCODE_BACK, keyArgs.keyCode);
-
- // press BTN_FORWARD, release BTN_FORWARD
- processKey(mapper, BTN_FORWARD, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
- ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-
- processKey(mapper, BTN_FORWARD, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
- ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
-
- // press BTN_EXTRA, release BTN_EXTRA
- processKey(mapper, BTN_EXTRA, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
- ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_BUTTON_FORWARD, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-
- processKey(mapper, BTN_EXTRA, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&keyArgs));
- ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
- ASSERT_EQ(AKEYCODE_FORWARD, keyArgs.keyCode);
-
- // press BTN_STYLUS, release BTN_STYLUS
- processKey(mapper, BTN_STYLUS, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_BUTTON_SECONDARY, motionArgs.buttonState);
-
- processKey(mapper, BTN_STYLUS, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-
- // press BTN_STYLUS2, release BTN_STYLUS2
- processKey(mapper, BTN_STYLUS2, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_BUTTON_TERTIARY, motionArgs.buttonState);
-
- processKey(mapper, BTN_STYLUS2, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(0, motionArgs.buttonState);
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
-
- // release touch
- processId(mapper, -1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
- ASSERT_EQ(0, motionArgs.buttonState);
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleAllToolTypes) {
- MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
- addMapperAndConfigure(mapper);
-
- NotifyMotionArgs motionArgs;
-
- // default tool type is finger
- processId(mapper, 1);
- processPosition(mapper, 100, 200);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
-
- // eraser
- processKey(mapper, BTN_TOOL_RUBBER, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_ERASER, motionArgs.pointerProperties[0].toolType);
-
- // stylus
- processKey(mapper, BTN_TOOL_RUBBER, 0);
- processKey(mapper, BTN_TOOL_PEN, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType);
-
- // brush
- processKey(mapper, BTN_TOOL_PEN, 0);
- processKey(mapper, BTN_TOOL_BRUSH, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType);
-
- // pencil
- processKey(mapper, BTN_TOOL_BRUSH, 0);
- processKey(mapper, BTN_TOOL_PENCIL, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType);
-
- // airbrush
- processKey(mapper, BTN_TOOL_PENCIL, 0);
- processKey(mapper, BTN_TOOL_AIRBRUSH, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType);
-
- // mouse
- processKey(mapper, BTN_TOOL_AIRBRUSH, 0);
- processKey(mapper, BTN_TOOL_MOUSE, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_MOUSE, motionArgs.pointerProperties[0].toolType);
-
- // lens
- processKey(mapper, BTN_TOOL_MOUSE, 0);
- processKey(mapper, BTN_TOOL_LENS, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_MOUSE, motionArgs.pointerProperties[0].toolType);
-
- // double-tap
- processKey(mapper, BTN_TOOL_LENS, 0);
- processKey(mapper, BTN_TOOL_DOUBLETAP, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
-
- // triple-tap
- processKey(mapper, BTN_TOOL_DOUBLETAP, 0);
- processKey(mapper, BTN_TOOL_TRIPLETAP, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
-
- // quad-tap
- processKey(mapper, BTN_TOOL_TRIPLETAP, 0);
- processKey(mapper, BTN_TOOL_QUADTAP, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
-
- // finger
- processKey(mapper, BTN_TOOL_QUADTAP, 0);
- processKey(mapper, BTN_TOOL_FINGER, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
-
- // stylus trumps finger
- processKey(mapper, BTN_TOOL_PEN, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType);
-
- // eraser trumps stylus
- processKey(mapper, BTN_TOOL_RUBBER, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_ERASER, motionArgs.pointerProperties[0].toolType);
-
- // mouse trumps eraser
- processKey(mapper, BTN_TOOL_MOUSE, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_MOUSE, motionArgs.pointerProperties[0].toolType);
-
- // MT tool type trumps BTN tool types: MT_TOOL_FINGER
- processToolType(mapper, MT_TOOL_FINGER); // this is the first time we send MT_TOOL_TYPE
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
-
- // MT tool type trumps BTN tool types: MT_TOOL_PEN
- processToolType(mapper, MT_TOOL_PEN);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_STYLUS, motionArgs.pointerProperties[0].toolType);
-
- // back to default tool type
- processToolType(mapper, -1); // use a deliberately undefined tool type, for testing
- processKey(mapper, BTN_TOOL_MOUSE, 0);
- processKey(mapper, BTN_TOOL_RUBBER, 0);
- processKey(mapper, BTN_TOOL_PEN, 0);
- processKey(mapper, BTN_TOOL_FINGER, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
- ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_WhenBtnTouchPresent_HoversIfItsValueIsZero) {
- MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareAxes(POSITION | ID | SLOT);
- mFakeEventHub->addKey(DEVICE_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
- addMapperAndConfigure(mapper);
-
- NotifyMotionArgs motionArgs;
-
- // initially hovering because BTN_TOUCH not sent yet, pressure defaults to 0
- processId(mapper, 1);
- processPosition(mapper, 100, 200);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
-
- // move a little
- processPosition(mapper, 150, 250);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-
- // down when BTN_TOUCH is pressed, pressure defaults to 1
- processKey(mapper, BTN_TOUCH, 1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
-
- // up when BTN_TOUCH is released, hover restored
- processKey(mapper, BTN_TOUCH, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-
- // exit hover when pointer goes away
- processId(mapper, -1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-}
-
-TEST_F(MultiTouchInputMapperTest, Process_WhenAbsMTPressureIsPresent_HoversIfItsValueIsZero) {
- MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareAxes(POSITION | ID | SLOT | PRESSURE);
- addMapperAndConfigure(mapper);
-
- NotifyMotionArgs motionArgs;
-
- // initially hovering because pressure is 0
- processId(mapper, 1);
- processPosition(mapper, 100, 200);
- processPressure(mapper, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(100), toDisplayY(200), 0, 0, 0, 0, 0, 0, 0, 0));
-
- // move a little
- processPosition(mapper, 150, 250);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-
- // down when pressure becomes non-zero
- processPressure(mapper, RAW_PRESSURE_MAX);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
-
- // up when pressure becomes 0, hover restored
- processPressure(mapper, 0);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 1, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_ENTER, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-
- // exit hover when pointer goes away
- processId(mapper, -1);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_EXIT, motionArgs.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
- toDisplayX(150), toDisplayY(250), 0, 0, 0, 0, 0, 0, 0, 0));
-}
-
-
-} // namespace android
diff --git a/media/jni/android_media_MediaMuxer.cpp b/media/jni/android_media_MediaMuxer.cpp
index ea890c2..3fef446f 100644
--- a/media/jni/android_media_MediaMuxer.cpp
+++ b/media/jni/android_media_MediaMuxer.cpp
@@ -132,7 +132,7 @@
}
// Constructor counterpart.
-static jint android_media_MediaMuxer_native_setup(
+static jlong android_media_MediaMuxer_native_setup(
JNIEnv *env, jclass clazz, jobject fileDescriptor,
jint format) {
int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
@@ -142,7 +142,7 @@
static_cast<MediaMuxer::OutputFormat>(format);
sp<MediaMuxer> muxer = new MediaMuxer(fd, fileFormat);
muxer->incStrong(clazz);
- return int(muxer.get());
+ return reinterpret_cast<jlong>(muxer.get());
}
static void android_media_MediaMuxer_setOrientationHint(
diff --git a/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java b/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java
index c2f4400..1902a40 100644
--- a/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java
@@ -19,13 +19,13 @@
import javax.microedition.khronos.egl.*;
public class EGLConfigImpl extends EGLConfig {
- private int mEGLConfig;
+ private long mEGLConfig;
- EGLConfigImpl(int config) {
+ EGLConfigImpl(long config) {
mEGLConfig = config;
}
- int get() {
+ long get() {
return mEGLConfig;
}
}
diff --git a/opengl/java/com/google/android/gles_jni/EGLContextImpl.java b/opengl/java/com/google/android/gles_jni/EGLContextImpl.java
index cd36099..47369ac 100644
--- a/opengl/java/com/google/android/gles_jni/EGLContextImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLContextImpl.java
@@ -21,13 +21,13 @@
public class EGLContextImpl extends EGLContext {
private GLImpl mGLContext;
- int mEGLContext;
-
- public EGLContextImpl(int ctx) {
+ long mEGLContext;
+
+ public EGLContextImpl(long ctx) {
mEGLContext = ctx;
mGLContext = new GLImpl();
}
-
+
@Override
public GL getGL() {
return mGLContext;
@@ -45,6 +45,12 @@
@Override
public int hashCode() {
- return mEGLContext;
+ /*
+ * Based on the algorithm suggested in
+ * http://developer.android.com/reference/java/lang/Object.html
+ */
+ int result = 17;
+ result = 31 * result + (int) (mEGLContext ^ (mEGLContext >>> 32));
+ return result;
}
}
diff --git a/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java b/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java
index e6c9817..9b932fc 100644
--- a/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java
@@ -19,9 +19,9 @@
import javax.microedition.khronos.egl.*;
public class EGLDisplayImpl extends EGLDisplay {
- int mEGLDisplay;
+ long mEGLDisplay;
- public EGLDisplayImpl(int dpy) {
+ public EGLDisplayImpl(long dpy) {
mEGLDisplay = dpy;
}
@@ -38,6 +38,12 @@
@Override
public int hashCode() {
- return mEGLDisplay;
+ /*
+ * Based on the algorithm suggested in
+ * http://developer.android.com/reference/java/lang/Object.html
+ */
+ int result = 17;
+ result = 31 * result + (int) (mEGLDisplay ^ (mEGLDisplay >>> 32));
+ return result;
}
}
diff --git a/opengl/java/com/google/android/gles_jni/EGLImpl.java b/opengl/java/com/google/android/gles_jni/EGLImpl.java
index 64a54c2..41fb072 100644
--- a/opengl/java/com/google/android/gles_jni/EGLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLImpl.java
@@ -51,7 +51,7 @@
public static native int getInitCount(EGLDisplay display);
public EGLContext eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, int[] attrib_list) {
- int eglContextId = _eglCreateContext(display, config, share_context, attrib_list);
+ long eglContextId = _eglCreateContext(display, config, share_context, attrib_list);
if (eglContextId == 0) {
return EGL10.EGL_NO_CONTEXT;
}
@@ -59,7 +59,7 @@
}
public EGLSurface eglCreatePbufferSurface(EGLDisplay display, EGLConfig config, int[] attrib_list) {
- int eglSurfaceId = _eglCreatePbufferSurface(display, config, attrib_list);
+ long eglSurfaceId = _eglCreatePbufferSurface(display, config, attrib_list);
if (eglSurfaceId == 0) {
return EGL10.EGL_NO_SURFACE;
}
@@ -87,7 +87,7 @@
sur = (Surface) native_window;
}
- int eglSurfaceId;
+ long eglSurfaceId;
if (sur != null) {
eglSurfaceId = _eglCreateWindowSurface(display, config, sur, attrib_list);
} else if (native_window instanceof SurfaceTexture) {
@@ -106,7 +106,7 @@
}
public synchronized EGLDisplay eglGetDisplay(Object native_display) {
- int value = _eglGetDisplay(native_display);
+ long value = _eglGetDisplay(native_display);
if (value == 0) {
return EGL10.EGL_NO_DISPLAY;
}
@@ -116,7 +116,7 @@
}
public synchronized EGLContext eglGetCurrentContext() {
- int value = _eglGetCurrentContext();
+ long value = _eglGetCurrentContext();
if (value == 0) {
return EGL10.EGL_NO_CONTEXT;
}
@@ -126,7 +126,7 @@
}
public synchronized EGLDisplay eglGetCurrentDisplay() {
- int value = _eglGetCurrentDisplay();
+ long value = _eglGetCurrentDisplay();
if (value == 0) {
return EGL10.EGL_NO_DISPLAY;
}
@@ -136,7 +136,7 @@
}
public synchronized EGLSurface eglGetCurrentSurface(int readdraw) {
- int value = _eglGetCurrentSurface(readdraw);
+ long value = _eglGetCurrentSurface(readdraw);
if (value == 0) {
return EGL10.EGL_NO_SURFACE;
}
@@ -145,15 +145,15 @@
return mSurface;
}
- private native int _eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, int[] attrib_list);
- private native int _eglCreatePbufferSurface(EGLDisplay display, EGLConfig config, int[] attrib_list);
+ private native long _eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, int[] attrib_list);
+ private native long _eglCreatePbufferSurface(EGLDisplay display, EGLConfig config, int[] attrib_list);
private native void _eglCreatePixmapSurface(EGLSurface sur, EGLDisplay display, EGLConfig config, Object native_pixmap, int[] attrib_list);
- private native int _eglCreateWindowSurface(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list);
- private native int _eglCreateWindowSurfaceTexture(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list);
- private native int _eglGetDisplay(Object native_display);
- private native int _eglGetCurrentContext();
- private native int _eglGetCurrentDisplay();
- private native int _eglGetCurrentSurface(int readdraw);
+ private native long _eglCreateWindowSurface(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list);
+ private native long _eglCreateWindowSurfaceTexture(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list);
+ private native long _eglGetDisplay(Object native_display);
+ private native long _eglGetCurrentContext();
+ private native long _eglGetCurrentDisplay();
+ private native long _eglGetCurrentSurface(int readdraw);
native private static void _nativeClassInit();
static { _nativeClassInit(); }
diff --git a/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java b/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java
index e7f15dc..7a3ed24 100644
--- a/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java
@@ -19,13 +19,13 @@
import javax.microedition.khronos.egl.*;
public class EGLSurfaceImpl extends EGLSurface {
- int mEGLSurface;
- private int mNativePixelRef;
+ long mEGLSurface;
+ private long mNativePixelRef;
public EGLSurfaceImpl() {
mEGLSurface = 0;
mNativePixelRef = 0;
}
- public EGLSurfaceImpl(int surface) {
+ public EGLSurfaceImpl(long surface) {
mEGLSurface = surface;
mNativePixelRef = 0;
}
@@ -43,6 +43,12 @@
@Override
public int hashCode() {
- return mEGLSurface;
+ /*
+ * Based on the algorithm suggested in
+ * http://developer.android.com/reference/java/lang/Object.html
+ */
+ int result = 17;
+ result = 31 * result + (int) (mEGLSurface ^ (mEGLSurface >>> 32));
+ return result;
}
}
diff --git a/policy/src/com/android/internal/policy/impl/PolicyControl.java b/policy/src/com/android/internal/policy/impl/PolicyControl.java
index e6a7d76..4f355dd 100644
--- a/policy/src/com/android/internal/policy/impl/PolicyControl.java
+++ b/policy/src/com/android/internal/policy/impl/PolicyControl.java
@@ -140,30 +140,32 @@
sImmersiveStatusFilter = null;
sImmersiveNavigationFilter = null;
sImmersivePreconfirmationsFilter = null;
- String[] nvps = value.split(":");
- for (String nvp : nvps) {
- int i = nvp.indexOf('=');
- if (i == -1) continue;
- String n = nvp.substring(0, i);
- String v = nvp.substring(i + 1);
- if (n.equals(NAME_IMMERSIVE_FULL)) {
- Filter f = Filter.parse(v);
- sImmersiveStatusFilter = sImmersiveNavigationFilter = f;
- if (sImmersivePreconfirmationsFilter == null) {
+ if (value != null) {
+ String[] nvps = value.split(":");
+ for (String nvp : nvps) {
+ int i = nvp.indexOf('=');
+ if (i == -1) continue;
+ String n = nvp.substring(0, i);
+ String v = nvp.substring(i + 1);
+ if (n.equals(NAME_IMMERSIVE_FULL)) {
+ Filter f = Filter.parse(v);
+ sImmersiveStatusFilter = sImmersiveNavigationFilter = f;
+ if (sImmersivePreconfirmationsFilter == null) {
+ sImmersivePreconfirmationsFilter = f;
+ }
+ } else if (n.equals(NAME_IMMERSIVE_STATUS)) {
+ Filter f = Filter.parse(v);
+ sImmersiveStatusFilter = f;
+ } else if (n.equals(NAME_IMMERSIVE_NAVIGATION)) {
+ Filter f = Filter.parse(v);
+ sImmersiveNavigationFilter = f;
+ if (sImmersivePreconfirmationsFilter == null) {
+ sImmersivePreconfirmationsFilter = f;
+ }
+ } else if (n.equals(NAME_IMMERSIVE_PRECONFIRMATIONS)) {
+ Filter f = Filter.parse(v);
sImmersivePreconfirmationsFilter = f;
}
- } else if (n.equals(NAME_IMMERSIVE_STATUS)) {
- Filter f = Filter.parse(v);
- sImmersiveStatusFilter = f;
- } else if (n.equals(NAME_IMMERSIVE_NAVIGATION)) {
- Filter f = Filter.parse(v);
- sImmersiveNavigationFilter = f;
- if (sImmersivePreconfirmationsFilter == null) {
- sImmersivePreconfirmationsFilter = f;
- }
- } else if (n.equals(NAME_IMMERSIVE_PRECONFIRMATIONS)) {
- Filter f = Filter.parse(v);
- sImmersivePreconfirmationsFilter = f;
}
}
if (DEBUG) {
diff --git a/rs/java/android/renderscript/BaseObj.java b/rs/java/android/renderscript/BaseObj.java
index eee4936..842aa23 100644
--- a/rs/java/android/renderscript/BaseObj.java
+++ b/rs/java/android/renderscript/BaseObj.java
@@ -32,7 +32,7 @@
mDestroyed = false;
}
- void setID(int id) {
+ void setID(long id) {
if (mID != 0) {
throw new RSRuntimeException("Internal Error, reset of object ID.");
}
diff --git a/rs/java/android/renderscript/FileA3D.java b/rs/java/android/renderscript/FileA3D.java
index f0acb56..4164810 100644
--- a/rs/java/android/renderscript/FileA3D.java
+++ b/rs/java/android/renderscript/FileA3D.java
@@ -136,7 +136,7 @@
return null;
}
- int objectID = rs.nFileA3DGetEntryByIndex(entry.mID, entry.mIndex);
+ long objectID = rs.nFileA3DGetEntryByIndex(entry.mID, entry.mIndex);
if(objectID == 0) {
return null;
}
@@ -292,7 +292,7 @@
long fileId = 0;
if (is instanceof AssetManager.AssetInputStream) {
- int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
+ long asset = ((AssetManager.AssetInputStream) is).getNativeAsset();
fileId = rs.nFileA3DCreateFromAssetStream(asset);
} else {
throw new RSRuntimeException("Unsupported asset stream");
diff --git a/rs/java/android/renderscript/Font.java b/rs/java/android/renderscript/Font.java
index 4cd89db..b22aeb7 100644
--- a/rs/java/android/renderscript/Font.java
+++ b/rs/java/android/renderscript/Font.java
@@ -148,7 +148,7 @@
return "DroidSans.ttf";
}
- Font(int id, RenderScript rs) {
+ Font(long id, RenderScript rs) {
super(id, rs);
}
@@ -159,7 +159,7 @@
static public Font createFromFile(RenderScript rs, Resources res, String path, float pointSize) {
rs.validate();
int dpi = res.getDisplayMetrics().densityDpi;
- int fontId = rs.nFontCreateFromFile(path, pointSize, dpi);
+ long fontId = rs.nFontCreateFromFile(path, pointSize, dpi);
if(fontId == 0) {
throw new RSRuntimeException("Unable to create font from file " + path);
@@ -184,7 +184,7 @@
AssetManager mgr = res.getAssets();
int dpi = res.getDisplayMetrics().densityDpi;
- int fontId = rs.nFontCreateFromAsset(mgr, path, pointSize, dpi);
+ long fontId = rs.nFontCreateFromAsset(mgr, path, pointSize, dpi);
if(fontId == 0) {
throw new RSRuntimeException("Unable to create font from asset " + path);
}
@@ -208,9 +208,9 @@
int dpi = res.getDisplayMetrics().densityDpi;
- int fontId = 0;
+ long fontId = 0;
if (is instanceof AssetManager.AssetInputStream) {
- int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
+ long asset = ((AssetManager.AssetInputStream) is).getNativeAsset();
fontId = rs.nFontCreateFromAssetStream(name, pointSize, dpi, asset);
} else {
throw new RSRuntimeException("Unsupported asset stream created");
diff --git a/rs/java/android/renderscript/ProgramStore.java b/rs/java/android/renderscript/ProgramStore.java
index 730c51b..c0fa9c4 100644
--- a/rs/java/android/renderscript/ProgramStore.java
+++ b/rs/java/android/renderscript/ProgramStore.java
@@ -143,7 +143,7 @@
BlendDstFunc mBlendDst;
boolean mDither;
- ProgramStore(int id, RenderScript rs) {
+ ProgramStore(long id, RenderScript rs) {
super(id, rs);
}
@@ -418,7 +418,7 @@
*/
public ProgramStore create() {
mRS.validate();
- int id = mRS.nProgramStoreCreate(mColorMaskR, mColorMaskG, mColorMaskB, mColorMaskA,
+ long id = mRS.nProgramStoreCreate(mColorMaskR, mColorMaskG, mColorMaskB, mColorMaskA,
mDepthMask, mDither,
mBlendSrc.mID, mBlendDst.mID, mDepthFunc.mID);
ProgramStore programStore = new ProgramStore(id, mRS);
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index b0ef156..a4a9070 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -502,8 +502,8 @@
rsnAllocationResize1D(mContext, id, dimX);
}
- native long rsnFileA3DCreateFromAssetStream(long con, int assetStream);
- synchronized long nFileA3DCreateFromAssetStream(int assetStream) {
+ native long rsnFileA3DCreateFromAssetStream(long con, long assetStream);
+ synchronized long nFileA3DCreateFromAssetStream(long assetStream) {
validate();
return rsnFileA3DCreateFromAssetStream(mContext, assetStream);
}
@@ -527,24 +527,24 @@
validate();
rsnFileA3DGetIndexEntries(mContext, fileA3D, numEntries, IDs, names);
}
- native int rsnFileA3DGetEntryByIndex(long con, long fileA3D, int index);
- synchronized int nFileA3DGetEntryByIndex(long fileA3D, int index) {
+ native long rsnFileA3DGetEntryByIndex(long con, long fileA3D, int index);
+ synchronized long nFileA3DGetEntryByIndex(long fileA3D, int index) {
validate();
return rsnFileA3DGetEntryByIndex(mContext, fileA3D, index);
}
- native int rsnFontCreateFromFile(long con, String fileName, float size, int dpi);
- synchronized int nFontCreateFromFile(String fileName, float size, int dpi) {
+ native long rsnFontCreateFromFile(long con, String fileName, float size, int dpi);
+ synchronized long nFontCreateFromFile(String fileName, float size, int dpi) {
validate();
return rsnFontCreateFromFile(mContext, fileName, size, dpi);
}
- native int rsnFontCreateFromAssetStream(long con, String name, float size, int dpi, int assetStream);
- synchronized int nFontCreateFromAssetStream(String name, float size, int dpi, int assetStream) {
+ native long rsnFontCreateFromAssetStream(long con, String name, float size, int dpi, long assetStream);
+ synchronized long nFontCreateFromAssetStream(String name, float size, int dpi, long assetStream) {
validate();
return rsnFontCreateFromAssetStream(mContext, name, size, dpi, assetStream);
}
- native int rsnFontCreateFromAsset(long con, AssetManager mgr, String path, float size, int dpi);
- synchronized int nFontCreateFromAsset(AssetManager mgr, String path, float size, int dpi) {
+ native long rsnFontCreateFromAsset(long con, AssetManager mgr, String path, float size, int dpi);
+ synchronized long nFontCreateFromAsset(AssetManager mgr, String path, float size, int dpi) {
validate();
return rsnFontCreateFromAsset(mContext, mgr, path, size, dpi);
}
@@ -661,9 +661,9 @@
rsnScriptSetVarObj(mContext, id, slot, val);
}
- native int rsnScriptCCreate(long con, String resName, String cacheDir,
+ native long rsnScriptCCreate(long con, String resName, String cacheDir,
byte[] script, int length);
- synchronized int nScriptCCreate(String resName, String cacheDir, byte[] script, int length) {
+ synchronized long nScriptCCreate(String resName, String cacheDir, byte[] script, int length) {
validate();
return rsnScriptCCreate(mContext, resName, cacheDir, script, length);
}
@@ -710,18 +710,18 @@
rsnScriptGroupExecute(mContext, group);
}
- native int rsnSamplerCreate(long con, int magFilter, int minFilter,
+ native long rsnSamplerCreate(long con, int magFilter, int minFilter,
int wrapS, int wrapT, int wrapR, float aniso);
- synchronized int nSamplerCreate(int magFilter, int minFilter,
+ synchronized long nSamplerCreate(int magFilter, int minFilter,
int wrapS, int wrapT, int wrapR, float aniso) {
validate();
return rsnSamplerCreate(mContext, magFilter, minFilter, wrapS, wrapT, wrapR, aniso);
}
- native int rsnProgramStoreCreate(long con, boolean r, boolean g, boolean b, boolean a,
+ native long rsnProgramStoreCreate(long con, boolean r, boolean g, boolean b, boolean a,
boolean depthMask, boolean dither,
int srcMode, int dstMode, int depthFunc);
- synchronized int nProgramStoreCreate(boolean r, boolean g, boolean b, boolean a,
+ synchronized long nProgramStoreCreate(boolean r, boolean g, boolean b, boolean a,
boolean depthMask, boolean dither,
int srcMode, int dstMode, int depthFunc) {
validate();
@@ -787,8 +787,8 @@
rsnMeshGetIndices(mContext, id, idxIds, primitives, vtxIdCount);
}
- native long rsnPathCreate(long con, int prim, boolean isStatic, long vtx, int loop, float q);
- synchronized long nPathCreate(int prim, boolean isStatic, long vtx, int loop, float q) {
+ native long rsnPathCreate(long con, int prim, boolean isStatic, long vtx, long loop, float q);
+ synchronized long nPathCreate(int prim, boolean isStatic, long vtx, long loop, float q) {
validate();
return rsnPathCreate(mContext, prim, isStatic, vtx, loop, q);
}
diff --git a/rs/java/android/renderscript/Sampler.java b/rs/java/android/renderscript/Sampler.java
index 39b867b..a4edbb5 100644
--- a/rs/java/android/renderscript/Sampler.java
+++ b/rs/java/android/renderscript/Sampler.java
@@ -49,7 +49,7 @@
Value mWrapR;
float mAniso;
- Sampler(int id, RenderScript rs) {
+ Sampler(long id, RenderScript rs) {
super(id, rs);
}
@@ -336,7 +336,7 @@
public Sampler create() {
mRS.validate();
- int id = mRS.nSamplerCreate(mMag.mID, mMin.mID,
+ long id = mRS.nSamplerCreate(mMag.mID, mMin.mID,
mWrapS.mID, mWrapT.mID, mWrapR.mID, mAniso);
Sampler sampler = new Sampler(id, mRS);
sampler.mMin = mMin;
diff --git a/rs/java/android/renderscript/ScriptC.java b/rs/java/android/renderscript/ScriptC.java
index c7979f6..9e76f52 100644
--- a/rs/java/android/renderscript/ScriptC.java
+++ b/rs/java/android/renderscript/ScriptC.java
@@ -38,7 +38,17 @@
protected ScriptC(int id, RenderScript rs) {
super(id, rs);
}
-
+ /**
+ * Only intended for use by the generated derived classes.
+ *
+ * @param id
+ * @param rs
+ *
+ * @hide
+ */
+ protected ScriptC(long id, RenderScript rs) {
+ super(id, rs);
+ }
/**
* Only intended for use by the generated derived classes.
*
@@ -49,7 +59,7 @@
*/
protected ScriptC(RenderScript rs, Resources resources, int resourceID) {
super(0, rs);
- int id = internalCreate(rs, resources, resourceID);
+ long id = internalCreate(rs, resources, resourceID);
if (id == 0) {
throw new RSRuntimeException("Loading of ScriptC script failed.");
}
@@ -63,7 +73,7 @@
static String mCachePath;
- private static synchronized int internalCreate(RenderScript rs, Resources resources, int resourceID) {
+ private static synchronized long internalCreate(RenderScript rs, Resources resources, int resourceID) {
byte[] pgm;
int pgmLength;
InputStream is = resources.openRawResource(resourceID);
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 024d0c3..80a5da2 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -220,7 +220,7 @@
nDeviceCreate(JNIEnv *_env, jobject _this)
{
LOG_API("nDeviceCreate");
- return (jint)rsDeviceCreate();
+ return (jlong)rsDeviceCreate();
}
static void
@@ -241,17 +241,17 @@
nContextCreate(JNIEnv *_env, jobject _this, jlong dev, jint ver, jint sdkVer, jint ct)
{
LOG_API("nContextCreate");
- return (jint)rsContextCreate((RsDevice)dev, ver, sdkVer, (RsContextType)ct, 0);
+ return (jlong)rsContextCreate((RsDevice)dev, ver, sdkVer, (RsContextType)ct, 0);
}
static jlong
nContextCreateGL(JNIEnv *_env, jobject _this, jlong dev, jint ver, jint sdkVer,
- int colorMin, int colorPref,
- int alphaMin, int alphaPref,
- int depthMin, int depthPref,
- int stencilMin, int stencilPref,
- int samplesMin, int samplesPref, float samplesQ,
- int dpi)
+ jint colorMin, jint colorPref,
+ jint alphaMin, jint alphaPref,
+ jint depthMin, jint depthPref,
+ jint stencilMin, jint stencilPref,
+ jint samplesMin, jint samplesPref, jfloat samplesQ,
+ jint dpi)
{
RsSurfaceConfig sc;
sc.alphaMin = alphaMin;
@@ -265,7 +265,7 @@
sc.samplesQ = samplesQ;
LOG_API("nContextCreateGL");
- return (jint)rsContextCreateGL((RsDevice)dev, ver, sdkVer, sc, dpi);
+ return (jlong)rsContextCreateGL((RsDevice)dev, ver, sdkVer, sc, dpi);
}
static void
@@ -355,7 +355,7 @@
ALOGV("message receive buffer too small. %i", receiveLen);
}
_env->ReleaseIntArrayElements(data, ptr, 0);
- return id;
+ return (jint)id;
}
static jint
@@ -370,7 +370,7 @@
auxDataPtr[0] = (jint)subID;
auxDataPtr[1] = (jint)receiveLen;
_env->ReleaseIntArrayElements(auxData, auxDataPtr, 0);
- return id;
+ return (jint)id;
}
static void nContextInitToClient(JNIEnv *_env, jobject _this, jlong con)
@@ -432,7 +432,7 @@
_env->ReleaseIntArrayElements(_ids, ids, JNI_ABORT);
_env->ReleaseIntArrayElements(_arraySizes, arraySizes, JNI_ABORT);
- return (jint)id;
+ return (jlong)id;
}
static void
@@ -499,7 +499,7 @@
int elementCount = _env->GetArrayLength(_typeData);
assert(elementCount == 6);
- LOG_API("nTypeCreate, con(%p)", (RsContext)con);
+ LOG_API("nTypeGetNativeData, con(%p)", (RsContext)con);
uint32_t typeData[6];
rsaTypeGetNativeData((RsContext)con, (RsType)id, typeData, 6);
@@ -515,7 +515,7 @@
nAllocationCreateTyped(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mips, jint usage, jint pointer)
{
LOG_API("nAllocationCreateTyped, con(%p), type(%p), mip(%i), usage(%i), ptr(%p)", (RsContext)con, (RsElement)type, mips, usage, (void *)pointer);
- return (jint) rsAllocationCreateTyped((RsContext)con, (RsType)type, (RsAllocationMipmapControl)mips, (uint32_t)usage, (uint32_t)pointer);
+ return (jlong) rsAllocationCreateTyped((RsContext)con, (RsType)type, (RsAllocationMipmapControl)mips, (uint32_t)usage, (uint32_t)pointer);
}
static void
@@ -662,7 +662,7 @@
static void
nAllocationData1D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint offset, jint lod,
- jint count, jobject data, int sizeBytes, int dataType)
+ jint count, jobject data, jint sizeBytes, jint dataType)
{
RsAllocation *alloc = (RsAllocation *)_alloc;
LOG_API("nAllocation1DData, con(%p), adapter(%p), offset(%i), count(%i), sizeBytes(%i), dataType(%i)",
@@ -671,8 +671,8 @@
}
static void
-// native void rsnAllocationElementData1D(int con, int id, int xoff, int compIdx, byte[] d, int sizeBytes);
-nAllocationElementData1D(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint offset, jint lod, jint compIdx, jbyteArray data, int sizeBytes)
+// native void rsnAllocationElementData1D(long con, long id, int xoff, int compIdx, byte[] d, int sizeBytes);
+nAllocationElementData1D(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint offset, jint lod, jint compIdx, jbyteArray data, jint sizeBytes)
{
jint len = _env->GetArrayLength(data);
LOG_API("nAllocationElementData1D, con(%p), alloc(%p), offset(%i), comp(%i), len(%i), sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, offset, compIdx, len, sizeBytes);
@@ -683,7 +683,7 @@
static void
nAllocationData2D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint lod, jint _face,
- jint w, jint h, jobject data, int sizeBytes, int dataType)
+ jint w, jint h, jobject data, jint sizeBytes, jint dataType)
{
RsAllocation *alloc = (RsAllocation *)_alloc;
RsAllocationCubemapFace face = (RsAllocationCubemapFace)_face;
@@ -797,9 +797,8 @@
static jlong
nFileA3DCreateFromAssetStream(JNIEnv *_env, jobject _this, jlong con, jlong native_asset)
{
- ALOGV("______nFileA3D %u", (uint32_t) native_asset);
-
Asset* asset = reinterpret_cast<Asset*>(native_asset);
+ ALOGV("______nFileA3D %p", asset);
jlong id = (jlong)rsaFileA3DCreateFromMemory((RsContext)con, asset->getBuffer(false), asset->getLength());
return id;
@@ -837,13 +836,13 @@
{
int32_t numEntries = 0;
rsaFileA3DGetNumIndexEntries((RsContext)con, &numEntries, (RsFile)fileA3D);
- return numEntries;
+ return (jint)numEntries;
}
static void
nFileA3DGetIndexEntries(JNIEnv *_env, jobject _this, jlong con, jlong fileA3D, jint numEntries, jintArray _ids, jobjectArray _entries)
{
- ALOGV("______nFileA3D %u", (uint32_t) fileA3D);
+ ALOGV("______nFileA3D %p", (RsFile) fileA3D);
RsFileIndexEntry *fileEntries = (RsFileIndexEntry*)malloc((uint32_t)numEntries * sizeof(RsFileIndexEntry));
rsaFileA3DGetIndexEntries((RsContext)con, fileEntries, (uint32_t)numEntries, (RsFile)fileA3D);
@@ -856,43 +855,43 @@
free(fileEntries);
}
-static int
+static jlong
nFileA3DGetEntryByIndex(JNIEnv *_env, jobject _this, jlong con, jlong fileA3D, jint index)
{
- ALOGV("______nFileA3D %u", (uint32_t) fileA3D);
- jint id = (jint)rsaFileA3DGetEntryByIndex((RsContext)con, (uint32_t)index, (RsFile)fileA3D);
+ ALOGV("______nFileA3D %p", (RsFile) fileA3D);
+ jlong id = (jlong)rsaFileA3DGetEntryByIndex((RsContext)con, (uint32_t)index, (RsFile)fileA3D);
return id;
}
// -----------------------------------
-static int
+static jlong
nFontCreateFromFile(JNIEnv *_env, jobject _this, jlong con,
jstring fileName, jfloat fontSize, jint dpi)
{
AutoJavaStringToUTF8 fileNameUTF(_env, fileName);
- jint id = (jint)rsFontCreateFromFile((RsContext)con,
+ jlong id = (jlong)rsFontCreateFromFile((RsContext)con,
fileNameUTF.c_str(), fileNameUTF.length(),
fontSize, dpi);
return id;
}
-static int
+static jlong
nFontCreateFromAssetStream(JNIEnv *_env, jobject _this, jlong con,
- jstring name, jfloat fontSize, jint dpi, jint native_asset)
+ jstring name, jfloat fontSize, jint dpi, jlong native_asset)
{
Asset* asset = reinterpret_cast<Asset*>(native_asset);
AutoJavaStringToUTF8 nameUTF(_env, name);
- jint id = (jint)rsFontCreateFromMemory((RsContext)con,
+ jlong id = (jlong)rsFontCreateFromMemory((RsContext)con,
nameUTF.c_str(), nameUTF.length(),
fontSize, dpi,
asset->getBuffer(false), asset->getLength());
return id;
}
-static int
+static jlong
nFontCreateFromAsset(JNIEnv *_env, jobject _this, jlong con, jobject _assetMgr, jstring _path,
jfloat fontSize, jint dpi)
{
@@ -907,7 +906,7 @@
return 0;
}
- jint id = (jint)rsFontCreateFromMemory((RsContext)con,
+ jlong id = (jlong)rsFontCreateFromMemory((RsContext)con,
str.c_str(), str.length(),
fontSize, dpi,
asset->getBuffer(false), asset->getLength());
@@ -1126,7 +1125,7 @@
// -----------------------------------
-static jint
+static jlong
nScriptCCreate(JNIEnv *_env, jobject _this, jlong con,
jstring resName, jstring cacheDir,
jbyteArray scriptRef, jint length)
@@ -1135,7 +1134,7 @@
AutoJavaStringToUTF8 resNameUTF(_env, resName);
AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir);
- jint ret = 0;
+ jlong ret = 0;
jbyte* script_ptr = NULL;
jint _exception = 0;
jint remaining;
@@ -1161,7 +1160,7 @@
//rsScriptCSetText((RsContext)con, (const char *)script_ptr, length);
- ret = (jint)rsScriptCCreate((RsContext)con,
+ ret = (jlong)rsScriptCCreate((RsContext)con,
resNameUTF.c_str(), resNameUTF.length(),
cacheDirUTF.c_str(), cacheDirUTF.length(),
(const char *)script_ptr, length);
@@ -1172,7 +1171,7 @@
_exception ? JNI_ABORT: 0);
}
- return ret;
+ return (jlong)ret;
}
static jlong
@@ -1186,14 +1185,14 @@
nScriptKernelIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot, jint sig)
{
LOG_API("nScriptKernelIDCreate, con(%p) script(%p), slot(%i), sig(%i)", (RsContext)con, (void *)sid, slot, sig);
- return (jint)rsScriptKernelIDCreate((RsContext)con, (RsScript)sid, slot, sig);
+ return (jlong)rsScriptKernelIDCreate((RsContext)con, (RsScript)sid, slot, sig);
}
static jlong
nScriptFieldIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot)
{
LOG_API("nScriptFieldIDCreate, con(%p) script(%p), slot(%i)", (RsContext)con, (void *)sid, slot);
- return (jint)rsScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot);
+ return (jlong)rsScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot);
}
static jlong
@@ -1253,7 +1252,7 @@
// ---------------------------------------------------------------------------
-static jint
+static jlong
nProgramStoreCreate(JNIEnv *_env, jobject _this, jlong con,
jboolean colorMaskR, jboolean colorMaskG, jboolean colorMaskB, jboolean colorMaskA,
jboolean depthMask, jboolean ditherEnable,
@@ -1261,7 +1260,7 @@
jint depthFunc)
{
LOG_API("nProgramStoreCreate, con(%p)", (RsContext)con);
- return (jint)rsProgramStoreCreate((RsContext)con, colorMaskR, colorMaskG, colorMaskB, colorMaskA,
+ return (jlong)rsProgramStoreCreate((RsContext)con, colorMaskR, colorMaskG, colorMaskB, colorMaskA,
depthMask, ditherEnable, (RsBlendSrcFunc)srcFunc,
(RsBlendDstFunc)destFunc, (RsDepthFunc)depthFunc);
}
@@ -1346,7 +1345,7 @@
nProgramRasterCreate(JNIEnv *_env, jobject _this, jlong con, jboolean pointSprite, jint cull)
{
LOG_API("nProgramRasterCreate, con(%p), pointSprite(%i), cull(%i)", (RsContext)con, pointSprite, cull);
- return (jint)rsProgramRasterCreate((RsContext)con, pointSprite, (RsCullMode)cull);
+ return (jlong)rsProgramRasterCreate((RsContext)con, pointSprite, (RsCullMode)cull);
}
@@ -1390,12 +1389,12 @@
// ---------------------------------------------------------------------------
-static jint
+static jlong
nSamplerCreate(JNIEnv *_env, jobject _this, jlong con, jint magFilter, jint minFilter,
jint wrapS, jint wrapT, jint wrapR, jfloat aniso)
{
LOG_API("nSamplerCreate, con(%p)", (RsContext)con);
- return (jint)rsSamplerCreate((RsContext)con,
+ return (jlong)rsSamplerCreate((RsContext)con,
(RsSamplerValue)magFilter,
(RsSamplerValue)minFilter,
(RsSamplerValue)wrapS,
@@ -1407,7 +1406,7 @@
// ---------------------------------------------------------------------------
static jlong
-nPathCreate(JNIEnv *_env, jobject _this, jlong con, jint prim, jboolean isStatic, jlong _vtx, jint _loop, jfloat q) {
+nPathCreate(JNIEnv *_env, jobject _this, jlong con, jint prim, jboolean isStatic, jlong _vtx, jlong _loop, jfloat q) {
LOG_API("nPathCreate, con(%p)", (RsContext)con);
jlong id = (jlong)rsPathCreate((RsContext)con, (RsPathPrimitive)prim, isStatic,
@@ -1526,15 +1525,15 @@
{"rsnObjDestroy", "(JJ)V", (void*)nObjDestroy },
{"rsnFileA3DCreateFromFile", "(JLjava/lang/String;)J", (void*)nFileA3DCreateFromFile },
-{"rsnFileA3DCreateFromAssetStream", "(JI)J", (void*)nFileA3DCreateFromAssetStream },
+{"rsnFileA3DCreateFromAssetStream", "(JJ)J", (void*)nFileA3DCreateFromAssetStream },
{"rsnFileA3DCreateFromAsset", "(JLandroid/content/res/AssetManager;Ljava/lang/String;)J", (void*)nFileA3DCreateFromAsset },
{"rsnFileA3DGetNumIndexEntries", "(JJ)I", (void*)nFileA3DGetNumIndexEntries },
{"rsnFileA3DGetIndexEntries", "(JJI[I[Ljava/lang/String;)V", (void*)nFileA3DGetIndexEntries },
-{"rsnFileA3DGetEntryByIndex", "(JJI)I", (void*)nFileA3DGetEntryByIndex },
+{"rsnFileA3DGetEntryByIndex", "(JJI)J", (void*)nFileA3DGetEntryByIndex },
-{"rsnFontCreateFromFile", "(JLjava/lang/String;FI)I", (void*)nFontCreateFromFile },
-{"rsnFontCreateFromAssetStream", "(JLjava/lang/String;FII)I", (void*)nFontCreateFromAssetStream },
-{"rsnFontCreateFromAsset", "(JLandroid/content/res/AssetManager;Ljava/lang/String;FI)I", (void*)nFontCreateFromAsset },
+{"rsnFontCreateFromFile", "(JLjava/lang/String;FI)J", (void*)nFontCreateFromFile },
+{"rsnFontCreateFromAssetStream", "(JLjava/lang/String;FIJ)J", (void*)nFontCreateFromAssetStream },
+{"rsnFontCreateFromAsset", "(JLandroid/content/res/AssetManager;Ljava/lang/String;FI)J", (void*)nFontCreateFromAsset },
{"rsnElementCreate", "(JJIZI)J", (void*)nElementCreate },
{"rsnElementCreate2", "(J[I[Ljava/lang/String;[I)J", (void*)nElementCreate2 },
@@ -1591,7 +1590,7 @@
{"rsnScriptSetVarVE", "(JJI[BJ[I)V", (void*)nScriptSetVarVE },
{"rsnScriptSetVarObj", "(JJIJ)V", (void*)nScriptSetVarObj },
-{"rsnScriptCCreate", "(JLjava/lang/String;Ljava/lang/String;[BI)I", (void*)nScriptCCreate },
+{"rsnScriptCCreate", "(JLjava/lang/String;Ljava/lang/String;[BI)J", (void*)nScriptCCreate },
{"rsnScriptIntrinsicCreate", "(JIJ)J", (void*)nScriptIntrinsicCreate },
{"rsnScriptKernelIDCreate", "(JJII)J", (void*)nScriptKernelIDCreate },
{"rsnScriptFieldIDCreate", "(JJI)J", (void*)nScriptFieldIDCreate },
@@ -1600,7 +1599,7 @@
{"rsnScriptGroupSetOutput", "(JJJJ)V", (void*)nScriptGroupSetOutput },
{"rsnScriptGroupExecute", "(JJ)V", (void*)nScriptGroupExecute },
-{"rsnProgramStoreCreate", "(JZZZZZZIII)I", (void*)nProgramStoreCreate },
+{"rsnProgramStoreCreate", "(JZZZZZZIII)J", (void*)nProgramStoreCreate },
{"rsnProgramBindConstants", "(JJIJ)V", (void*)nProgramBindConstants },
{"rsnProgramBindTexture", "(JJIJ)V", (void*)nProgramBindTexture },
@@ -1616,9 +1615,9 @@
{"rsnContextBindProgramVertex", "(JI)V", (void*)nContextBindProgramVertex },
{"rsnContextBindProgramRaster", "(JI)V", (void*)nContextBindProgramRaster },
-{"rsnSamplerCreate", "(JIIIIIF)I", (void*)nSamplerCreate },
+{"rsnSamplerCreate", "(JIIIIIF)J", (void*)nSamplerCreate },
-{"rsnPathCreate", "(JIZJIF)J", (void*)nPathCreate },
+{"rsnPathCreate", "(JIZJJF)J", (void*)nPathCreate },
{"rsnMeshCreate", "(J[I[I[I)J", (void*)nMeshCreate },
{"rsnMeshGetVertexBufferCount", "(JJ)I", (void*)nMeshGetVertexBufferCount },
@@ -1648,7 +1647,7 @@
assert(env != NULL);
if (registerFuncs(env) < 0) {
- ALOGE("ERROR: MediaPlayer native registration failed\n");
+ ALOGE("ERROR: Renderscript native registration failed\n");
goto bail;
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
index 3378e3d..e208677 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
@@ -53,13 +53,13 @@
static final String TAG = "AppWidgetService";
- Context mContext;
- Handler mSaveStateHandler;
+ final Context mContext;
+ final Handler mSaveStateHandler;
- SparseArray<AppWidgetServiceImpl> mAppWidgetServices;
+ final SparseArray<AppWidgetServiceImpl> mAppWidgetServices;
- @Override
- public void onCreate(Context context) {
+ public AppWidgetService(Context context) {
+ super(context);
mContext = context;
mSaveStateHandler = BackgroundThread.getHandler();
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 1e7c18a..186ae1b 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -83,6 +83,7 @@
import com.android.internal.backup.IBackupTransport;
import com.android.internal.backup.IObbBackupService;
import com.android.server.EventLogTags;
+import com.android.server.SystemService;
import com.android.server.backup.PackageManagerBackupAgent.Metadata;
import java.io.BufferedInputStream;
@@ -277,6 +278,20 @@
// Watch the device provisioning operation during setup
ContentObserver mProvisionedObserver;
+ public static final class Lifecycle extends SystemService {
+ private final BackupManagerService mService;
+
+ public Lifecycle(Context context) {
+ super(context);
+ mService = new BackupManagerService(context);
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(Context.BACKUP_SERVICE, mService);
+ }
+ }
+
class ProvisionedObserver extends ContentObserver {
public ProvisionedObserver(Handler handler) {
super(handler);
diff --git a/services/backup/java/com/android/server/backup/BackupManagerSystemService.java b/services/backup/java/com/android/server/backup/BackupManagerSystemService.java
deleted file mode 100644
index db2c94a..0000000
--- a/services/backup/java/com/android/server/backup/BackupManagerSystemService.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.backup;
-
-import android.content.Context;
-
-import com.android.server.SystemService;
-
-public class BackupManagerSystemService extends SystemService {
- private BackupManagerService mBackupManagerImpl;
-
- @Override
- public void onCreate(Context context) {
- mBackupManagerImpl = new BackupManagerService(context);
- }
-
- @Override
- public void onStart() {
- publishBinderService(Context.BACKUP_SERVICE, mBackupManagerImpl);
- }
-}
-
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index eb347bb..5d86b38 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -334,6 +334,10 @@
static final BatchTimeOrder sBatchOrder = new BatchTimeOrder();
final ArrayList<Batch> mAlarmBatches = new ArrayList<Batch>();
+ public AlarmManagerService(Context context) {
+ super(context);
+ }
+
static long convertToElapsed(long when, int type) {
final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
if (isRtc) {
diff --git a/services/core/java/com/android/server/ConsumerIrService.java b/services/core/java/com/android/server/ConsumerIrService.java
index 066a9c4..ea6812d 100644
--- a/services/core/java/com/android/server/ConsumerIrService.java
+++ b/services/core/java/com/android/server/ConsumerIrService.java
@@ -29,13 +29,13 @@
private static final int MAX_XMIT_TIME = 2000000; /* in microseconds */
- private static native int halOpen();
- private static native int halTransmit(int halObject, int carrierFrequency, int[] pattern);
- private static native int[] halGetCarrierFrequencies(int halObject);
+ private static native long halOpen();
+ private static native int halTransmit(long halObject, int carrierFrequency, int[] pattern);
+ private static native int[] halGetCarrierFrequencies(long halObject);
private final Context mContext;
private final PowerManager.WakeLock mWakeLock;
- private final int mHal;
+ private final long mNativeHal;
private final Object mHalLock = new Object();
ConsumerIrService(Context context) {
@@ -45,23 +45,23 @@
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mWakeLock.setReferenceCounted(true);
- mHal = halOpen();
+ mNativeHal = halOpen();
if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CONSUMER_IR)) {
- if (mHal == 0) {
+ if (mNativeHal == 0) {
throw new RuntimeException("FEATURE_CONSUMER_IR present, but no IR HAL loaded!");
}
- } else if (mHal != 0) {
+ } else if (mNativeHal != 0) {
throw new RuntimeException("IR HAL present, but FEATURE_CONSUMER_IR is not set!");
}
}
@Override
public boolean hasIrEmitter() {
- return mHal != 0;
+ return mNativeHal != 0;
}
private void throwIfNoIrEmitter() {
- if (mHal == 0) {
+ if (mNativeHal == 0) {
throw new UnsupportedOperationException("IR emitter not available");
}
}
@@ -91,7 +91,7 @@
// Right now there is no mechanism to ensure fair queing of IR requests
synchronized (mHalLock) {
- int err = halTransmit(mHal, carrierFrequency, pattern);
+ int err = halTransmit(mNativeHal, carrierFrequency, pattern);
if (err < 0) {
Slog.e(TAG, "Error transmitting: " + err);
@@ -109,7 +109,7 @@
throwIfNoIrEmitter();
synchronized(mHalLock) {
- return halGetCarrierFrequencies(mHal);
+ return halGetCarrierFrequencies(mNativeHal);
}
}
}
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index de912dc..ad693d0 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -88,6 +88,10 @@
private PowerManager.WakeLock mWakeLock;
+ public UiModeManagerService(Context context) {
+ super(context);
+ }
+
private static Intent buildHomeIntent(String category) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(category);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 8975d12..7b2fc50 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1881,11 +1881,11 @@
}
}
- public static class Lifecycle extends SystemService {
- private ActivityManagerService mService;
+ public static final class Lifecycle extends SystemService {
+ private final ActivityManagerService mService;
- @Override
- public void onCreate(Context context) {
+ public Lifecycle(Context context) {
+ super(context);
mService = new ActivityManagerService(context);
}
@@ -7755,22 +7755,27 @@
*/
public void removeContentProvider(IBinder connection, boolean stable) {
enforceNotIsolatedCaller("removeContentProvider");
- synchronized (this) {
- ContentProviderConnection conn;
- try {
- conn = (ContentProviderConnection)connection;
- } catch (ClassCastException e) {
- String msg ="removeContentProvider: " + connection
- + " not a ContentProviderConnection";
- Slog.w(TAG, msg);
- throw new IllegalArgumentException(msg);
+ long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (this) {
+ ContentProviderConnection conn;
+ try {
+ conn = (ContentProviderConnection)connection;
+ } catch (ClassCastException e) {
+ String msg ="removeContentProvider: " + connection
+ + " not a ContentProviderConnection";
+ Slog.w(TAG, msg);
+ throw new IllegalArgumentException(msg);
+ }
+ if (conn == null) {
+ throw new NullPointerException("connection is null");
+ }
+ if (decProviderCountLocked(conn, null, null, stable)) {
+ updateOomAdjLocked();
+ }
}
- if (conn == null) {
- throw new NullPointerException("connection is null");
- }
- if (decProviderCountLocked(conn, null, null, stable)) {
- updateOomAdjLocked();
- }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 4a07256..77bb1a9 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -2734,15 +2734,6 @@
here.fillInStackTrace();
Slog.i(TAG, "Removing activity " + r + " from stack");
}
- final TaskRecord task = r.task;
- if (task != null && task.removeActivity(r)) {
- if (DEBUG_STACK) Slog.i(TAG,
- "removeActivityFromHistoryLocked: last activity removed from " + this);
- if (mStackSupervisor.isFrontStack(this) && task == topTask() && task.mOnTopOfHome) {
- mStackSupervisor.moveHomeToTop();
- }
- removeTask(task);
- }
r.takeFromHistory();
removeTimeoutsForActivityLocked(r);
if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (removed from history)");
@@ -2753,6 +2744,15 @@
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
+ final TaskRecord task = r.task;
+ if (task != null && task.removeActivity(r)) {
+ if (DEBUG_STACK) Slog.i(TAG,
+ "removeActivityFromHistoryLocked: last activity removed from " + this);
+ if (mStackSupervisor.isFrontStack(this) && task == topTask() && task.mOnTopOfHome) {
+ mStackSupervisor.moveHomeToTop();
+ }
+ removeTask(task);
+ }
cleanUpActivityServicesLocked(r);
r.removeUriPermissionsLocked();
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index d5ee838..6be6405 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -124,7 +124,7 @@
private static final int DISPLAY_BLANK_STATE_BLANKED = 1;
private static final int DISPLAY_BLANK_STATE_UNBLANKED = 2;
- private Context mContext;
+ private final Context mContext;
private final DisplayManagerHandler mHandler;
private final Handler mUiHandler;
private final DisplayAdapterListener mDisplayAdapterListener;
@@ -208,7 +208,9 @@
private final DisplayViewport mTempDefaultViewport = new DisplayViewport();
private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport();
- public DisplayManagerService() {
+ public DisplayManagerService(Context context) {
+ super(context);
+ mContext = context;
mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
mUiHandler = UiThread.getHandler();
mDisplayAdapterListener = new DisplayAdapterListener();
@@ -216,11 +218,6 @@
}
@Override
- public void onCreate(Context context) {
- mContext = context;
- }
-
- @Override
public void onStart() {
mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
index 3d22370..94cf668 100644
--- a/services/core/java/com/android/server/lights/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -157,8 +157,9 @@
}
};
- @Override
- public void onCreate(Context context) {
+ public LightsService(Context context) {
+ super(context);
+
mNativePointer = init_native();
for (int i = 0; i < LightsManager.LIGHT_ID_COUNT; i++) {
@@ -183,6 +184,7 @@
}
};
+ @Override
protected void finalize() throws Throwable {
finalize_native(mNativePointer);
super.finalize();
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e4ea033..01175bb 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1118,6 +1118,10 @@
return out;
}
+ public NotificationManagerService(Context context) {
+ super(context);
+ }
+
@Override
public void onStart() {
mAm = ActivityManagerNative.getDefault();
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index e2ff146..6185e50 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -18,6 +18,7 @@
import com.android.server.SystemService;
+import android.content.Context;
import android.content.pm.PackageStats;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
@@ -39,6 +40,10 @@
byte buf[] = new byte[1024];
int buflen = 0;
+ public Installer(Context context) {
+ super(context);
+ }
+
@Override
public void onStart() {
Slog.i(TAG, "Waiting for installd to be ready.");
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index b9ecde1..b2344e6 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -168,7 +168,7 @@
// effectively and terminate the dream.
private static final int DREAM_BATTERY_LEVEL_DRAIN_CUTOFF = 5;
- private Context mContext;
+ private final Context mContext;
private LightsManager mLightsManager;
private BatteryService mBatteryService;
private DisplayManagerInternal mDisplayManagerInternal;
@@ -374,7 +374,9 @@
private static native void nativeSetInteractive(boolean enable);
private static native void nativeSetAutoSuspend(boolean enable);
- public PowerManagerService() {
+ public PowerManagerService(Context context) {
+ super(context);
+ mContext = context;
synchronized (mLock) {
mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
@@ -391,11 +393,6 @@
}
@Override
- public void onCreate(Context context) {
- mContext = context;
- }
-
- @Override
public void onStart() {
publishBinderService(Context.POWER_SERVICE, new BinderService());
publishLocalService(PowerManagerInternal.class, new LocalService());
diff --git a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
index 8805084..43a99e0 100644
--- a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
+++ b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
@@ -89,11 +89,11 @@
private long mLastReportedFreeMemTime;
boolean mLowMemFlag=false;
private boolean mMemFullFlag=false;
- private ContentResolver mResolver;
- private long mTotalMemory; // on /data
- private StatFs mDataFileStats;
- private StatFs mSystemFileStats;
- private StatFs mCacheFileStats;
+ private final ContentResolver mResolver;
+ private final long mTotalMemory; // on /data
+ private final StatFs mDataFileStats;
+ private final StatFs mSystemFileStats;
+ private final StatFs mCacheFileStats;
private static final File DATA_PATH = Environment.getDataDirectory();
private static final File SYSTEM_PATH = Environment.getRootDirectory();
@@ -102,10 +102,10 @@
private long mThreadStartTime = -1;
boolean mClearSucceeded = false;
boolean mClearingCache;
- private Intent mStorageLowIntent;
- private Intent mStorageOkIntent;
- private Intent mStorageFullIntent;
- private Intent mStorageNotFullIntent;
+ private final Intent mStorageLowIntent;
+ private final Intent mStorageOkIntent;
+ private final Intent mStorageFullIntent;
+ private final Intent mStorageNotFullIntent;
private CachePackageDataObserver mClearCacheObserver;
private CacheFileDeletedObserver mCacheFileDeletedObserver;
private static final int _TRUE = 1;
@@ -134,7 +134,7 @@
* Handler that checks the amount of disk space on the device and sends a
* notification if the device runs low on disk space
*/
- private Handler mHandler = new Handler() {
+ private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
//don't handle an invalid message
@@ -310,12 +310,8 @@
delay);
}
- /**
- * Constructor to run service. initializes the disk space threshold value
- * and posts an empty message to kickstart the process.
- */
- @Override
- public void onCreate(Context context) {
+ public DeviceStorageMonitorService(Context context) {
+ super(context);
mLastReportedFreeMemTime = 0;
mResolver = context.getContentResolver();
//create StatFs object
@@ -335,6 +331,10 @@
mStorageNotFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
}
+ /**
+ * Initializes the disk space threshold value and posts an empty message to
+ * kickstart the process.
+ */
@Override
public void onStart() {
// cache storage thresholds
diff --git a/services/core/java/com/android/server/twilight/TwilightService.java b/services/core/java/com/android/server/twilight/TwilightService.java
index 8feb97b..a71961c 100644
--- a/services/core/java/com/android/server/twilight/TwilightService.java
+++ b/services/core/java/com/android/server/twilight/TwilightService.java
@@ -65,6 +65,10 @@
TwilightState mTwilightState;
+ public TwilightService(Context context) {
+ super(context);
+ }
+
@Override
public void onStart() {
mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 7293d6f..8f07e27 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -4535,8 +4535,8 @@
void removeAppFromTaskLocked(AppWindowToken wtoken) {
final Task task = mTaskIdToTask.get(wtoken.groupId);
- if (!wtoken.mDeferRemoval && task != null && task.removeAppToken(wtoken)) {
- removeTaskLocked(task);
+ if (task != null) {
+ task.removeAppToken(wtoken);
}
}
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index 1a3ce63..85f69a4 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -2,6 +2,8 @@
# files
LOCAL_REL_DIR := core/jni
+LOCAL_CFLAGS += -Wno-unused-parameter
+
LOCAL_SRC_FILES += \
$(LOCAL_REL_DIR)/com_android_server_AlarmManagerService.cpp \
$(LOCAL_REL_DIR)/com_android_server_AssetAtlasService.cpp \
@@ -45,6 +47,7 @@
libutils \
libui \
libinput \
+ libinputflinger \
libinputservice \
libsensorservice \
libskia \
diff --git a/services/core/jni/com_android_server_ConsumerIrService.cpp b/services/core/jni/com_android_server_ConsumerIrService.cpp
index 004c0aa..3a50ff7 100644
--- a/services/core/jni/com_android_server_ConsumerIrService.cpp
+++ b/services/core/jni/com_android_server_ConsumerIrService.cpp
@@ -29,7 +29,7 @@
namespace android {
-static jint halOpen(JNIEnv *env, jobject obj) {
+static jlong halOpen(JNIEnv *env, jobject obj) {
hw_module_t const* module;
consumerir_device_t *dev;
int err;
@@ -47,10 +47,10 @@
return 0;
}
- return reinterpret_cast<jint>(dev);
+ return reinterpret_cast<jlong>(dev);
}
-static jint halTransmit(JNIEnv *env, jobject obj, jint halObject,
+static jint halTransmit(JNIEnv *env, jobject obj, jlong halObject,
jint carrierFrequency, jintArray pattern) {
int ret;
@@ -67,8 +67,8 @@
}
static jintArray halGetCarrierFrequencies(JNIEnv *env, jobject obj,
- jint halObject) {
- consumerir_device_t *dev = (consumerir_device_t *) halObject;
+ jlong halObject) {
+ consumerir_device_t *dev = reinterpret_cast<consumerir_device_t*>(halObject);
consumerir_freq_range_t *ranges;
int len;
@@ -101,9 +101,9 @@
}
static JNINativeMethod method_table[] = {
- { "halOpen", "()I", (void *)halOpen },
- { "halTransmit", "(II[I)I", (void *)halTransmit },
- { "halGetCarrierFrequencies", "(I)[I", (void *)halGetCarrierFrequencies},
+ { "halOpen", "()J", (void *)halOpen },
+ { "halTransmit", "(JI[I)I", (void *)halTransmit },
+ { "halGetCarrierFrequencies", "(J)[I", (void *)halGetCarrierFrequencies},
};
int register_android_server_ConsumerIrService(JNIEnv *env) {
diff --git a/services/core/jni/com_android_server_input_InputApplicationHandle.h b/services/core/jni/com_android_server_input_InputApplicationHandle.h
index 89d48c6..62c8570 100644
--- a/services/core/jni/com_android_server_input_InputApplicationHandle.h
+++ b/services/core/jni/com_android_server_input_InputApplicationHandle.h
@@ -17,7 +17,7 @@
#ifndef _ANDROID_SERVER_INPUT_APPLICATION_HANDLE_H
#define _ANDROID_SERVER_INPUT_APPLICATION_HANDLE_H
-#include <input/InputApplication.h>
+#include <inputflinger/InputApplication.h>
#include "JNIHelp.h"
#include "jni.h"
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 43fbe9d..321776c 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -35,10 +35,11 @@
#include <utils/Looper.h>
#include <utils/threads.h>
-#include <input/InputManager.h>
#include <input/PointerController.h>
#include <input/SpriteController.h>
+#include <inputflinger/InputManager.h>
+
#include <android_os_MessageQueue.h>
#include <android_view_InputDevice.h>
#include <android_view_KeyEvent.h>
diff --git a/services/core/jni/com_android_server_input_InputWindowHandle.cpp b/services/core/jni/com_android_server_input_InputWindowHandle.cpp
index b80183c..03bf7eb 100644
--- a/services/core/jni/com_android_server_input_InputWindowHandle.cpp
+++ b/services/core/jni/com_android_server_input_InputWindowHandle.cpp
@@ -23,6 +23,7 @@
#include <android_view_InputChannel.h>
#include <android/graphics/Region.h>
+#include <ui/Region.h>
#include "com_android_server_input_InputWindowHandle.h"
#include "com_android_server_input_InputApplicationHandle.h"
@@ -86,6 +87,8 @@
if (!mInfo) {
mInfo = new InputWindowInfo();
+ } else {
+ mInfo->touchableRegion.clear();
}
jobject inputChannelObj = env->GetObjectField(obj,
@@ -131,10 +134,11 @@
gInputWindowHandleClassInfo.touchableRegion);
if (regionObj) {
SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj);
- mInfo->touchableRegion.set(*region);
+ for (SkRegion::Iterator it(*region); !it.done(); it.next()) {
+ const SkIRect& rect = it.rect();
+ mInfo->addTouchableRegion(Rect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom));
+ }
env->DeleteLocalRef(regionObj);
- } else {
- mInfo->touchableRegion.setEmpty();
}
mInfo->visible = env->GetBooleanField(obj,
diff --git a/services/core/jni/com_android_server_input_InputWindowHandle.h b/services/core/jni/com_android_server_input_InputWindowHandle.h
index 2cfa17d3..8d9e7d7 100644
--- a/services/core/jni/com_android_server_input_InputWindowHandle.h
+++ b/services/core/jni/com_android_server_input_InputWindowHandle.h
@@ -17,7 +17,7 @@
#ifndef _ANDROID_SERVER_INPUT_WINDOW_HANDLE_H
#define _ANDROID_SERVER_INPUT_WINDOW_HANDLE_H
-#include <input/InputWindow.h>
+#include <inputflinger/InputWindow.h>
#include "JNIHelp.h"
#include "jni.h"
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.h b/services/core/jni/com_android_server_power_PowerManagerService.h
index 0808b80..b48e546 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.h
+++ b/services/core/jni/com_android_server_power_PowerManagerService.h
@@ -20,7 +20,7 @@
#include "JNIHelp.h"
#include "jni.h"
-#include <androidfw/PowerManager.h>
+#include <powermanager/PowerManager.h>
namespace android {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a8f2df1..bb96544 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -25,6 +25,7 @@
import com.android.internal.util.XmlUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.org.conscrypt.TrustedCertificateStore;
+import com.android.server.SystemService;
import android.app.Activity;
import android.app.ActivityManagerNative;
@@ -138,6 +139,26 @@
*/
private boolean mHasFeature;
+ public static final class Lifecycle extends SystemService {
+ private DevicePolicyManagerService mService;
+
+ public Lifecycle(Context context) {
+ super(context);
+ mService = new DevicePolicyManagerService(context);
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(Context.DEVICE_POLICY_SERVICE, mService);
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == PHASE_LOCK_SETTINGS_READY) {
+ mService.systemReady();
+ }
+ }
+ }
public static class DevicePolicyData {
int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
int mActivePasswordLength = 0;
@@ -599,9 +620,10 @@
Slog.w(LOG_TAG, "Tried to remove device policy file for user 0! Ignoring.");
return;
}
-
- mDeviceOwner.removeProfileOwner(userHandle);
- mDeviceOwner.writeOwnerFile();
+ if (mDeviceOwner != null) {
+ mDeviceOwner.removeProfileOwner(userHandle);
+ mDeviceOwner.writeOwnerFile();
+ }
DevicePolicyData policy = mUserData.get(userHandle);
if (policy != null) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerSystemService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerSystemService.java
deleted file mode 100644
index 160aa39..0000000
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerSystemService.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.devicepolicy;
-
-import android.content.Context;
-
-import com.android.server.SystemService;
-
-/**
- * SystemService wrapper for the DevicePolicyManager implementation. Publishes
- * Context.DEVICE_POLICY_SERVICE.
- */
-public final class DevicePolicyManagerSystemService extends SystemService {
- private DevicePolicyManagerService mDevicePolicyManagerImpl;
-
- @Override
- public void onCreate(Context context) {
- mDevicePolicyManagerImpl = new DevicePolicyManagerService(context);
- }
-
- @Override
- public void onStart() {
- publishBinderService(Context.DEVICE_POLICY_SERVICE, mDevicePolicyManagerImpl);
- }
-
- @Override
- public void onBootPhase(int phase) {
- if (phase == PHASE_LOCK_SETTINGS_READY) {
- mDevicePolicyManagerImpl.systemReady();
- }
- }
-}
\ No newline at end of file
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 9bc2201..85e5e23 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -104,9 +104,9 @@
* them from the build system somehow.
*/
private static final String BACKUP_MANAGER_SERVICE_CLASS =
- "com.android.server.backup.BackupManagerSystemService";
+ "com.android.server.backup.BackupManagerService$Lifecycle";
private static final String DEVICE_POLICY_MANAGER_SERVICE_CLASS =
- "com.android.server.devicepolicy.DevicePolicyManagerSystemService";
+ "com.android.server.devicepolicy.DevicePolicyManagerService$Lifecycle";
private static final String APPWIDGET_SERVICE_CLASS =
"com.android.server.appwidget.AppWidgetService";
private static final String PRINT_MANAGER_SERVICE_CLASS =
@@ -209,6 +209,7 @@
// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
+ LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Start services.
try {
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index 7438297..f7bec6e 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -66,13 +66,13 @@
*/
public final class PrintManagerService extends SystemService {
+ private final PrintManagerImpl mPrintManagerImpl;
- private PrintManagerImpl mPrintManagerImpl;
-
- @Override
- public void onCreate(Context context) {
+ public PrintManagerService(Context context) {
+ super(context);
mPrintManagerImpl = new PrintManagerImpl(context);
}
+
@Override
public void onStart() {
publishBinderService(Context.PRINT_SERVICE, mPrintManagerImpl);
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java
index 0b85189..8d8d9de 100644
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java
+++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/CompareActivity.java
@@ -97,7 +97,7 @@
Log.d(LOG_TAG, "failure to access hardware layer");
return;
}
- Method copyInto = hardwareLayer.getClass().getSuperclass()
+ Method copyInto = hardwareLayer.getClass()
.getDeclaredMethod("copyInto", Bitmap.class);
if (!copyInto.isAccessible())
copyInto.setAccessible(true);
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java
index a08b558..c90b626 100644
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java
+++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/ErrorCalculator.java
@@ -35,23 +35,24 @@
private static final boolean LOG_TIMING = false;
private static final boolean LOG_CALC = false;
- private final RenderScript mRS;
+ private RenderScript mRS;
private Allocation mIdealPixelsAllocation;
private Allocation mGivenPixelsAllocation;
private Allocation mOutputPixelsAllocation;
- private final Allocation mInputRowsAllocation;
- private final Allocation mOutputRegionsAllocation;
+ private Allocation mInputRowsAllocation;
+ private Allocation mOutputRegionsAllocation;
- private final ScriptC_errorCalculator mScript;
+ private ScriptC_errorCalculator mScript;
- private final int[] mOutputRowRegions;
+ private int[] mOutputRowRegions;
public ErrorCalculator(Context c, Resources resources) {
int width = resources.getDimensionPixelSize(R.dimen.layer_width);
int height = resources.getDimensionPixelSize(R.dimen.layer_height);
mOutputRowRegions = new int[height / REGION_SIZE];
+/*
mRS = RenderScript.create(c);
int[] rowIndices = new int[height / REGION_SIZE];
for (int i = 0; i < rowIndices.length; i++)
@@ -67,12 +68,15 @@
mInputRowsAllocation.copyFrom(rowIndices);
mOutputRegionsAllocation = Allocation.createSized(mRS, Element.I32(mRS),
mOutputRowRegions.length, Allocation.USAGE_SCRIPT);
+*/
}
private static long startMillis, middleMillis;
public float calcErrorRS(Bitmap ideal, Bitmap given) {
+ if (true)
+ return calcError(ideal, given);
if (LOG_TIMING) {
startMillis = System.currentTimeMillis();
}
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 6a3c506..f9a2d19 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -149,205 +149,506 @@
// =========================================================================
// =========================================================================
-status_t
-AaptGroupEntry::parseNamePart(const String8& part, int* axis, uint32_t* value)
+/* static */ void AaptLocaleValue::splitAndLowerCase(const char* const chars,
+ Vector<String8>* parts, const char separator) {
+ const char *p = chars;
+ const char *q;
+ while (NULL != (q = strchr(p, separator))) {
+ String8 val(p, q - p);
+ val.toLower();
+ parts->add(val);
+ p = q+1;
+ }
+
+ if (p < chars + strlen(chars)) {
+ String8 val(p);
+ val.toLower();
+ parts->add(val);
+ }
+}
+
+/* static */
+inline bool isAlpha(const String8& string) {
+ const size_t length = string.length();
+ for (size_t i = 0; i < length; ++i) {
+ if (!isalpha(string[i])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* static */
+inline bool isNumber(const String8& string) {
+ const size_t length = string.length();
+ for (size_t i = 0; i < length; ++i) {
+ if (!isdigit(string[i])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void AaptLocaleValue::setLanguage(const char* languageChars) {
+ size_t i = 0;
+ while ((*languageChars) != '\0') {
+ language[i++] = tolower(*languageChars);
+ languageChars++;
+ }
+}
+
+void AaptLocaleValue::setRegion(const char* regionChars) {
+ size_t i = 0;
+ while ((*regionChars) != '\0') {
+ region[i++] = toupper(*regionChars);
+ regionChars++;
+ }
+}
+
+void AaptLocaleValue::setScript(const char* scriptChars) {
+ size_t i = 0;
+ while ((*scriptChars) != '\0') {
+ if (i == 0) {
+ script[i++] = toupper(*scriptChars);
+ } else {
+ script[i++] = tolower(*scriptChars);
+ }
+ scriptChars++;
+ }
+}
+
+void AaptLocaleValue::setVariant(const char* variantChars) {
+ size_t i = 0;
+ while ((*variantChars) != '\0') {
+ variant[i++] = *variantChars;
+ variantChars++;
+ }
+}
+
+bool AaptLocaleValue::initFromFilterString(const String8& str) {
+ // A locale (as specified in the filter) is an underscore separated name such
+ // as "en_US", "en_Latn_US", or "en_US_POSIX".
+ Vector<String8> parts;
+ splitAndLowerCase(str.string(), &parts, '_');
+
+ const int numTags = parts.size();
+ bool valid = false;
+ if (numTags >= 1) {
+ const String8& lang = parts[0];
+ if (isAlpha(lang) && (lang.length() == 2 || lang.length() == 3)) {
+ setLanguage(lang.string());
+ valid = true;
+ }
+ }
+
+ if (!valid || numTags == 1) {
+ return valid;
+ }
+
+ // At this point, valid == true && numTags > 1.
+ const String8& part2 = parts[1];
+ if ((part2.length() == 2 && isAlpha(part2)) ||
+ (part2.length() == 3 && isNumber(part2))) {
+ setRegion(part2.string());
+ } else if (part2.length() == 4 && isAlpha(part2)) {
+ setScript(part2.string());
+ } else if (part2.length() >= 5 && part2.length() <= 8) {
+ setVariant(part2.string());
+ } else {
+ valid = false;
+ }
+
+ if (!valid || numTags == 2) {
+ return valid;
+ }
+
+ // At this point, valid == true && numTags > 1.
+ const String8& part3 = parts[2];
+ if (((part3.length() == 2 && isAlpha(part3)) ||
+ (part3.length() == 3 && isNumber(part3))) && script[0]) {
+ setRegion(part3.string());
+ } else if (part3.length() >= 5 && part3.length() <= 8) {
+ setVariant(part3.string());
+ } else {
+ valid = false;
+ }
+
+ if (!valid || numTags == 3) {
+ return valid;
+ }
+
+ const String8& part4 = parts[3];
+ if (part4.length() >= 5 && part4.length() <= 8) {
+ setVariant(part4.string());
+ } else {
+ valid = false;
+ }
+
+ if (!valid || numTags > 4) {
+ return false;
+ }
+
+ return true;
+}
+
+int AaptLocaleValue::initFromDirName(const Vector<String8>& parts, const int startIndex) {
+ const int size = parts.size();
+ int currentIndex = startIndex;
+
+ String8 part = parts[currentIndex];
+ if (part[0] == 'b' && part[1] == '+') {
+ // This is a "modified" BCP-47 language tag. Same semantics as BCP-47 tags,
+ // except that the separator is "+" and not "-".
+ Vector<String8> subtags;
+ AaptLocaleValue::splitAndLowerCase(part.string(), &subtags, '+');
+ subtags.removeItemsAt(0);
+ if (subtags.size() == 1) {
+ setLanguage(subtags[0]);
+ } else if (subtags.size() == 2) {
+ setLanguage(subtags[0]);
+
+ // The second tag can either be a region, a variant or a script.
+ switch (subtags[1].size()) {
+ case 2:
+ case 3:
+ setRegion(subtags[1]);
+ break;
+ case 4:
+ setScript(subtags[1]);
+ break;
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ setVariant(subtags[1]);
+ break;
+ default:
+ fprintf(stderr, "ERROR: Invalid BCP-47 tag in directory name %s\n",
+ part.string());
+ return -1;
+ }
+ } else if (subtags.size() == 3) {
+ // The language is always the first subtag.
+ setLanguage(subtags[0]);
+
+ // The second subtag can either be a script or a region code.
+ // If its size is 4, it's a script code, else it's a region code.
+ bool hasRegion = false;
+ if (subtags[1].size() == 4) {
+ setScript(subtags[1]);
+ } else if (subtags[1].size() == 2 || subtags[1].size() == 3) {
+ setRegion(subtags[1]);
+ hasRegion = true;
+ } else {
+ fprintf(stderr, "ERROR: Invalid BCP-47 tag in directory name %s\n", part.string());
+ return -1;
+ }
+
+ // The third tag can either be a region code (if the second tag was
+ // a script), else a variant code.
+ if (subtags[2].size() > 4) {
+ setVariant(subtags[2]);
+ } else {
+ setRegion(subtags[2]);
+ }
+ } else if (subtags.size() == 4) {
+ setLanguage(subtags[0]);
+ setScript(subtags[1]);
+ setRegion(subtags[2]);
+ setVariant(subtags[3]);
+ } else {
+ fprintf(stderr, "ERROR: Invalid BCP-47 tag in directory name: %s\n", part.string());
+ return -1;
+ }
+
+ return ++currentIndex;
+ } else {
+ if ((part.length() == 2 || part.length() == 3) && isAlpha(part)) {
+ setLanguage(part);
+ if (++currentIndex == size) {
+ return size;
+ }
+ } else {
+ return currentIndex;
+ }
+
+ part = parts[currentIndex];
+ if (part.string()[0] == 'r' && part.length() == 3) {
+ setRegion(part.string() + 1);
+ if (++currentIndex == size) {
+ return size;
+ }
+ }
+ }
+
+ return currentIndex;
+}
+
+
+String8 AaptLocaleValue::toDirName() const {
+ String8 dirName("");
+ if (language[0]) {
+ dirName += language;
+ } else {
+ return dirName;
+ }
+
+ if (script[0]) {
+ dirName += "-s";
+ dirName += script;
+ }
+
+ if (region[0]) {
+ dirName += "-r";
+ dirName += region;
+ }
+
+ if (variant[0]) {
+ dirName += "-v";
+ dirName += variant;
+ }
+
+ return dirName;
+}
+
+void AaptLocaleValue::initFromResTable(const ResTable_config& config) {
+ config.unpackLanguage(language);
+ config.unpackRegion(region);
+ if (config.localeScript[0]) {
+ memcpy(script, config.localeScript, sizeof(config.localeScript));
+ }
+
+ if (config.localeVariant[0]) {
+ memcpy(variant, config.localeVariant, sizeof(config.localeVariant));
+ }
+}
+
+void AaptLocaleValue::writeTo(ResTable_config* out) const {
+ out->packLanguage(language);
+ out->packRegion(region);
+
+ if (script[0]) {
+ memcpy(out->localeScript, script, sizeof(out->localeScript));
+ }
+
+ if (variant[0]) {
+ memcpy(out->localeVariant, variant, sizeof(out->localeVariant));
+ }
+}
+
+
+/* static */ bool
+AaptGroupEntry::parseFilterNamePart(const String8& part, int* axis, AxisValue* value)
{
ResTable_config config;
+ memset(&config, 0, sizeof(ResTable_config));
// IMSI - MCC
if (getMccName(part.string(), &config)) {
*axis = AXIS_MCC;
- *value = config.mcc;
- return 0;
+ value->intValue = config.mcc;
+ return true;
}
// IMSI - MNC
if (getMncName(part.string(), &config)) {
*axis = AXIS_MNC;
- *value = config.mnc;
- return 0;
+ value->intValue = config.mnc;
+ return true;
}
// locale - language
- if (part.length() == 2 && isalpha(part[0]) && isalpha(part[1])) {
- *axis = AXIS_LANGUAGE;
- *value = part[1] << 8 | part[0];
- return 0;
- }
-
- // locale - language_REGION
- if (part.length() == 5 && isalpha(part[0]) && isalpha(part[1])
- && part[2] == '_' && isalpha(part[3]) && isalpha(part[4])) {
- *axis = AXIS_LANGUAGE;
- *value = (part[4] << 24) | (part[3] << 16) | (part[1] << 8) | (part[0]);
- return 0;
+ if (value->localeValue.initFromFilterString(part)) {
+ *axis = AXIS_LOCALE;
+ return true;
}
// layout direction
if (getLayoutDirectionName(part.string(), &config)) {
*axis = AXIS_LAYOUTDIR;
- *value = (config.screenLayout&ResTable_config::MASK_LAYOUTDIR);
- return 0;
+ value->intValue = (config.screenLayout&ResTable_config::MASK_LAYOUTDIR);
+ return true;
}
// smallest screen dp width
if (getSmallestScreenWidthDpName(part.string(), &config)) {
*axis = AXIS_SMALLESTSCREENWIDTHDP;
- *value = config.smallestScreenWidthDp;
- return 0;
+ value->intValue = config.smallestScreenWidthDp;
+ return true;
}
// screen dp width
if (getScreenWidthDpName(part.string(), &config)) {
*axis = AXIS_SCREENWIDTHDP;
- *value = config.screenWidthDp;
- return 0;
+ value->intValue = config.screenWidthDp;
+ return true;
}
// screen dp height
if (getScreenHeightDpName(part.string(), &config)) {
*axis = AXIS_SCREENHEIGHTDP;
- *value = config.screenHeightDp;
- return 0;
+ value->intValue = config.screenHeightDp;
+ return true;
}
// screen layout size
if (getScreenLayoutSizeName(part.string(), &config)) {
*axis = AXIS_SCREENLAYOUTSIZE;
- *value = (config.screenLayout&ResTable_config::MASK_SCREENSIZE);
- return 0;
+ value->intValue = (config.screenLayout&ResTable_config::MASK_SCREENSIZE);
+ return true;
}
// screen layout long
if (getScreenLayoutLongName(part.string(), &config)) {
*axis = AXIS_SCREENLAYOUTLONG;
- *value = (config.screenLayout&ResTable_config::MASK_SCREENLONG);
- return 0;
+ value->intValue = (config.screenLayout&ResTable_config::MASK_SCREENLONG);
+ return true;
}
// orientation
if (getOrientationName(part.string(), &config)) {
*axis = AXIS_ORIENTATION;
- *value = config.orientation;
- return 0;
+ value->intValue = config.orientation;
+ return true;
}
// ui mode type
if (getUiModeTypeName(part.string(), &config)) {
*axis = AXIS_UIMODETYPE;
- *value = (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
- return 0;
+ value->intValue = (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
+ return true;
}
// ui mode night
if (getUiModeNightName(part.string(), &config)) {
*axis = AXIS_UIMODENIGHT;
- *value = (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
- return 0;
+ value->intValue = (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
+ return true;
}
// density
if (getDensityName(part.string(), &config)) {
*axis = AXIS_DENSITY;
- *value = config.density;
- return 0;
+ value->intValue = config.density;
+ return true;
}
// touchscreen
if (getTouchscreenName(part.string(), &config)) {
*axis = AXIS_TOUCHSCREEN;
- *value = config.touchscreen;
- return 0;
+ value->intValue = config.touchscreen;
+ return true;
}
// keyboard hidden
if (getKeysHiddenName(part.string(), &config)) {
*axis = AXIS_KEYSHIDDEN;
- *value = config.inputFlags;
- return 0;
+ value->intValue = config.inputFlags;
+ return true;
}
// keyboard
if (getKeyboardName(part.string(), &config)) {
*axis = AXIS_KEYBOARD;
- *value = config.keyboard;
- return 0;
+ value->intValue = config.keyboard;
+ return true;
}
// navigation hidden
if (getNavHiddenName(part.string(), &config)) {
*axis = AXIS_NAVHIDDEN;
- *value = config.inputFlags;
+ value->intValue = config.inputFlags;
return 0;
}
// navigation
if (getNavigationName(part.string(), &config)) {
*axis = AXIS_NAVIGATION;
- *value = config.navigation;
- return 0;
+ value->intValue = config.navigation;
+ return true;
}
// screen size
if (getScreenSizeName(part.string(), &config)) {
*axis = AXIS_SCREENSIZE;
- *value = config.screenSize;
- return 0;
+ value->intValue = config.screenSize;
+ return true;
}
// version
if (getVersionName(part.string(), &config)) {
*axis = AXIS_VERSION;
- *value = config.version;
- return 0;
+ value->intValue = config.version;
+ return true;
}
- return 1;
+ return false;
}
-uint32_t
+AxisValue
AaptGroupEntry::getConfigValueForAxis(const ResTable_config& config, int axis)
{
+ AxisValue value;
switch (axis) {
case AXIS_MCC:
- return config.mcc;
+ value.intValue = config.mcc;
+ break;
case AXIS_MNC:
- return config.mnc;
- case AXIS_LANGUAGE:
- return (((uint32_t)config.country[1]) << 24) | (((uint32_t)config.country[0]) << 16)
- | (((uint32_t)config.language[1]) << 8) | (config.language[0]);
+ value.intValue = config.mnc;
+ break;
+ case AXIS_LOCALE:
+ value.localeValue.initFromResTable(config);
+ break;
case AXIS_LAYOUTDIR:
- return config.screenLayout&ResTable_config::MASK_LAYOUTDIR;
+ value.intValue = config.screenLayout&ResTable_config::MASK_LAYOUTDIR;
+ break;
case AXIS_SCREENLAYOUTSIZE:
- return config.screenLayout&ResTable_config::MASK_SCREENSIZE;
+ value.intValue = config.screenLayout&ResTable_config::MASK_SCREENSIZE;
+ break;
case AXIS_ORIENTATION:
- return config.orientation;
+ value.intValue = config.orientation;
+ break;
case AXIS_UIMODETYPE:
- return (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
+ value.intValue = (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
+ break;
case AXIS_UIMODENIGHT:
- return (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
+ value.intValue = (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
+ break;
case AXIS_DENSITY:
- return config.density;
+ value.intValue = config.density;
+ break;
case AXIS_TOUCHSCREEN:
- return config.touchscreen;
+ value.intValue = config.touchscreen;
+ break;
case AXIS_KEYSHIDDEN:
- return config.inputFlags;
+ value.intValue = config.inputFlags;
+ break;
case AXIS_KEYBOARD:
- return config.keyboard;
+ value.intValue = config.keyboard;
+ break;
case AXIS_NAVIGATION:
- return config.navigation;
+ value.intValue = config.navigation;
+ break;
case AXIS_SCREENSIZE:
- return config.screenSize;
+ value.intValue = config.screenSize;
+ break;
case AXIS_SMALLESTSCREENWIDTHDP:
- return config.smallestScreenWidthDp;
+ value.intValue = config.smallestScreenWidthDp;
+ break;
case AXIS_SCREENWIDTHDP:
- return config.screenWidthDp;
+ value.intValue = config.screenWidthDp;
+ break;
case AXIS_SCREENHEIGHTDP:
- return config.screenHeightDp;
+ value.intValue = config.screenHeightDp;
+ break;
case AXIS_VERSION:
- return config.version;
+ value.intValue = config.version;
+ break;
}
- return 0;
+
+ return value;
}
bool
@@ -371,24 +672,14 @@
mParamsChanged = true;
Vector<String8> parts;
+ AaptLocaleValue::splitAndLowerCase(dir, &parts, '-');
- String8 mcc, mnc, loc, layoutsize, layoutlong, orient, den;
+ String8 mcc, mnc, layoutsize, layoutlong, orient, den;
String8 touch, key, keysHidden, nav, navHidden, size, layoutDir, vers;
String8 uiModeType, uiModeNight, smallestwidthdp, widthdp, heightdp;
- const char *p = dir;
- const char *q;
- while (NULL != (q = strchr(p, '-'))) {
- String8 val(p, q-p);
- val.toLower();
- parts.add(val);
- //printf("part: %s\n", parts[parts.size()-1].string());
- p = q+1;
- }
- String8 val(p);
- val.toLower();
- parts.add(val);
- //printf("part: %s\n", parts[parts.size()-1].string());
+ AaptLocaleValue locale;
+ int numLocaleComponents = 0;
const int N = parts.size();
int index = 0;
@@ -429,38 +720,18 @@
}
part = parts[index];
} else {
- //printf("not mcc: %s\n", part.string());
+ //printf("not mnc: %s\n", part.string());
}
- // locale - language
- if (part.length() == 2 && isalpha(part[0]) && isalpha(part[1])) {
- loc = part;
-
- index++;
- if (index == N) {
- goto success;
- }
- part = parts[index];
- } else {
- //printf("not language: %s\n", part.string());
+ index = locale.initFromDirName(parts, index);
+ if (index == -1) {
+ return false;
+ }
+ if (index >= N){
+ goto success;
}
- // locale - region
- if (loc.length() > 0
- && part.length() == 3 && part[0] == 'r' && part[0] && part[1]) {
- loc += "-";
- part.toUpper();
- loc += part.string() + 1;
-
- index++;
- if (index == N) {
- goto success;
- }
- part = parts[index];
- } else {
- //printf("not region: %s\n", part.string());
- }
-
+ part = parts[index];
if (getLayoutDirectionName(part.string())) {
layoutDir = part;
@@ -679,7 +950,7 @@
success:
this->mcc = mcc;
this->mnc = mnc;
- this->locale = loc;
+ this->locale = locale;
this->screenLayoutSize = layoutsize;
this->screenLayoutLong = layoutlong;
this->smallestScreenWidthDp = smallestwidthdp;
@@ -711,7 +982,7 @@
s += ",";
s += this->mnc;
s += ",";
- s += this->locale;
+ s += locale.toDirName();
s += ",";
s += layoutDirection;
s += ",";
@@ -765,12 +1036,15 @@
}
s += mnc;
}
- if (this->locale != "") {
- if (s.length() > 0) {
- s += "-";
- }
- s += locale;
+
+ const String8 localeComponent = locale.toDirName();
+ if (localeComponent != "") {
+ if (s.length() > 0) {
+ s += "-";
+ }
+ s += localeComponent;
}
+
if (this->layoutDirection != "") {
if (s.length() > 0) {
s += "-";
@@ -942,55 +1216,6 @@
return true;
}
-/*
- * Does this directory name fit the pattern of a locale dir ("en-rUS" or
- * "default")?
- *
- * TODO: Should insist that the first two letters are lower case, and the
- * second two are upper.
- */
-bool AaptGroupEntry::getLocaleName(const char* fileName,
- ResTable_config* out)
-{
- if (strcmp(fileName, kWildcardName) == 0
- || strcmp(fileName, kDefaultLocale) == 0) {
- if (out) {
- out->language[0] = 0;
- out->language[1] = 0;
- out->country[0] = 0;
- out->country[1] = 0;
- }
- return true;
- }
-
- if (strlen(fileName) == 2 && isalpha(fileName[0]) && isalpha(fileName[1])) {
- if (out) {
- out->language[0] = fileName[0];
- out->language[1] = fileName[1];
- out->country[0] = 0;
- out->country[1] = 0;
- }
- return true;
- }
-
- if (strlen(fileName) == 5 &&
- isalpha(fileName[0]) &&
- isalpha(fileName[1]) &&
- fileName[2] == '-' &&
- isalpha(fileName[3]) &&
- isalpha(fileName[4])) {
- if (out) {
- out->language[0] = fileName[0];
- out->language[1] = fileName[1];
- out->country[0] = fileName[3];
- out->country[1] = fileName[4];
- }
- return true;
- }
-
- return false;
-}
-
bool AaptGroupEntry::getLayoutDirectionName(const char* name, ResTable_config* out)
{
if (strcmp(name, kWildcardName) == 0) {
@@ -1496,18 +1721,18 @@
return v;
}
-const ResTable_config& AaptGroupEntry::toParams() const
+const ResTable_config AaptGroupEntry::toParams() const
{
if (!mParamsChanged) {
return mParams;
}
mParamsChanged = false;
- ResTable_config& params(mParams);
- memset(¶ms, 0, sizeof(params));
+ ResTable_config& params = mParams;
+ memset(¶ms, 0, sizeof(ResTable_config));
getMccName(mcc.string(), ¶ms);
getMncName(mnc.string(), ¶ms);
- getLocaleName(locale.string(), ¶ms);
+ locale.writeTo(¶ms);
getLayoutDirectionName(layoutDirection.string(), ¶ms);
getSmallestScreenWidthDpName(smallestScreenWidthDp.string(), ¶ms);
getScreenWidthDpName(screenWidthDp.string(), ¶ms);
@@ -1992,7 +2217,9 @@
AaptAssets::AaptAssets()
: AaptDir(String8(), String8()),
- mChanged(false), mHaveIncludedAssets(false), mRes(NULL)
+ mHavePrivateSymbols(false),
+ mChanged(false), mHaveIncludedAssets(false),
+ mRes(NULL)
{
}
@@ -2505,9 +2732,9 @@
// If our preferred density is hdpi but we only have mdpi and xhdpi resources, we
// pick xhdpi.
uint32_t preferredDensity = 0;
- const SortedVector<uint32_t>* preferredConfigs = prefFilter.configsForAxis(AXIS_DENSITY);
+ const SortedVector<AxisValue>* preferredConfigs = prefFilter.configsForAxis(AXIS_DENSITY);
if (preferredConfigs != NULL && preferredConfigs->size() > 0) {
- preferredDensity = (*preferredConfigs)[0];
+ preferredDensity = (*preferredConfigs)[0].intValue;
}
// Now deal with preferred configurations.
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index 9cc9007..336d08b 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -13,7 +13,6 @@
#include <utils/RefBase.h>
#include <utils/SortedVector.h>
#include <utils/String8.h>
-#include <utils/String8.h>
#include <utils/Vector.h>
#include "ZipFile.h"
@@ -34,8 +33,7 @@
AXIS_NONE = 0,
AXIS_MCC = 1,
AXIS_MNC,
- AXIS_LANGUAGE,
- AXIS_REGION,
+ AXIS_LOCALE,
AXIS_SCREENLAYOUTSIZE,
AXIS_SCREENLAYOUTLONG,
AXIS_ORIENTATION,
@@ -58,6 +56,73 @@
AXIS_END = AXIS_VERSION,
};
+struct AaptLocaleValue {
+ char language[4];
+ char region[4];
+ char script[4];
+ char variant[8];
+
+ AaptLocaleValue() {
+ memset(this, 0, sizeof(AaptLocaleValue));
+ }
+
+ // Initialize this AaptLocaleValue from a config string.
+ bool initFromFilterString(const String8& config);
+
+ int initFromDirName(const Vector<String8>& parts, const int startIndex);
+
+ // Initialize this AaptLocaleValue from a ResTable_config.
+ void initFromResTable(const ResTable_config& config);
+
+ void writeTo(ResTable_config* out) const;
+
+ String8 toDirName() const;
+
+ int compare(const AaptLocaleValue& other) const {
+ return memcmp(this, &other, sizeof(AaptLocaleValue));
+ }
+
+ static void splitAndLowerCase(const char* const chars, Vector<String8>* parts,
+ const char separator);
+
+ inline bool operator<(const AaptLocaleValue& o) const { return compare(o) < 0; }
+ inline bool operator<=(const AaptLocaleValue& o) const { return compare(o) <= 0; }
+ inline bool operator==(const AaptLocaleValue& o) const { return compare(o) == 0; }
+ inline bool operator!=(const AaptLocaleValue& o) const { return compare(o) != 0; }
+ inline bool operator>=(const AaptLocaleValue& o) const { return compare(o) >= 0; }
+ inline bool operator>(const AaptLocaleValue& o) const { return compare(o) > 0; }
+private:
+ void setLanguage(const char* language);
+ void setRegion(const char* language);
+ void setScript(const char* script);
+ void setVariant(const char* variant);
+};
+
+struct AxisValue {
+ // Used for all axes except AXIS_LOCALE, which is represented
+ // as a AaptLocaleValue value.
+ int intValue;
+ AaptLocaleValue localeValue;
+
+ AxisValue() : intValue(0) {
+ }
+
+ inline int compare(const AxisValue &other) const {
+ if (intValue != other.intValue) {
+ return intValue - other.intValue;
+ }
+
+ return localeValue.compare(other.localeValue);
+ }
+
+ inline bool operator<(const AxisValue& o) const { return compare(o) < 0; }
+ inline bool operator<=(const AxisValue& o) const { return compare(o) <= 0; }
+ inline bool operator==(const AxisValue& o) const { return compare(o) == 0; }
+ inline bool operator!=(const AxisValue& o) const { return compare(o) != 0; }
+ inline bool operator>=(const AxisValue& o) const { return compare(o) >= 0; }
+ inline bool operator>(const AxisValue& o) const { return compare(o) > 0; }
+};
+
/**
* This structure contains a specific variation of a single file out
* of all the variations it can have that we can have.
@@ -65,22 +130,38 @@
struct AaptGroupEntry
{
public:
- AaptGroupEntry() : mParamsChanged(true) { }
- AaptGroupEntry(const String8& _locale, const String8& _vendor)
- : locale(_locale), vendor(_vendor), mParamsChanged(true) { }
+ AaptGroupEntry() : mParamsChanged(true) {
+ memset(&mParams, 0, sizeof(ResTable_config));
+ }
bool initFromDirName(const char* dir, String8* resType);
- static status_t parseNamePart(const String8& part, int* axis, uint32_t* value);
+ static bool parseFilterNamePart(const String8& part, int* axis, AxisValue* value);
- static uint32_t getConfigValueForAxis(const ResTable_config& config, int axis);
+ static AxisValue getConfigValueForAxis(const ResTable_config& config, int axis);
static bool configSameExcept(const ResTable_config& config,
const ResTable_config& otherConfig, int axis);
+ int compare(const AaptGroupEntry& o) const;
+
+ const ResTable_config toParams() const;
+
+ inline bool operator<(const AaptGroupEntry& o) const { return compare(o) < 0; }
+ inline bool operator<=(const AaptGroupEntry& o) const { return compare(o) <= 0; }
+ inline bool operator==(const AaptGroupEntry& o) const { return compare(o) == 0; }
+ inline bool operator!=(const AaptGroupEntry& o) const { return compare(o) != 0; }
+ inline bool operator>=(const AaptGroupEntry& o) const { return compare(o) >= 0; }
+ inline bool operator>(const AaptGroupEntry& o) const { return compare(o) > 0; }
+
+ String8 toString() const;
+ String8 toDirName(const String8& resType) const;
+
+ const String8& getVersionString() const { return version; }
+
+private:
static bool getMccName(const char* name, ResTable_config* out = NULL);
static bool getMncName(const char* name, ResTable_config* out = NULL);
- static bool getLocaleName(const char* name, ResTable_config* out = NULL);
static bool getScreenLayoutSizeName(const char* name, ResTable_config* out = NULL);
static bool getScreenLayoutLongName(const char* name, ResTable_config* out = NULL);
static bool getOrientationName(const char* name, ResTable_config* out = NULL);
@@ -99,26 +180,9 @@
static bool getLayoutDirectionName(const char* name, ResTable_config* out = NULL);
static bool getVersionName(const char* name, ResTable_config* out = NULL);
- int compare(const AaptGroupEntry& o) const;
-
- const ResTable_config& toParams() const;
-
- inline bool operator<(const AaptGroupEntry& o) const { return compare(o) < 0; }
- inline bool operator<=(const AaptGroupEntry& o) const { return compare(o) <= 0; }
- inline bool operator==(const AaptGroupEntry& o) const { return compare(o) == 0; }
- inline bool operator!=(const AaptGroupEntry& o) const { return compare(o) != 0; }
- inline bool operator>=(const AaptGroupEntry& o) const { return compare(o) >= 0; }
- inline bool operator>(const AaptGroupEntry& o) const { return compare(o) > 0; }
-
- String8 toString() const;
- String8 toDirName(const String8& resType) const;
-
- const String8& getVersionString() const { return version; }
-
-private:
String8 mcc;
String8 mnc;
- String8 locale;
+ AaptLocaleValue locale;
String8 vendor;
String8 smallestScreenWidthDp;
String8 screenWidthDp;
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 48e3125..8e856b7 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -600,6 +600,7 @@
// the API version because key resources like icons will have an implicit
// version if they are using newer config types like density.
ResTable_config config;
+ memset(&config, 0, sizeof(ResTable_config));
config.language[0] = 'e';
config.language[1] = 'n';
config.country[0] = 'U';
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index a390e42..c923bc2 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -80,6 +80,7 @@
ResourceDirIterator(const sp<ResourceTypeSet>& set, const String8& resType)
: mResType(resType), mSet(set), mSetPos(0), mGroupPos(0)
{
+ memset(&mParams, 0, sizeof(ResTable_config));
}
inline const sp<AaptGroup>& getGroup() const { return mGroup; }
diff --git a/tools/aapt/ResourceFilter.cpp b/tools/aapt/ResourceFilter.cpp
index 8cfd2a5..e8a2be4 100644
--- a/tools/aapt/ResourceFilter.cpp
+++ b/tools/aapt/ResourceFilter.cpp
@@ -28,8 +28,8 @@
mContainsPseudo = true;
}
int axis;
- uint32_t value;
- if (AaptGroupEntry::parseNamePart(part, &axis, &value)) {
+ AxisValue value;
+ if (!AaptGroupEntry::parseFilterNamePart(part, &axis, &value)) {
fprintf(stderr, "Invalid configuration: %s\n", arg);
fprintf(stderr, " ");
for (int i=0; i<p-arg; i++) {
@@ -44,15 +44,20 @@
ssize_t index = mData.indexOfKey(axis);
if (index < 0) {
- mData.add(axis, SortedVector<uint32_t>());
+ mData.add(axis, SortedVector<AxisValue>());
}
- SortedVector<uint32_t>& sv = mData.editValueFor(axis);
+ SortedVector<AxisValue>& sv = mData.editValueFor(axis);
sv.add(value);
- // if it's a locale with a region, also match an unmodified locale of the
- // same language
- if (axis == AXIS_LANGUAGE) {
- if (value & 0xffff0000) {
- sv.add(value & 0x0000ffff);
+
+ // If it's a locale with a region, script or variant, we should also match an
+ // unmodified locale of the same language
+ if (axis == AXIS_LOCALE) {
+ if (value.localeValue.region[0] || value.localeValue.script[0] ||
+ value.localeValue.variant[0]) {
+ AxisValue copy;
+ memcpy(copy.localeValue.language, value.localeValue.language,
+ sizeof(value.localeValue.language));
+ sv.add(copy);
}
}
p = q;
@@ -70,9 +75,9 @@
}
bool
-ResourceFilter::match(int axis, uint32_t value) const
+ResourceFilter::match(int axis, const AxisValue& value) const
{
- if (value == 0) {
+ if (value.intValue == 0 && (value.localeValue.language[0] == 0)) {
// they didn't specify anything so take everything
return true;
}
@@ -81,7 +86,7 @@
// we didn't request anything on this axis so take everything
return true;
}
- const SortedVector<uint32_t>& sv = mData.valueAt(index);
+ const SortedVector<AxisValue>& sv = mData.valueAt(index);
return sv.indexOf(value) >= 0;
}
@@ -102,7 +107,7 @@
return true;
}
-const SortedVector<uint32_t>* ResourceFilter::configsForAxis(int axis) const
+const SortedVector<AxisValue>* ResourceFilter::configsForAxis(int axis) const
{
ssize_t index = mData.indexOfKey(axis);
if (index < 0) {
diff --git a/tools/aapt/ResourceFilter.h b/tools/aapt/ResourceFilter.h
index 647b7bb..0d127ba 100644
--- a/tools/aapt/ResourceFilter.h
+++ b/tools/aapt/ResourceFilter.h
@@ -19,14 +19,15 @@
ResourceFilter() : mData(), mContainsPseudo(false) {}
status_t parse(const char* arg);
bool isEmpty() const;
- bool match(int axis, uint32_t value) const;
bool match(int axis, const ResTable_config& config) const;
bool match(const ResTable_config& config) const;
- const SortedVector<uint32_t>* configsForAxis(int axis) const;
+ const SortedVector<AxisValue>* configsForAxis(int axis) const;
inline bool containsPseudo() const { return mContainsPseudo; }
private:
- KeyedVector<int,SortedVector<uint32_t> > mData;
+ bool match(int axis, const AxisValue& value) const;
+
+ KeyedVector<int,SortedVector<AxisValue> > mData;
bool mContainsPseudo;
};
diff --git a/tools/aapt/ResourceIdCache.h b/tools/aapt/ResourceIdCache.h
index 65f7781..e6bcda2 100644
--- a/tools/aapt/ResourceIdCache.h
+++ b/tools/aapt/ResourceIdCache.h
@@ -7,7 +7,6 @@
#define RESOURCE_ID_CACHE_H
namespace android {
-class android::String16;
class ResourceIdCache {
public:
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 02a74b1..aff0088 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -1292,8 +1292,8 @@
curIsStyled = true;
} else if (strcmp16(block.getElementName(&len), string16.string()) == 0) {
// Note the existence and locale of every string we process
- char rawLocale[16];
- curParams.getLocale(rawLocale);
+ char rawLocale[RESTABLE_MAX_LOCALE_LEN];
+ curParams.getBcp47Locale(rawLocale);
String8 locale(rawLocale);
String16 name;
String16 translatable;
diff --git a/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java b/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java
index e1b3f92..802cf1c 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java
@@ -28,7 +28,6 @@
import com.ibm.icu.lang.UScriptRun;
import android.graphics.Paint_Delegate.FontInfo;
-import android.graphics.RectF;;
/**
* Render the text by breaking it into various scripts and using the right font for each script.
@@ -52,11 +51,12 @@
}
}
- private Graphics2D graphics;
- private Paint_Delegate paint;
- private char[] text;
+ private Graphics2D mGraphics;
+ private Paint_Delegate mPaint;
+ private char[] mText;
// Bounds of the text drawn so far.
- private RectF bounds;
+ private RectF mBounds;
+ private float mBaseline;
/**
* @param graphics May be null.
@@ -65,9 +65,9 @@
*/
/* package */ BidiRenderer(Graphics2D graphics, Paint_Delegate paint, char[] text) {
assert (paint != null);
- this.graphics = graphics;
- this.paint = paint;
- this.text = text;
+ mGraphics = graphics;
+ mPaint = paint;
+ mText = text;
}
/**
@@ -81,25 +81,26 @@
* @param advances If not null, then advances for each character to be rendered are returned
* here.
* @param advancesIndex index into advances from where the advances need to be filled.
- * @param draw If true and {@link graphics} is not null, draw the rendered text on the graphics
+ * @param draw If true and {@code graphics} is not null, draw the rendered text on the graphics
* at the given co-ordinates
* @param x The x-coordinate of the left edge of where the text should be drawn on the given
* graphics.
- * @param y The y-coordinate at which to draw the text on the given graphics.
+ * @param y The y-coordinate at which to draw the text on the given mGraphics.
* @return A rectangle specifying the bounds of the text drawn.
*/
- /* package */ RectF renderText(int start, int limit, boolean isRtl, float advances[],
+ /* package */ RectF renderText(int start, int limit, boolean isRtl, float[] advances,
int advancesIndex, boolean draw, float x, float y) {
// We break the text into scripts and then select font based on it and then render each of
// the script runs.
- bounds = new RectF(x, y, x, y);
- for (ScriptRun run : getScriptRuns(text, start, limit, isRtl, paint.getFonts())) {
+ mBounds = new RectF(x, y, x, y);
+ mBaseline = y;
+ for (ScriptRun run : getScriptRuns(mText, start, limit, isRtl, mPaint.getFonts())) {
int flag = Font.LAYOUT_NO_LIMIT_CONTEXT | Font.LAYOUT_NO_START_CONTEXT;
flag |= isRtl ? Font.LAYOUT_RIGHT_TO_LEFT : Font.LAYOUT_LEFT_TO_RIGHT;
renderScript(run.start, run.limit, run.font, flag, advances, advancesIndex, draw);
advancesIndex += run.limit - run.start;
}
- return bounds;
+ return mBounds;
}
/**
@@ -108,20 +109,22 @@
* be drawn using the preferred font.
*/
private void renderScript(int start, int limit, FontInfo preferredFont, int flag,
- float advances[], int advancesIndex, boolean draw) {
- List<FontInfo> fonts = paint.getFonts();
+ float[] advances, int advancesIndex, boolean draw) {
+ List<FontInfo> fonts = mPaint.getFonts();
if (fonts == null || preferredFont == null) {
return;
}
while (start < limit) {
boolean foundFont = false;
- int canDisplayUpTo = preferredFont.mFont.canDisplayUpTo(text, start, limit);
+ int canDisplayUpTo = preferredFont.mFont.canDisplayUpTo(mText, start, limit);
if (canDisplayUpTo == -1) {
// We can draw all characters in the text.
render(start, limit, preferredFont, flag, advances, advancesIndex, draw);
return;
- } else if (canDisplayUpTo > start) { // can draw something
+ }
+ if (canDisplayUpTo > start) {
+ // We can draw something.
render(start, canDisplayUpTo, preferredFont, flag, advances, advancesIndex, draw);
advancesIndex += canDisplayUpTo - start;
start = canDisplayUpTo;
@@ -129,9 +132,9 @@
// The current character cannot be drawn with the preferred font. Cycle through all the
// fonts to check which one can draw it.
- int charCount = Character.isHighSurrogate(text[start]) ? 2 : 1;
+ int charCount = Character.isHighSurrogate(mText[start]) ? 2 : 1;
for (FontInfo font : fonts) {
- canDisplayUpTo = font.mFont.canDisplayUpTo(text, start, start + charCount);
+ canDisplayUpTo = font.mFont.canDisplayUpTo(mText, start, start + charCount);
if (canDisplayUpTo == -1) {
render(start, start+charCount, font, flag, advances, advancesIndex, draw);
start += charCount;
@@ -154,41 +157,45 @@
}
/**
- * Render the text with the given font to the right of the bounds passed.
+ * Renders the text to the right of the bounds with the given font.
+ * @param font The font to render the text with.
*/
- private void render(int start, int limit, FontInfo font, int flag, float advances[],
+ private void render(int start, int limit, FontInfo font, int flag, float[] advances,
int advancesIndex, boolean draw) {
// Since the metrics don't have anti-aliasing set, we create a new FontRenderContext with
// the anti-aliasing set.
FontRenderContext f = font.mMetrics.getFontRenderContext();
- FontRenderContext frc = new FontRenderContext(f.getTransform(), paint.isAntiAliased(),
+ FontRenderContext frc = new FontRenderContext(f.getTransform(), mPaint.isAntiAliased(),
f.usesFractionalMetrics());
- GlyphVector gv = font.mFont.layoutGlyphVector(frc, text, start, limit, flag);
+ GlyphVector gv = font.mFont.layoutGlyphVector(frc, mText, start, limit, flag);
int ng = gv.getNumGlyphs();
int[] ci = gv.getGlyphCharIndices(0, ng, null);
- for (int i = 0; i < ng; i++) {
- float adv = gv.getGlyphMetrics(i).getAdvanceX();
- if (advances != null) {
+ if (advances != null) {
+ for (int i = 0; i < ng; i++) {
int adv_idx = advancesIndex + ci[i];
- advances[adv_idx] += adv;
+ advances[adv_idx] += gv.getGlyphMetrics(i).getAdvanceX();
}
}
- if (draw && graphics != null) {
- graphics.drawGlyphVector(gv, bounds.right, bounds.bottom);
+ if (draw && mGraphics != null) {
+ mGraphics.drawGlyphVector(gv, mBounds.right, mBaseline);
}
- Rectangle2D awtBounds = gv.getVisualBounds();
- RectF visualBounds = awtRectToAndroidRect(awtBounds, bounds.right, bounds.bottom);
- // If the width of the bounds is zero, no text has been drawn yet. Hence, use the
- // coordinates from the bounds as an offset only.
- if (Math.abs(bounds.right - bounds.left) == 0) {
- bounds = visualBounds;
+
+ // Update the bounds.
+ Rectangle2D awtBounds = gv.getLogicalBounds();
+ RectF bounds = awtRectToAndroidRect(awtBounds, mBounds.right, mBaseline);
+ // If the width of the bounds is zero, no text had been drawn earlier. Hence, use the
+ // coordinates from the bounds as an offset.
+ if (Math.abs(mBounds.right - mBounds.left) == 0) {
+ mBounds = bounds;
} else {
- bounds.union(visualBounds);
+ mBounds.union(bounds);
}
}
- private RectF awtRectToAndroidRect(Rectangle2D awtRec, float offsetX, float offsetY) {
+ // --- Static helper methods ---
+
+ private static RectF awtRectToAndroidRect(Rectangle2D awtRec, float offsetX, float offsetY) {
float left = (float) awtRec.getX();
float top = (float) awtRec.getY();
float right = (float) (left + awtRec.getWidth());
@@ -198,8 +205,6 @@
return androidRect;
}
- // --- Static helper methods ---
-
/* package */ static List<ScriptRun> getScriptRuns(char[] text, int start, int limit,
boolean isRtl, List<FontInfo> fonts) {
LinkedList<ScriptRun> scriptRuns = new LinkedList<ScriptRun>();