Merge "Remove deprecated and unused entryEvicted method." into honeycomb-mr1
diff --git a/api/current.xml b/api/current.xml
index 416516f..4996e6a 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -28850,7 +28850,7 @@
deprecated="not deprecated"
visibility="public"
>
-<method name="completedDownload"
+<method name="addCompletedDownload"
return="long"
abstract="false"
native="false"
@@ -118085,6 +118085,497 @@
</field>
</class>
</package>
+<package name="android.net.rtp"
+>
+<class name="AudioCodec"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getCodec"
+ return="android.net.rtp.AudioCodec"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="rtpmap" type="java.lang.String">
+</parameter>
+<parameter name="fmtp" type="java.lang.String">
+</parameter>
+</method>
+<method name="getCodecs"
+ return="android.net.rtp.AudioCodec[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<field name="AMR"
+ type="android.net.rtp.AudioCodec"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GSM"
+ type="android.net.rtp.AudioCodec"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GSM_EFR"
+ type="android.net.rtp.AudioCodec"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PCMA"
+ type="android.net.rtp.AudioCodec"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PCMU"
+ type="android.net.rtp.AudioCodec"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fmtp"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="rtpmap"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="type"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="AudioGroup"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="AudioGroup"
+ type="android.net.rtp.AudioGroup"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="clear"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMode"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getStreams"
+ return="android.net.rtp.AudioStream[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="sendDtmf"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="int">
+</parameter>
+</method>
+<method name="setMode"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="int">
+</parameter>
+</method>
+<field name="MODE_ECHO_SUPPRESSION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MODE_MUTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MODE_NORMAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MODE_ON_HOLD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="AudioStream"
+ extends="android.net.rtp.RtpStream"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="AudioStream"
+ type="android.net.rtp.AudioStream"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="address" type="java.net.InetAddress">
+</parameter>
+<exception name="SocketException" type="java.net.SocketException">
+</exception>
+</constructor>
+<method name="getCodec"
+ return="android.net.rtp.AudioCodec"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDtmfType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getGroup"
+ return="android.net.rtp.AudioGroup"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isBusy"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="join"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="group" type="android.net.rtp.AudioGroup">
+</parameter>
+</method>
+<method name="setCodec"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="codec" type="android.net.rtp.AudioCodec">
+</parameter>
+</method>
+<method name="setDtmfType"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="int">
+</parameter>
+</method>
+</class>
+<class name="RtpStream"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="associate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="address" type="java.net.InetAddress">
+</parameter>
+<parameter name="port" type="int">
+</parameter>
+</method>
+<method name="getLocalAddress"
+ return="java.net.InetAddress"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getLocalPort"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMode"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getRemoteAddress"
+ return="java.net.InetAddress"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getRemotePort"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isBusy"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="release"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setMode"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mode" type="int">
+</parameter>
+</method>
+<field name="MODE_NORMAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MODE_RECEIVE_ONLY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MODE_SEND_ONLY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+</package>
<package name="android.net.sip"
>
<class name="SipAudioCall"
@@ -218100,6 +218591,28 @@
visibility="public"
>
</field>
+<field name="AXIS_BRAKE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="23"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AXIS_GAS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="22"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="AXIS_GENERIC_1"
type="int"
transient="false"
@@ -218353,6 +218866,17 @@
visibility="public"
>
</field>
+<field name="AXIS_RUDDER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="20"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="AXIS_RX"
type="int"
transient="false"
@@ -218397,6 +218921,17 @@
visibility="public"
>
</field>
+<field name="AXIS_THROTTLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="19"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="AXIS_TOOL_MAJOR"
type="int"
transient="false"
@@ -218452,6 +218987,17 @@
visibility="public"
>
</field>
+<field name="AXIS_WHEEL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="21"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="AXIS_X"
type="int"
transient="false"
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index d04fa57..b88e5cf 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -376,8 +376,8 @@
/**
* This download shows in the notifications after completion ONLY.
* It is usuable only with
- * {@link DownloadManager#completedDownload(String, String, boolean, String,
- * String, long, boolean)}.
+ * {@link DownloadManager#addCompletedDownload(String, String,
+ * boolean, String, String, long, boolean)}.
*/
public static final int VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION = 3;
@@ -1111,7 +1111,7 @@
* @return an ID for the download entry added to the downloads app, unique across the system
* This ID is used to make future calls related to this download.
*/
- public long completedDownload(String title, String description,
+ public long addCompletedDownload(String title, String description,
boolean isMediaScannerScannable, String mimeType, String path, long length,
boolean showNotification) {
// make sure the input args are non-null/non-zero
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 9a6a274..fa5479b 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -245,11 +245,12 @@
private static native void nDestroyDisplayList(int displayList);
@Override
- public boolean drawDisplayList(DisplayList displayList) {
- return nDrawDisplayList(mRenderer, ((GLES20DisplayList) displayList).mNativeDisplayList);
+ public boolean drawDisplayList(DisplayList displayList, Rect dirty) {
+ return nDrawDisplayList(mRenderer,
+ ((GLES20DisplayList) displayList).mNativeDisplayList, dirty);
}
- private static native boolean nDrawDisplayList(int renderer, int displayList);
+ private static native boolean nDrawDisplayList(int renderer, int displayList, Rect dirty);
///////////////////////////////////////////////////////////////////////////
// Hardware layer
diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java
index 262eb81..aeff31f 100644
--- a/core/java/android/view/GLES20DisplayList.java
+++ b/core/java/android/view/GLES20DisplayList.java
@@ -40,13 +40,6 @@
hostView = new WeakReference<View>(view);
}
- public void invalidateView() {
- View v = hostView.get();
- if (v != null) {
- v.invalidate();
- }
- }
-
@Override
HardwareCanvas start() {
if (mStarted) {
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index e6fecc8..cb1003a 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -53,8 +53,13 @@
* Draws the specified display list onto this canvas.
*
* @param displayList The display list to replay.
+ * @param dirty The dirty region to redraw in the next pass, matters only
+ * if this method returns true, can be null.
+ *
+ * @return True if the content of the display list requires another
+ * drawing pass (invalidate()), false otherwise
*/
- abstract boolean drawDisplayList(DisplayList displayList);
+ abstract boolean drawDisplayList(DisplayList displayList, Rect dirty);
/**
* Draws the specified layer onto this canvas.
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index b53aa21..c078c08 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -269,7 +269,7 @@
static EGLDisplay sEglDisplay;
static EGLConfig sEglConfig;
- private static Thread sEglThread;
+ private static Thread sEglThread;
EGLSurface mEglSurface;
@@ -284,6 +284,8 @@
final boolean mTranslucent;
private boolean mDestroyed;
+
+ private final Rect mRedrawClip = new Rect();
GlRenderer(int glVersion, boolean translucent) {
mGlVersion = glVersion;
@@ -606,8 +608,13 @@
DisplayList displayList = view.getDisplayList();
if (displayList != null) {
- if (canvas.drawDisplayList(displayList)) {
- view.invalidate();
+ if (canvas.drawDisplayList(displayList, mRedrawClip)) {
+ if (mRedrawClip.isEmpty()) {
+ view.invalidate();
+ } else {
+ view.getParent().invalidateChild(view, mRedrawClip);
+ }
+ mRedrawClip.setEmpty();
}
} else {
// Shouldn't reach here
@@ -646,8 +653,8 @@
private int checkCurrent() {
// TODO: Don't check the current context when we have one per UI thread
// TODO: Use a threadlocal flag to know whether the surface has changed
- if (sEgl.eglGetCurrentContext() != sEglContext ||
- sEgl.eglGetCurrentSurface(EGL10.EGL_DRAW) != mEglSurface) {
+ if (!sEglContext.equals(sEgl.eglGetCurrentContext()) ||
+ !mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) {
if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, sEglContext)) {
fallback(true);
Log.e(LOG_TAG, "eglMakeCurrent failed " +
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 076f712..3c39149 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -675,6 +675,87 @@
public static final int AXIS_RTRIGGER = 18;
/**
+ * Constant used to identify the Throttle axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a joystick, reports the absolute position of the throttle control.
+ * The value is normalized to a range from 0.0 (fully open) to 1.0 (fully closed).
+ * </ul>
+ * </p>
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_THROTTLE = 19;
+
+ /**
+ * Constant used to identify the Rudder axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a joystick, reports the absolute position of the rudder control.
+ * The value is normalized to a range from -1.0 (turn left) to 1.0 (turn right).
+ * </ul>
+ * </p>
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_RUDDER = 20;
+
+ /**
+ * Constant used to identify the Wheel axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a joystick, reports the absolute position of the steering wheel control.
+ * The value is normalized to a range from -1.0 (turn left) to 1.0 (turn right).
+ * </ul>
+ * </p>
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_WHEEL = 21;
+
+ /**
+ * Constant used to identify the Gas axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a joystick, reports the absolute position of the gas (accelerator) control.
+ * The value is normalized to a range from 0.0 (no acceleration)
+ * to 1.0 (maximum acceleration).
+ * </ul>
+ * </p>
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_GAS = 22;
+
+ /**
+ * Constant used to identify the Brake axis of a motion event.
+ * <p>
+ * <ul>
+ * <li>For a joystick, reports the absolute position of the brake control.
+ * The value is normalized to a range from 0.0 (no braking) to 1.0 (maximum braking).
+ * </ul>
+ * </p>
+ *
+ * @see #getAxisValue(int, int)
+ * @see #getHistoricalAxisValue(int, int, int)
+ * @see MotionEvent.PointerCoords#getAxisValue(int)
+ * @see InputDevice#getMotionRange
+ */
+ public static final int AXIS_BRAKE = 23;
+
+ /**
* Constant used to identify the Generic 1 axis of a motion event.
* The interpretation of a generic axis is device-specific.
*
@@ -877,6 +958,11 @@
names.append(AXIS_HAT_Y, "AXIS_HAT_Y");
names.append(AXIS_LTRIGGER, "AXIS_LTRIGGER");
names.append(AXIS_RTRIGGER, "AXIS_RTRIGGER");
+ names.append(AXIS_THROTTLE, "AXIS_THROTTLE");
+ names.append(AXIS_RUDDER, "AXIS_RUDDER");
+ names.append(AXIS_WHEEL, "AXIS_WHEEL");
+ names.append(AXIS_GAS, "AXIS_GAS");
+ names.append(AXIS_BRAKE, "AXIS_BRAKE");
names.append(AXIS_GENERIC_1, "AXIS_GENERIC_1");
names.append(AXIS_GENERIC_2, "AXIS_GENERIC_2");
names.append(AXIS_GENERIC_3, "AXIS_GENERIC_3");
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index 0124151..5521e92 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.util.DisplayMetrics;
import android.util.FloatMath;
+import android.util.Log;
/**
* Detects transformation gestures involving more than one pointer ("multitouch")
@@ -36,6 +37,8 @@
* </ul>
*/
public class ScaleGestureDetector {
+ private static final String TAG = "ScaleGestureDetector";
+
/**
* The listener for receiving notifications when gestures occur.
* If you want to listen for all the different gestures then implement
@@ -170,6 +173,10 @@
final int action = event.getActionMasked();
boolean handled = true;
+ if (action == MotionEvent.ACTION_DOWN) {
+ reset(); // Start fresh
+ }
+
if (!mGestureInProgress) {
switch (action) {
case MotionEvent.ACTION_DOWN: {
@@ -197,6 +204,11 @@
int index1 = event.getActionIndex();
int index0 = event.findPointerIndex(mActiveId0);
mActiveId1 = event.getPointerId(index1);
+ if (index0 < 0 || index0 == index1) {
+ // Probably someone sending us a broken event stream.
+ index0 = findNewActiveIndex(event, index0 == index1 ? -1 : mActiveId1, index0);
+ mActiveId0 = event.getPointerId(index0);
+ }
mActive0MostRecent = false;
setContext(event);
@@ -315,6 +327,7 @@
final int index = event.findPointerIndex(actionId == mActiveId0 ?
mActiveId1 : mActiveId0);
mActiveId0 = event.getPointerId(index);
+
mActive0MostRecent = true;
mActiveId1 = -1;
mFocusX = event.getX(index);
@@ -338,6 +351,18 @@
mActiveId1 = event.getPointerId(event.getActionIndex());
mActive0MostRecent = false;
+ int index0 = event.findPointerIndex(mActiveId0);
+ if (index0 < 0 || mActiveId0 == mActiveId1) {
+ // Probably someone sending us a broken event stream.
+ Log.e(TAG, "Got " + MotionEvent.actionToString(action) +
+ " with bad state while a gesture was in progress. " +
+ "Did you forget to pass an event to " +
+ "ScaleGestureDetector#onTouchEvent?");
+ index0 = findNewActiveIndex(event,
+ mActiveId0 == mActiveId1 ? -1 : mActiveId1, index0);
+ mActiveId0 = event.getPointerId(index0);
+ }
+
setContext(event);
mGestureInProgress = mListener.onScaleBegin(this);
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 3153ac5..6ef680b 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2585,7 +2585,7 @@
}
} else {
child.mPrivateFlags &= ~DIRTY_MASK;
- ((HardwareCanvas) canvas).drawDisplayList(displayList);
+ ((HardwareCanvas) canvas).drawDisplayList(displayList, null);
}
}
} else if (cache != null) {
@@ -4275,11 +4275,10 @@
* does not exist within the group
*/
public View getChildAt(int index) {
- try {
- return mChildren[index];
- } catch (IndexOutOfBoundsException ex) {
+ if (index < 0 || index >= mChildrenCount) {
return null;
}
+ return mChildren[index];
}
/**
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 5468230..11908bb 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1606,13 +1606,9 @@
return;
} catch (IllegalArgumentException e) {
Log.e(TAG, "IllegalArgumentException locking surface", e);
- try {
- if (!sWindowSession.outOfMemory(mWindow)) {
- Slog.w(TAG, "No processes killed for memory; killing self");
- Process.killProcess(Process.myPid());
- }
- } catch (RemoteException ex) {
- }
+ // Don't assume this is due to out of memory, it could be
+ // something else, and if it is something else then we could
+ // kill stuff (or ourself) for no reason.
mLayoutRequested = true; // ask wm for a new surface next time.
return;
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 2d3157e9d..eb7269b 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -351,7 +351,8 @@
private ZoomManager mZoomManager;
- private Rect mGLRectViewport = new Rect();
+ private final Rect mGLRectViewport = new Rect();
+ private final Rect mViewRectViewport = new Rect();
private boolean mGLViewportEmpty = false;
/**
@@ -847,6 +848,9 @@
private Rect mScrollingLayerBounds = new Rect();
private boolean mSentAutoScrollMessage = false;
+ // used for serializing asynchronously handled touch events.
+ private final TouchEventQueue mTouchEventQueue = new TouchEventQueue();
+
// Used to notify listeners of a new picture.
private PictureListener mPictureListener;
/**
@@ -4112,7 +4116,7 @@
}
if (animateZoom) {
mZoomManager.animateZoom(canvas);
- } else {
+ } else if (!canvas.isHardwareAccelerated()) {
canvas.scale(mZoomManager.getScale(), mZoomManager.getScale());
}
@@ -4149,7 +4153,7 @@
if (canvas.isHardwareAccelerated()) {
int functor = nativeGetDrawGLFunction(mGLViewportEmpty ? null : mGLRectViewport,
- getScale(), extras);
+ mGLViewportEmpty ? null : mViewRectViewport, getScale(), extras);
((HardwareCanvas) canvas).callDrawGLFunction(functor);
} else {
DrawFilter df = null;
@@ -5081,6 +5085,8 @@
}
addAccessibilityApisToJavaScript();
+
+ mTouchEventQueue.reset();
}
@Override
@@ -5253,6 +5259,7 @@
// Then need to invert the Y axis, just for GL
View rootView = getRootView();
int rootViewHeight = rootView.getHeight();
+ mViewRectViewport.set(mGLRectViewport);
int savedWebViewBottom = mGLRectViewport.bottom;
mGLRectViewport.bottom = rootViewHeight - mGLRectViewport.top - getVisibleTitleHeight();
mGLRectViewport.top = rootViewHeight - savedWebViewBottom;
@@ -5260,7 +5267,8 @@
} else {
mGLViewportEmpty = true;
}
- nativeUpdateDrawGLFunction(mGLViewportEmpty ? null : mGLRectViewport);
+ nativeUpdateDrawGLFunction(mGLViewportEmpty ? null : mGLRectViewport,
+ mGLViewportEmpty ? null : mViewRectViewport);
}
/**
@@ -5432,34 +5440,17 @@
+ " numPointers=" + ev.getPointerCount());
}
- int action = ev.getActionMasked();
- if (ev.getPointerCount() > 1) { // Multi-touch
- mIsHandlingMultiTouch = true;
-
- // If WebKit already showed no interests in this sequence of events,
- // WebView handles them directly.
- if (mPreventDefault == PREVENT_DEFAULT_NO) {
- handleMultiTouchInWebView(ev);
- } else {
- passMultiTouchToWebKit(ev);
- }
- return true;
+ // If WebKit wasn't interested in this multitouch gesture, enqueue
+ // the event for handling directly rather than making the round trip
+ // to WebKit and back.
+ if (ev.getPointerCount() > 1 && mPreventDefault != PREVENT_DEFAULT_NO) {
+ passMultiTouchToWebKit(ev, mTouchEventQueue.nextTouchSequence());
} else {
- final ScaleGestureDetector detector = mZoomManager.getMultiTouchGestureDetector();
- if (detector != null) {
- // ScaleGestureDetector needs a consistent event stream to operate properly.
- // It won't take any action with fewer than two pointers, but it needs to
- // update internal bookkeeping state.
- detector.onTouchEvent(ev);
- }
+ mTouchEventQueue.enqueueTouchEvent(ev);
}
- // Skip ACTION_MOVE for single touch if it's still handling multi-touch.
- if (mIsHandlingMultiTouch && action == MotionEvent.ACTION_MOVE) {
- return false;
- }
-
- return handleTouchEventCommon(ev, action, Math.round(ev.getX()), Math.round(ev.getY()));
+ // Since all events are handled asynchronously, we always want the gesture stream.
+ return true;
}
/*
@@ -5579,6 +5570,7 @@
ted.mReprocess = mDeferTouchProcess;
ted.mNativeLayer = nativeScrollableLayer(
contentX, contentY, ted.mNativeLayerRect, null);
+ ted.mDontEnqueueResult = true;
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
if (mDeferTouchProcess) {
// still needs to set them for compute deltaX/Y
@@ -5625,6 +5617,7 @@
ted.mReprocess = mDeferTouchProcess;
ted.mNativeLayer = mScrollingLayer;
ted.mNativeLayerRect.set(mScrollingLayerRect);
+ ted.mDontEnqueueResult = true;
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
mLastSentTouchTime = eventTime;
if (mDeferTouchProcess) {
@@ -5806,6 +5799,7 @@
ted.mReprocess = mDeferTouchProcess;
ted.mNativeLayer = mScrollingLayer;
ted.mNativeLayerRect.set(mScrollingLayerRect);
+ ted.mDontEnqueueResult = true;
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
}
mLastTouchUpTime = eventTime;
@@ -5828,6 +5822,7 @@
ted.mNativeLayer = nativeScrollableLayer(
contentX, contentY,
ted.mNativeLayerRect, null);
+ ted.mDontEnqueueResult = true;
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
} else if (mPreventDefault != PREVENT_DEFAULT_YES){
mZoomManager.handleDoubleTap(mLastTouchX, mLastTouchY);
@@ -5952,7 +5947,7 @@
return true;
}
- private void passMultiTouchToWebKit(MotionEvent ev) {
+ private void passMultiTouchToWebKit(MotionEvent ev, long sequence) {
TouchEventData ted = new TouchEventData();
ted.mAction = ev.getActionMasked();
final int count = ev.getPointerCount();
@@ -5967,6 +5962,7 @@
ted.mMetaState = ev.getMetaState();
ted.mReprocess = true;
ted.mMotionEvent = MotionEvent.obtain(ev);
+ ted.mSequence = sequence;
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
cancelLongPress();
mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
@@ -6016,7 +6012,7 @@
if (action == MotionEvent.ACTION_POINTER_DOWN) {
cancelTouch();
action = MotionEvent.ACTION_DOWN;
- } else if (action == MotionEvent.ACTION_POINTER_UP) {
+ } else if (action == MotionEvent.ACTION_POINTER_UP && ev.getPointerCount() == 2) {
// set mLastTouchX/Y to the remaining point
mLastTouchX = Math.round(x);
mLastTouchY = Math.round(y);
@@ -6044,6 +6040,7 @@
ted.mAction = MotionEvent.ACTION_CANCEL;
ted.mNativeLayer = nativeScrollableLayer(
x, y, ted.mNativeLayerRect, null);
+ ted.mDontEnqueueResult = true;
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
mPreventDefault = PREVENT_DEFAULT_IGNORE;
}
@@ -7121,6 +7118,297 @@
return mWebViewCore;
}
+ /**
+ * Used only by TouchEventQueue to store pending touch events.
+ */
+ private static class QueuedTouch {
+ long mSequence;
+ MotionEvent mEvent; // Optional
+ TouchEventData mTed; // Optional
+
+ QueuedTouch mNext;
+
+ public QueuedTouch set(TouchEventData ted) {
+ mSequence = ted.mSequence;
+ mTed = ted;
+ mEvent = null;
+ mNext = null;
+ return this;
+ }
+
+ public QueuedTouch set(MotionEvent ev, long sequence) {
+ mEvent = MotionEvent.obtain(ev);
+ mSequence = sequence;
+ mTed = null;
+ mNext = null;
+ return this;
+ }
+
+ public QueuedTouch add(QueuedTouch other) {
+ if (other.mSequence < mSequence) {
+ other.mNext = this;
+ return other;
+ }
+
+ QueuedTouch insertAt = this;
+ while (insertAt.mNext != null && insertAt.mNext.mSequence < other.mSequence) {
+ insertAt = insertAt.mNext;
+ }
+ other.mNext = insertAt.mNext;
+ insertAt.mNext = other;
+ return this;
+ }
+ }
+
+ /**
+ * WebView handles touch events asynchronously since some events must be passed to WebKit
+ * for potentially slower processing. TouchEventQueue serializes touch events regardless
+ * of which path they take to ensure that no events are ever processed out of order
+ * by WebView.
+ */
+ private class TouchEventQueue {
+ private long mNextTouchSequence = Long.MIN_VALUE + 1;
+ private long mLastHandledTouchSequence = Long.MIN_VALUE;
+ private QueuedTouch mTouchEventQueue;
+ private QueuedTouch mQueuedTouchRecycleBin;
+ private int mQueuedTouchRecycleCount;
+ private static final int MAX_RECYCLED_QUEUED_TOUCH = 15;
+
+ private QueuedTouch obtainQueuedTouch() {
+ if (mQueuedTouchRecycleBin != null) {
+ QueuedTouch result = mQueuedTouchRecycleBin;
+ mQueuedTouchRecycleBin = result.mNext;
+ mQueuedTouchRecycleCount--;
+ return result;
+ }
+ return new QueuedTouch();
+ }
+
+ private void recycleQueuedTouch(QueuedTouch qd) {
+ if (mQueuedTouchRecycleCount < MAX_RECYCLED_QUEUED_TOUCH) {
+ qd.mNext = mQueuedTouchRecycleBin;
+ mQueuedTouchRecycleBin = qd;
+ mQueuedTouchRecycleCount++;
+ }
+ }
+
+ /**
+ * Reset the touch event queue. This will dump any pending events
+ * and reset the sequence numbering.
+ */
+ public void reset() {
+ mNextTouchSequence = Long.MIN_VALUE + 1;
+ mLastHandledTouchSequence = Long.MIN_VALUE;
+ while (mTouchEventQueue != null) {
+ QueuedTouch recycleMe = mTouchEventQueue;
+ mTouchEventQueue = mTouchEventQueue.mNext;
+ recycleQueuedTouch(recycleMe);
+ }
+ }
+
+ /**
+ * Return the next valid sequence number for tagging incoming touch events.
+ * @return The next touch event sequence number
+ */
+ public long nextTouchSequence() {
+ return mNextTouchSequence++;
+ }
+
+ /**
+ * Enqueue a touch event in the form of TouchEventData.
+ * The sequence number will be read from the mSequence field of the argument.
+ *
+ * If the touch event's sequence number is the next in line to be processed, it will
+ * be handled before this method returns. Any subsequent events that have already
+ * been queued will also be processed in their proper order.
+ *
+ * @param ted Touch data to be processed in order.
+ */
+ public void enqueueTouchEvent(TouchEventData ted) {
+ if (mLastHandledTouchSequence + 1 == ted.mSequence) {
+ handleQueuedTouchEventData(ted);
+
+ mLastHandledTouchSequence++;
+
+ // Do we have any more? Run them if so.
+ QueuedTouch qd = mTouchEventQueue;
+ while (qd != null && qd.mSequence == mLastHandledTouchSequence + 1) {
+ handleQueuedTouch(qd);
+ QueuedTouch recycleMe = qd;
+ qd = qd.mNext;
+ recycleQueuedTouch(recycleMe);
+ mLastHandledTouchSequence++;
+ }
+ mTouchEventQueue = qd;
+ } else {
+ QueuedTouch qd = obtainQueuedTouch().set(ted);
+ mTouchEventQueue = mTouchEventQueue == null ? qd : mTouchEventQueue.add(qd);
+ }
+ }
+
+ /**
+ * Enqueue a touch event in the form of a MotionEvent from the framework.
+ *
+ * If the touch event's sequence number is the next in line to be processed, it will
+ * be handled before this method returns. Any subsequent events that have already
+ * been queued will also be processed in their proper order.
+ *
+ * @param ev MotionEvent to be processed in order
+ */
+ public void enqueueTouchEvent(MotionEvent ev) {
+ final long sequence = nextTouchSequence();
+ if (mLastHandledTouchSequence + 1 == sequence) {
+ handleQueuedMotionEvent(ev);
+
+ mLastHandledTouchSequence++;
+
+ // Do we have any more? Run them if so.
+ QueuedTouch qd = mTouchEventQueue;
+ while (qd != null && qd.mSequence == mLastHandledTouchSequence + 1) {
+ handleQueuedTouch(qd);
+ QueuedTouch recycleMe = qd;
+ qd = qd.mNext;
+ recycleQueuedTouch(recycleMe);
+ mLastHandledTouchSequence++;
+ }
+ mTouchEventQueue = qd;
+ } else {
+ QueuedTouch qd = obtainQueuedTouch().set(ev, sequence);
+ mTouchEventQueue = mTouchEventQueue == null ? qd : mTouchEventQueue.add(qd);
+ }
+ }
+
+ private void handleQueuedTouch(QueuedTouch qt) {
+ if (qt.mTed != null) {
+ handleQueuedTouchEventData(qt.mTed);
+ } else {
+ handleQueuedMotionEvent(qt.mEvent);
+ qt.mEvent.recycle();
+ }
+ }
+
+ private void handleQueuedMotionEvent(MotionEvent ev) {
+ int action = ev.getActionMasked();
+ if (ev.getPointerCount() > 1) { // Multi-touch
+ mIsHandlingMultiTouch = true;
+
+ handleMultiTouchInWebView(ev);
+ } else {
+ final ScaleGestureDetector detector = mZoomManager.getMultiTouchGestureDetector();
+ if (detector != null) {
+ // ScaleGestureDetector needs a consistent event stream to operate properly.
+ // It won't take any action with fewer than two pointers, but it needs to
+ // update internal bookkeeping state.
+ detector.onTouchEvent(ev);
+ }
+
+ handleTouchEventCommon(ev, action, Math.round(ev.getX()), Math.round(ev.getY()));
+ }
+ }
+
+ private void handleQueuedTouchEventData(TouchEventData ted) {
+ if (!ted.mReprocess) {
+ if (ted.mAction == MotionEvent.ACTION_DOWN
+ && mPreventDefault == PREVENT_DEFAULT_MAYBE_YES) {
+ // if prevent default is called from WebCore, UI
+ // will not handle the rest of the touch events any
+ // more.
+ mPreventDefault = ted.mNativeResult ? PREVENT_DEFAULT_YES
+ : PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN;
+ } else if (ted.mAction == MotionEvent.ACTION_MOVE
+ && mPreventDefault == PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN) {
+ // the return for the first ACTION_MOVE will decide
+ // whether UI will handle touch or not. Currently no
+ // support for alternating prevent default
+ mPreventDefault = ted.mNativeResult ? PREVENT_DEFAULT_YES
+ : PREVENT_DEFAULT_NO;
+ }
+ if (mPreventDefault == PREVENT_DEFAULT_YES) {
+ mTouchHighlightRegion.setEmpty();
+ }
+ } else {
+ if (ted.mPoints.length > 1) { // multi-touch
+ if (ted.mAction == MotionEvent.ACTION_POINTER_UP &&
+ ted.mMotionEvent.getPointerCount() == 2) {
+ mIsHandlingMultiTouch = false;
+ }
+ if (!ted.mNativeResult) {
+ mPreventDefault = PREVENT_DEFAULT_NO;
+ handleMultiTouchInWebView(ted.mMotionEvent);
+ } else {
+ mPreventDefault = PREVENT_DEFAULT_YES;
+ }
+ return;
+ }
+
+ // prevent default is not called in WebCore, so the
+ // message needs to be reprocessed in UI
+ if (!ted.mNativeResult) {
+ // Following is for single touch.
+ switch (ted.mAction) {
+ case MotionEvent.ACTION_DOWN:
+ mLastDeferTouchX = contentToViewX(ted.mPoints[0].x)
+ - mScrollX;
+ mLastDeferTouchY = contentToViewY(ted.mPoints[0].y)
+ - mScrollY;
+ mDeferTouchMode = TOUCH_INIT_MODE;
+ break;
+ case MotionEvent.ACTION_MOVE: {
+ // no snapping in defer process
+ int x = contentToViewX(ted.mPoints[0].x) - mScrollX;
+ int y = contentToViewY(ted.mPoints[0].y) - mScrollY;
+ if (mDeferTouchMode != TOUCH_DRAG_MODE) {
+ mDeferTouchMode = TOUCH_DRAG_MODE;
+ mLastDeferTouchX = x;
+ mLastDeferTouchY = y;
+ startScrollingLayer(x, y);
+ startDrag();
+ }
+ int deltaX = pinLocX((int) (mScrollX
+ + mLastDeferTouchX - x))
+ - mScrollX;
+ int deltaY = pinLocY((int) (mScrollY
+ + mLastDeferTouchY - y))
+ - mScrollY;
+ doDrag(deltaX, deltaY);
+ if (deltaX != 0) mLastDeferTouchX = x;
+ if (deltaY != 0) mLastDeferTouchY = y;
+ break;
+ }
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ if (mDeferTouchMode == TOUCH_DRAG_MODE) {
+ // no fling in defer process
+ mScroller.springBack(mScrollX, mScrollY, 0,
+ computeMaxScrollX(), 0,
+ computeMaxScrollY());
+ invalidate();
+ WebViewCore.resumePriority();
+ WebViewCore.resumeUpdatePicture(mWebViewCore);
+ }
+ mDeferTouchMode = TOUCH_DONE_MODE;
+ break;
+ case WebViewCore.ACTION_DOUBLETAP:
+ // doDoubleTap() needs mLastTouchX/Y as anchor
+ mLastTouchX = contentToViewX(ted.mPoints[0].x) - mScrollX;
+ mLastTouchY = contentToViewY(ted.mPoints[0].y) - mScrollY;
+ mZoomManager.handleDoubleTap(mLastTouchX, mLastTouchY);
+ mDeferTouchMode = TOUCH_DONE_MODE;
+ break;
+ case WebViewCore.ACTION_LONGPRESS:
+ HitTestResult hitTest = getHitTestResult();
+ if (hitTest != null && hitTest.mType
+ != HitTestResult.UNKNOWN_TYPE) {
+ performLongClick();
+ }
+ mDeferTouchMode = TOUCH_DONE_MODE;
+ break;
+ }
+ }
+ }
+ }
+ }
+
//-------------------------------------------------------------------------
// Methods can be called from a separate thread, like WebViewCore
// If it needs to call the View system, it has to send message.
@@ -7236,6 +7524,7 @@
ted.mNativeLayer = nativeScrollableLayer(
ted.mPoints[0].x, ted.mPoints[0].y,
ted.mNativeLayerRect, null);
+ ted.mDontEnqueueResult = true;
mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
} else if (mPreventDefault != PREVENT_DEFAULT_YES) {
mTouchMode = TOUCH_DONE_MODE;
@@ -7450,105 +7739,9 @@
if (inFullScreenMode()) {
break;
}
- if (msg.obj == null) {
- if (msg.arg1 == MotionEvent.ACTION_DOWN
- && mPreventDefault == PREVENT_DEFAULT_MAYBE_YES) {
- // if prevent default is called from WebCore, UI
- // will not handle the rest of the touch events any
- // more.
- mPreventDefault = msg.arg2 == 1 ? PREVENT_DEFAULT_YES
- : PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN;
- } else if (msg.arg1 == MotionEvent.ACTION_MOVE
- && mPreventDefault == PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN) {
- // the return for the first ACTION_MOVE will decide
- // whether UI will handle touch or not. Currently no
- // support for alternating prevent default
- mPreventDefault = msg.arg2 == 1 ? PREVENT_DEFAULT_YES
- : PREVENT_DEFAULT_NO;
- }
- if (mPreventDefault == PREVENT_DEFAULT_YES) {
- mTouchHighlightRegion.setEmpty();
- }
- } else {
- TouchEventData ted = (TouchEventData) msg.obj;
-
- if (ted.mPoints.length > 1) { // multi-touch
- if (ted.mAction == MotionEvent.ACTION_POINTER_UP) {
- mIsHandlingMultiTouch = false;
- }
- if (msg.arg2 == 0) {
- mPreventDefault = PREVENT_DEFAULT_NO;
- handleMultiTouchInWebView(ted.mMotionEvent);
- } else {
- mPreventDefault = PREVENT_DEFAULT_YES;
- }
- break;
- }
-
- // prevent default is not called in WebCore, so the
- // message needs to be reprocessed in UI
- if (msg.arg2 == 0) {
- // Following is for single touch.
- switch (ted.mAction) {
- case MotionEvent.ACTION_DOWN:
- mLastDeferTouchX = contentToViewX(ted.mPoints[0].x)
- - mScrollX;
- mLastDeferTouchY = contentToViewY(ted.mPoints[0].y)
- - mScrollY;
- mDeferTouchMode = TOUCH_INIT_MODE;
- break;
- case MotionEvent.ACTION_MOVE: {
- // no snapping in defer process
- int x = contentToViewX(ted.mPoints[0].x) - mScrollX;
- int y = contentToViewY(ted.mPoints[0].y) - mScrollY;
- if (mDeferTouchMode != TOUCH_DRAG_MODE) {
- mDeferTouchMode = TOUCH_DRAG_MODE;
- mLastDeferTouchX = x;
- mLastDeferTouchY = y;
- startScrollingLayer(x, y);
- startDrag();
- }
- int deltaX = pinLocX((int) (mScrollX
- + mLastDeferTouchX - x))
- - mScrollX;
- int deltaY = pinLocY((int) (mScrollY
- + mLastDeferTouchY - y))
- - mScrollY;
- doDrag(deltaX, deltaY);
- if (deltaX != 0) mLastDeferTouchX = x;
- if (deltaY != 0) mLastDeferTouchY = y;
- break;
- }
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- if (mDeferTouchMode == TOUCH_DRAG_MODE) {
- // no fling in defer process
- mScroller.springBack(mScrollX, mScrollY, 0,
- computeMaxScrollX(), 0,
- computeMaxScrollY());
- invalidate();
- WebViewCore.resumePriority();
- WebViewCore.resumeUpdatePicture(mWebViewCore);
- }
- mDeferTouchMode = TOUCH_DONE_MODE;
- break;
- case WebViewCore.ACTION_DOUBLETAP:
- // doDoubleTap() needs mLastTouchX/Y as anchor
- mLastTouchX = contentToViewX(ted.mPoints[0].x) - mScrollX;
- mLastTouchY = contentToViewY(ted.mPoints[0].y) - mScrollY;
- mZoomManager.handleDoubleTap(mLastTouchX, mLastTouchY);
- mDeferTouchMode = TOUCH_DONE_MODE;
- break;
- case WebViewCore.ACTION_LONGPRESS:
- HitTestResult hitTest = getHitTestResult();
- if (hitTest != null && hitTest.mType
- != HitTestResult.UNKNOWN_TYPE) {
- performLongClick();
- }
- mDeferTouchMode = TOUCH_DONE_MODE;
- break;
- }
- }
+ TouchEventData ted = (TouchEventData) msg.obj;
+ if (!ted.mDontEnqueueResult) {
+ mTouchEventQueue.enqueueTouchEvent(ted);
}
break;
@@ -8341,8 +8534,9 @@
boolean splitIfNeeded);
private native void nativeDumpDisplayTree(String urlOrNull);
private native boolean nativeEvaluateLayersAnimations();
- private native int nativeGetDrawGLFunction(Rect rect, float scale, int extras);
- private native void nativeUpdateDrawGLFunction(Rect rect);
+ private native int nativeGetDrawGLFunction(Rect rect, Rect viewRect,
+ float scale, int extras);
+ private native void nativeUpdateDrawGLFunction(Rect rect, Rect viewRect);
private native boolean nativeDrawGL(Rect rect, float scale, int extras);
private native void nativeExtendSelection(int x, int y);
private native int nativeFindAll(String findLower, String findUpper,
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index c18c9e4..f367b93 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -825,6 +825,9 @@
MotionEvent mMotionEvent;
int mNativeLayer;
Rect mNativeLayerRect = new Rect();
+ long mSequence;
+ boolean mNativeResult;
+ boolean mDontEnqueueResult;
}
static class GeolocationPermissionsData {
@@ -1332,13 +1335,14 @@
nativeScrollLayer(ted.mNativeLayer,
ted.mNativeLayerRect);
}
+ ted.mNativeResult = nativeHandleTouchEvent(ted.mAction, ted.mIds,
+ xArray, yArray, count, ted.mMetaState);
Message.obtain(
mWebView.mPrivateHandler,
WebView.PREVENT_TOUCH_ID,
ted.mAction,
- nativeHandleTouchEvent(ted.mAction, ted.mIds,
- xArray, yArray, count, ted.mMetaState) ? 1 : 0,
- ted.mReprocess ? ted : null).sendToTarget();
+ ted.mNativeResult ? 1 : 0,
+ ted).sendToTarget();
break;
}
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 427126b..af954c9 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -3019,12 +3019,13 @@
hasOpaqueScrollbars()) || super.isOpaque();
if (retValue) {
// only return true if the list items cover the entire area of the view
- final int listTop = mListPadding.top;
+ final int listTop = mListPadding != null ? mListPadding.top : mPaddingTop;
View first = getChildAt(0);
if (first == null || first.getTop() > listTop) {
return false;
}
- final int listBottom = getHeight() - mListPadding.bottom;
+ final int listBottom = getHeight() -
+ (mListPadding != null ? mListPadding.bottom : mPaddingBottom);
View last = getChildAt(getChildCount() - 1);
if (last == null || last.getBottom() < listBottom) {
return false;
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 2d2165b..1c0a2bb 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -889,7 +889,7 @@
boolean isConnected = mServiceConnection.isConnected();
boolean hasNewItems = false;
- if (!isConnected) {
+ if (!isInCache && !isConnected) {
// Requesting bind service will trigger a super.notifyDataSetChanged(), which will
// in turn trigger another request to getView()
requestBindService();
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index e3a66c5..a41b348 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -385,7 +385,7 @@
if ((flagsChanged & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
mHomeAsUpView.setVisibility((options & ActionBar.DISPLAY_HOME_AS_UP) != 0
- ? VISIBLE : INVISIBLE);
+ ? VISIBLE : GONE);
}
if ((flagsChanged & ActionBar.DISPLAY_USE_LOGO) != 0) {
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 7a609a5..a78f660 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -35,7 +35,6 @@
#include <DisplayListRenderer.h>
#include <LayerRenderer.h>
-#include <OpenGLDebugRenderer.h>
#include <OpenGLRenderer.h>
#include <SkiaShader.h>
#include <SkiaColorFilter.h>
@@ -60,7 +59,6 @@
// Debug
#define DEBUG_RENDERER 0
-#define PROFILE_RENDERER 0
// Debug
#if DEBUG_RENDERER
@@ -99,11 +97,7 @@
static OpenGLRenderer* android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject clazz) {
RENDERER_LOGD("Create OpenGLRenderer");
-#if PROFILE_RENDERER
- return new OpenGLDebugRenderer;
-#else
return new OpenGLRenderer;
-#endif
}
static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz,
@@ -139,7 +133,8 @@
static bool android_view_GLES20Canvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
OpenGLRenderer* renderer, Functor *functor) {
- return renderer->callDrawGLFunction(functor);
+ android::uirenderer::Rect dirty;
+ return renderer->callDrawGLFunction(functor, dirty);
}
// ----------------------------------------------------------------------------
@@ -503,8 +498,14 @@
}
static bool android_view_GLES20Canvas_drawDisplayList(JNIEnv* env,
- jobject clazz, OpenGLRenderer* renderer, DisplayList* displayList) {
- return renderer->drawDisplayList(displayList);
+ jobject clazz, OpenGLRenderer* renderer, DisplayList* displayList, jobject dirty) {
+ android::uirenderer::Rect bounds;
+ bool redraw = renderer->drawDisplayList(displayList, bounds);
+ if (redraw && dirty != NULL) {
+ env->CallVoidMethod(dirty, gRectClassInfo.set,
+ int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
+ }
+ return redraw;
}
// ----------------------------------------------------------------------------
@@ -663,7 +664,8 @@
{ "nGetDisplayList", "(I)I", (void*) android_view_GLES20Canvas_getDisplayList },
{ "nDestroyDisplayList", "(I)V", (void*) android_view_GLES20Canvas_destroyDisplayList },
{ "nGetDisplayListRenderer", "(I)I", (void*) android_view_GLES20Canvas_getDisplayListRenderer },
- { "nDrawDisplayList", "(II)Z", (void*) android_view_GLES20Canvas_drawDisplayList },
+ { "nDrawDisplayList", "(IILandroid/graphics/Rect;)Z",
+ (void*) android_view_GLES20Canvas_drawDisplayList },
{ "nInterrupt", "(I)V", (void*) android_view_GLES20Canvas_interrupt },
{ "nResume", "(I)V", (void*) android_view_GLES20Canvas_resume },
diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
index e7ea8c8..3d24bee 100644
--- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
@@ -400,7 +400,7 @@
}
static jint jni_eglGetCurrentSurface(JNIEnv *_env, jobject _this, jint readdraw) {
- if (!(readdraw == EGL_READ) || (readdraw == EGL_DRAW)) {
+ if ((readdraw != EGL_READ) && (readdraw != EGL_DRAW)) {
doThrow(_env, "java/lang/IllegalArgumentException");
return 0;
}
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
new file mode 100644
index 0000000..6840962
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
new file mode 100644
index 0000000..b3196c3
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
new file mode 100644
index 0000000..c44ae7a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
new file mode 100644
index 0000000..e240a2d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_ab_back_holo_dark.png b/core/res/res/drawable-hdpi/ic_ab_back_holo_dark.png
index 52fccf8..7855cda 100644
--- a/core/res/res/drawable-hdpi/ic_ab_back_holo_dark.png
+++ b/core/res/res/drawable-hdpi/ic_ab_back_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_ab_back_holo_light.png b/core/res/res/drawable-hdpi/ic_ab_back_holo_light.png
index 0354599..c062773 100644
--- a/core/res/res/drawable-hdpi/ic_ab_back_holo_light.png
+++ b/core/res/res/drawable-hdpi/ic_ab_back_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
new file mode 100644
index 0000000..9a24b9c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
new file mode 100644
index 0000000..93d9741
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
new file mode 100644
index 0000000..f462d98
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
new file mode 100644
index 0000000..30373a6
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_ab_back_holo_dark.png b/core/res/res/drawable-mdpi/ic_ab_back_holo_dark.png
index 959b4e4..ae3e6bf 100644
--- a/core/res/res/drawable-mdpi/ic_ab_back_holo_dark.png
+++ b/core/res/res/drawable-mdpi/ic_ab_back_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_ab_back_holo_light.png b/core/res/res/drawable-mdpi/ic_ab_back_holo_light.png
index 41333b8..c61e3fa 100644
--- a/core/res/res/drawable-mdpi/ic_ab_back_holo_light.png
+++ b/core/res/res/drawable-mdpi/ic_ab_back_holo_light.png
Binary files differ
diff --git a/core/res/res/layout/action_bar_home.xml b/core/res/res/layout/action_bar_home.xml
index e8b5637..7867577 100644
--- a/core/res/res/layout/action_bar_home.xml
+++ b/core/res/res/layout/action_bar_home.xml
@@ -14,16 +14,18 @@
limitations under the License.
-->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:background="?android:attr/selectableItemBackground">
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:background="?android:attr/selectableItemBackground"
+ android:orientation="horizontal">
<ImageView android:id="@android:id/up"
android:src="?android:attr/homeAsUpIndicator"
android:layout_gravity="top|left"
- android:visibility="invisible"
+ android:visibility="gone"
android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
+ android:layout_height="wrap_content"
+ android:layout_marginRight="-12dip" />
<ImageView android:id="@android:id/home"
android:layout_width="wrap_content"
android:layout_height="match_parent"
@@ -31,4 +33,4 @@
android:paddingRight="16dip"
android:layout_gravity="center"
android:scaleType="center" />
-</FrameLayout>
+</LinearLayout>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 066aae9..af0074b 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -828,7 +828,7 @@
<string name="anr_application_process" msgid="4185842666452210193">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulaması (<xliff:g id="PROCESS">%2$s</xliff:g> işleminde) yanıt vermiyor."</string>
<string name="anr_process" msgid="1246866008169975783">"<xliff:g id="PROCESS">%1$s</xliff:g> işlemi yanıt vermiyor."</string>
<string name="force_close" msgid="3653416315450806396">"Kapanmaya zorla"</string>
- <string name="report" msgid="4060218260984795706">"Rapor"</string>
+ <string name="report" msgid="4060218260984795706">"Bildir"</string>
<string name="wait" msgid="7147118217226317732">"Bekle"</string>
<string name="launch_warning_title" msgid="8323761616052121936">"Uygulama yönlendirildi"</string>
<string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> ÅŸimdi çalışıyor."</string>
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index 6d925d6..1428b63 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -409,6 +409,10 @@
axis 0x03 RX
axis 0x04 RY
axis 0x05 RZ
+axis 0x06 THROTTLE
+axis 0x07 RUDDER
+axis 0x08 WHEEL
+axis 0x09 GAS
+axis 0x0a BRAKE
axis 0x10 HAT_X
axis 0x11 HAT_Y
-
\ No newline at end of file
diff --git a/data/keyboards/Vendor_045e_Product_028e.kl b/data/keyboards/Vendor_045e_Product_028e.kl
new file mode 100644
index 0000000..99f046a
--- /dev/null
+++ b/data/keyboards/Vendor_045e_Product_028e.kl
@@ -0,0 +1,46 @@
+# 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.
+
+#
+# XBox 360 USB Controller
+#
+
+key 304 BUTTON_A
+key 305 BUTTON_B
+key 307 BUTTON_X
+key 308 BUTTON_Y
+key 310 BUTTON_L1
+key 311 BUTTON_R1
+key 314 BUTTON_SELECT
+key 315 BUTTON_START
+key 316 BUTTON_MODE
+key 317 BUTTON_THUMBL
+key 318 BUTTON_THUMBR
+
+# Left and right stick.
+# The reported value for flat is 128 out of a range from -32767 to 32768, which is absurd.
+# This confuses applications that rely on the flat value because the joystick actually
+# settles in a flat range of +/- 4096 or so.
+axis 0x00 X flat 4096
+axis 0x01 Y flat 4096
+axis 0x03 Z flat 4096
+axis 0x04 RZ flat 4096
+
+# Triggers.
+axis 0x02 LTRIGGER
+axis 0x05 RTRIGGER
+
+# Hat.
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
diff --git a/data/keyboards/Vendor_046d_Product_c294.kl b/data/keyboards/Vendor_046d_Product_c294.kl
new file mode 100644
index 0000000..5492f49
--- /dev/null
+++ b/data/keyboards/Vendor_046d_Product_c294.kl
@@ -0,0 +1,53 @@
+# 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.
+
+#
+# Logitech G25 Racing Wheel (in Compatibility Mode)
+#
+
+# 4 way buttons above hat
+key 0x121 BUTTON_A
+key 0x123 BUTTON_B
+key 0x120 BUTTON_X
+key 0x122 BUTTON_Y
+
+# Row of buttons under hat
+key 0x12b BUTTON_1
+key 0x128 BUTTON_2
+key 0x129 BUTTON_3
+key 0x12a BUTTON_4
+
+# Gear shift positions
+# 0x12a top-left gear (aliased as BUTTON_4)
+# 0x12b bottom-left gear (aliased as BUTTON_1)
+
+# Buttons on wheel
+key 0x127 BUTTON_L1
+key 0x126 BUTTON_R1
+
+# Toggles under wheel
+key 0x125 BUTTON_L2
+key 0x124 BUTTON_R2
+
+# Hat
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+# Steering Wheel
+axis 0x00 WHEEL
+
+# Accelerator / Brake
+# 00..7e : accelerator
+# 80..ff : brake
+axis 0x01 split 0x7f GAS BRAKE
diff --git a/data/keyboards/Vendor_046d_Product_c299.kl b/data/keyboards/Vendor_046d_Product_c299.kl
new file mode 100644
index 0000000..d42963d
--- /dev/null
+++ b/data/keyboards/Vendor_046d_Product_c299.kl
@@ -0,0 +1,62 @@
+# 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.
+
+#
+# Logitech G25 Racing Wheel (in Native Mode)
+#
+
+# 4 way buttons above hat
+key 0x121 BUTTON_A
+key 0x123 BUTTON_B
+key 0x120 BUTTON_X
+key 0x122 BUTTON_Y
+
+# Row of buttons under hat
+key 0x12b BUTTON_1
+key 0x128 BUTTON_2
+key 0x129 BUTTON_3
+key 0x12a BUTTON_4
+
+# Gear shift positions
+key 0x12c BUTTON_5
+key 0x12d BUTTON_6
+key 0x12e BUTTON_7
+key 0x12f BUTTON_8
+key 0x2d0 BUTTON_9
+key 0x2d1 BUTTON_10
+key 0x2d2 BUTTON_11
+
+# Buttons on wheel
+key 0x127 BUTTON_L1
+key 0x126 BUTTON_R1
+
+# Toggles under wheel
+key 0x125 BUTTON_L2
+key 0x124 BUTTON_R2
+
+# Hat
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+# Steering Wheel
+axis 0x00 WHEEL
+
+# Clutch
+axis 0x01 invert GENERIC_1
+
+# Accelerator
+axis 0x02 invert GAS
+
+# Brake
+axis 0x05 invert BRAKE
diff --git a/data/keyboards/common.mk b/data/keyboards/common.mk
index 5b367b9..335298c 100644
--- a/data/keyboards/common.mk
+++ b/data/keyboards/common.mk
@@ -19,7 +19,10 @@
Generic.kl \
AVRCP.kl \
qwerty.kl \
+ Vendor_045e_Product_028e.kl \
Vendor_046d_Product_c216.kl \
+ Vendor_046d_Product_c294.kl \
+ Vendor_046d_Product_c299.kl \
Vendor_046d_Product_c532.kl \
Vendor_054c_Product_0268.kl \
Vendor_05ac_Product_0239.kl \
diff --git a/drm/java/android/drm/DrmManagerClient.java b/drm/java/android/drm/DrmManagerClient.java
index c541456..782ffdb 100644
--- a/drm/java/android/drm/DrmManagerClient.java
+++ b/drm/java/android/drm/DrmManagerClient.java
@@ -735,6 +735,7 @@
* This method expects uri in the following format
* content://media/<table_name>/<row_index> (or)
* file://sdcard/test.mp4
+ * http://test.com/test.mp4
*
* Here <table_name> shall be "video" or "audio" or "images"
* <row_index> the index of the content in given table
@@ -746,6 +747,10 @@
if (null == scheme || scheme.equals("") ||
scheme.equals(ContentResolver.SCHEME_FILE)) {
path = uri.getPath();
+
+ } else if (scheme.equals("http")) {
+ path = uri.toString();
+
} else if (scheme.equals(ContentResolver.SCHEME_CONTENT)) {
String[] projection = new String[] {MediaStore.MediaColumns.DATA};
Cursor cursor = null;
diff --git a/include/ui/KeyLayoutMap.h b/include/ui/KeyLayoutMap.h
index 904c8f3..d82d0c8 100644
--- a/include/ui/KeyLayoutMap.h
+++ b/include/ui/KeyLayoutMap.h
@@ -24,6 +24,36 @@
namespace android {
+struct AxisInfo {
+ enum Mode {
+ // Axis value is reported directly.
+ MODE_NORMAL = 0,
+ // Axis value should be inverted before reporting.
+ MODE_INVERT = 1,
+ // Axis value should be split into two axes
+ MODE_SPLIT = 2,
+ };
+
+ // Axis mode.
+ Mode mode;
+
+ // Axis id.
+ // When split, this is the axis used for values smaller than the split position.
+ int32_t axis;
+
+ // When split, this is the axis used for values after higher than the split position.
+ int32_t highAxis;
+
+ // The split value, or 0 if not split.
+ int32_t splitValue;
+
+ // The flat value, or -1 if none.
+ int32_t flatOverride;
+
+ AxisInfo() : mode(MODE_NORMAL), axis(-1), highAxis(-1), splitValue(0), flatOverride(-1) {
+ }
+};
+
/**
* Describes a mapping from keyboard scan codes and joystick axes to Android key codes and axes.
*/
@@ -36,7 +66,7 @@
status_t mapKey(int32_t scanCode, int32_t* keyCode, uint32_t* flags) const;
status_t findScanCodesForKey(int32_t keyCode, Vector<int32_t>* outScanCodes) const;
- status_t mapAxis(int32_t scanCode, int32_t* axis) const;
+ status_t mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const;
private:
struct Key {
@@ -45,7 +75,7 @@
};
KeyedVector<int32_t, Key> mKeys;
- KeyedVector<int32_t, int32_t> mAxes;
+ KeyedVector<int32_t, AxisInfo> mAxes;
KeyLayoutMap();
diff --git a/include/ui/KeycodeLabels.h b/include/ui/KeycodeLabels.h
index bdfbf7c..b912e9b 100755
--- a/include/ui/KeycodeLabels.h
+++ b/include/ui/KeycodeLabels.h
@@ -270,6 +270,11 @@
{ "HAT_Y", 16 },
{ "LTRIGGER", 17 },
{ "RTRIGGER", 18 },
+ { "THROTTLE", 19 },
+ { "RUDDER", 20 },
+ { "WHEEL", 21 },
+ { "GAS", 22 },
+ { "BRAKE", 23 },
{ "GENERIC_1", 32 },
{ "GENERIC_2", 33 },
{ "GENERIC_3", 34 },
diff --git a/include/utils/Functor.h b/include/utils/Functor.h
index 3955bc3..565f4a3 100644
--- a/include/utils/Functor.h
+++ b/include/utils/Functor.h
@@ -26,6 +26,7 @@
Functor() {}
virtual ~Functor() {}
virtual status_t operator ()() { return true; }
+ virtual status_t operator ()(float* data, uint32_t len) { return true; }
};
}; // namespace android
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 38e0848..f4a0161 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -15,7 +15,6 @@
LayerCache.cpp \
LayerRenderer.cpp \
Matrix.cpp \
- OpenGLDebugRenderer.cpp \
OpenGLRenderer.cpp \
Patch.cpp \
PatchCache.cpp \
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index d5d2ba0..737fa02 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -166,7 +166,7 @@
void DisplayList::init() {
}
-bool DisplayList::replay(OpenGLRenderer& renderer, uint32_t level) {
+bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) {
bool needsInvalidate = false;
TextContainer text;
mReader.rewind();
@@ -189,7 +189,7 @@
case DrawGLFunction: {
Functor *functor = (Functor *) getInt();
DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], functor);
- needsInvalidate |= renderer.callDrawGLFunction(functor);
+ needsInvalidate |= renderer.callDrawGLFunction(functor, dirty);
}
break;
case Save: {
@@ -287,7 +287,7 @@
DisplayList* displayList = getDisplayList();
DISPLAY_LIST_LOGD("%s%s %p, %d", (char*) indent, OP_NAMES[op],
displayList, level + 1);
- needsInvalidate |= renderer.drawDisplayList(displayList, level + 1);
+ needsInvalidate |= renderer.drawDisplayList(displayList, dirty, level + 1);
}
break;
case DrawLayer: {
@@ -589,7 +589,8 @@
void DisplayListRenderer::resume() {
}
-bool DisplayListRenderer::callDrawGLFunction(Functor *functor) {
+bool DisplayListRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
+ // Ignore dirty during recording, it matters only when we replay
addOp(DisplayList::DrawGLFunction);
addInt((int) functor);
return false; // No invalidate needed at record-time
@@ -673,7 +674,9 @@
return OpenGLRenderer::clipRect(left, top, right, bottom, op);
}
-bool DisplayListRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
+bool DisplayListRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level) {
+ // dirty is an out parameter and should not be recorded,
+ // it matters only when replaying the display list
addOp(DisplayList::DrawDisplayList);
addDisplayList(displayList);
return false;
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index e8f189d..f24545d 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -103,7 +103,7 @@
void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false);
- bool replay(OpenGLRenderer& renderer, uint32_t level = 0);
+ bool replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level = 0);
private:
void init();
@@ -214,7 +214,7 @@
void prepareDirty(float left, float top, float right, float bottom, bool opaque);
void finish();
- bool callDrawGLFunction(Functor *functor);
+ bool callDrawGLFunction(Functor *functor, Rect& dirty);
void interrupt();
void resume();
@@ -238,7 +238,7 @@
bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
- bool drawDisplayList(DisplayList* displayList, uint32_t level = 0);
+ bool drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level = 0);
void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
diff --git a/libs/hwui/OpenGLDebugRenderer.cpp b/libs/hwui/OpenGLDebugRenderer.cpp
deleted file mode 100644
index 05870bb..0000000
--- a/libs/hwui/OpenGLDebugRenderer.cpp
+++ /dev/null
@@ -1,156 +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 "OpenGLRenderer"
-
-#include <utils/StopWatch.h>
-
-#include "OpenGLDebugRenderer.h"
-
-namespace android {
-namespace uirenderer {
-
-void OpenGLDebugRenderer::prepareDirty(float left, float top,
- float right, float bottom, bool opaque) {
- mPrimitivesCount = 0;
- LOGD("========= Frame start =========");
- OpenGLRenderer::prepareDirty(left, top, right, bottom, opaque);
-}
-
-void OpenGLDebugRenderer::finish() {
- LOGD("========= Frame end =========");
- LOGD("Primitives draw count = %d", mPrimitivesCount);
- OpenGLRenderer::finish();
-}
-
-void OpenGLDebugRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
- mPrimitivesCount++;
- StopWatch w("composeLayer");
- return OpenGLRenderer::composeLayer(current, previous);
-}
-
-int OpenGLDebugRenderer::saveLayer(float left, float top, float right, float bottom,
- SkPaint* p, int flags) {
- mPrimitivesCount++;
- StopWatch w("saveLayer");
- return OpenGLRenderer::saveLayer(left, top, right, bottom, p, flags);
-}
-
-bool OpenGLDebugRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
- mPrimitivesCount++;
- StopWatch w("drawDisplayList");
- return OpenGLRenderer::drawDisplayList(displayList);
-}
-
-void OpenGLDebugRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawLayer");
- OpenGLRenderer::drawLayer(layer, x, y, paint);
-}
-
-void OpenGLDebugRenderer::drawBitmap(SkBitmap* bitmap, float left, float top,
- SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawBitmap");
- OpenGLRenderer::drawBitmap(bitmap, left, top, paint);
-}
-
-void OpenGLDebugRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix,
- SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawBitmapMatrix");
- OpenGLRenderer::drawBitmap(bitmap, matrix, paint);
-}
-
-void OpenGLDebugRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
- float srcRight, float srcBottom, float dstLeft, float dstTop,
- float dstRight, float dstBottom, SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawBitmapRect");
- OpenGLRenderer::drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
- dstLeft, dstTop, dstRight, dstBottom, paint);
-}
-
-void OpenGLDebugRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
- const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
- float left, float top, float right, float bottom, SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawPatch");
- OpenGLRenderer::drawPatch(bitmap, xDivs, yDivs, colors, width, height, numColors,
- left, top, right, bottom, paint);
-}
-
-void OpenGLDebugRenderer::drawColor(int color, SkXfermode::Mode mode) {
- mPrimitivesCount++;
- StopWatch w("drawColor");
- OpenGLRenderer::drawColor(color, mode);
-}
-
-void OpenGLDebugRenderer::drawRect(float left, float top, float right, float bottom,
- SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawRect");
- OpenGLRenderer::drawRect(left, top, right, bottom, paint);
-}
-
-void OpenGLDebugRenderer::drawRoundRect(float left, float top, float right, float bottom,
- float rx, float ry, SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawRoundRect");
- OpenGLRenderer::drawRoundRect(left, top, right, bottom, rx, ry, paint);
-}
-
-void OpenGLDebugRenderer::drawCircle(float x, float y, float radius, SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawCircle");
- OpenGLRenderer::drawCircle(x, y, radius, paint);
-}
-
-void OpenGLDebugRenderer::drawOval(float left, float top, float right, float bottom,
- SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawOval");
- OpenGLRenderer::drawOval(left, top, right, bottom, paint);
-}
-
-void OpenGLDebugRenderer::drawArc(float left, float top, float right, float bottom,
- float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawArc");
- OpenGLRenderer::drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
-}
-
-void OpenGLDebugRenderer::drawPath(SkPath* path, SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawPath");
- OpenGLRenderer::drawPath(path, paint);
-}
-
-void OpenGLDebugRenderer::drawLines(float* points, int count, SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawLines");
- OpenGLRenderer::drawLines(points, count, paint);
-}
-
-void OpenGLDebugRenderer::drawText(const char* text, int bytesCount, int count, float x, float y,
- SkPaint* paint) {
- mPrimitivesCount++;
- StopWatch w("drawText");
- OpenGLRenderer::drawText(text, bytesCount, count, x, y, paint);
-}
-
-}; // namespace uirenderer
-}; // namespace android
diff --git a/libs/hwui/OpenGLDebugRenderer.h b/libs/hwui/OpenGLDebugRenderer.h
deleted file mode 100644
index 1a18a67..0000000
--- a/libs/hwui/OpenGLDebugRenderer.h
+++ /dev/null
@@ -1,77 +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_OPENGL_DEBUG_RENDERER_H
-#define ANDROID_HWUI_OPENGL_DEBUG_RENDERER_H
-
-#include "OpenGLRenderer.h"
-
-namespace android {
-namespace uirenderer {
-
-///////////////////////////////////////////////////////////////////////////////
-// Renderer
-///////////////////////////////////////////////////////////////////////////////
-
-class OpenGLDebugRenderer: public OpenGLRenderer {
-public:
- OpenGLDebugRenderer(): mPrimitivesCount(0) {
- }
-
- ~OpenGLDebugRenderer() {
- }
-
- void prepareDirty(float left, float top, float right, float bottom, bool opaque);
- void finish();
-
- int saveLayer(float left, float top, float right, float bottom,
- SkPaint* p, int flags);
-
- bool drawDisplayList(DisplayList* displayList, uint32_t level = 0);
- void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
- void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
- void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
- void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
- float srcRight, float srcBottom, float dstLeft, float dstTop,
- float dstRight, float dstBottom, SkPaint* paint);
- void drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
- const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
- float left, float top, float right, float bottom, SkPaint* paint);
- void drawColor(int color, SkXfermode::Mode mode);
- void drawRect(float left, float top, float right, float bottom, SkPaint* paint);
- void drawRoundRect(float left, float top, float right, float bottom,
- float rx, float ry, SkPaint* paint);
- void drawCircle(float x, float y, float radius, SkPaint* paint);
- void drawOval(float left, float top, float right, float bottom, SkPaint* paint);
- void drawArc(float left, float top, float right, float bottom,
- float startAngle, float sweepAngle, bool useCenter, SkPaint* paint);
- void drawPath(SkPath* path, SkPaint* paint);
- void drawLines(float* points, int count, SkPaint* paint);
- void drawText(const char* text, int bytesCount, int count, float x, float y,
- SkPaint* paint);
-
-protected:
- void composeLayer(sp<Snapshot> current, sp<Snapshot> previous);
-
-private:
- uint32_t mPrimitivesCount;
-
-}; // class OpenGLDebugRenderer
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif // ANDROID_HWUI_OPENGL_DEBUG_RENDERER_H
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index dfca7eb..1f65201 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -210,7 +210,7 @@
glBlendEquation(GL_FUNC_ADD);
}
-bool OpenGLRenderer::callDrawGLFunction(Functor *functor) {
+bool OpenGLRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
interrupt();
if (mDirtyClip) {
setScissorFromClip();
@@ -226,9 +226,16 @@
}
#endif
- status_t result = (*functor)();
+ float bounds[4];
+ status_t result = (*functor)(&bounds[0], 4);
+
+ if (result != 0) {
+ Rect localDirty(bounds[0], bounds[1], bounds[2], bounds[3]);
+ dirty.unionWith(localDirty);
+ }
+
resume();
- return (result == 0) ? false : true;
+ return result != 0;
}
///////////////////////////////////////////////////////////////////////////////
@@ -1057,11 +1064,11 @@
// Drawing
///////////////////////////////////////////////////////////////////////////////
-bool OpenGLRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
+bool OpenGLRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level) {
// All the usual checks and setup operations (quickReject, setupDraw, etc.)
// will be performed by the display list itself
if (displayList) {
- return displayList->replay(*this, level);
+ return displayList->replay(*this, dirty, level);
}
return false;
}
@@ -1522,7 +1529,6 @@
break;
}
- // TODO: Handle paint->getTextScaleX()
const float oldX = x;
const float oldY = y;
const bool pureTranslate = mSnapshot->transform->isPureTranslate();
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 7bbf034..9d86388 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -70,7 +70,7 @@
virtual void interrupt();
virtual void resume();
- virtual bool callDrawGLFunction(Functor *functor);
+ virtual bool callDrawGLFunction(Functor *functor, Rect& dirty);
int getSaveCount() const;
virtual int save(int flags);
@@ -96,7 +96,7 @@
bool quickReject(float left, float top, float right, float bottom);
virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
- virtual bool drawDisplayList(DisplayList* displayList, uint32_t level = 0);
+ virtual bool drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level = 0);
virtual void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
virtual void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
virtual void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
diff --git a/libs/hwui/TextDropShadowCache.h b/libs/hwui/TextDropShadowCache.h
index 62c4250..d46686d 100644
--- a/libs/hwui/TextDropShadowCache.h
+++ b/libs/hwui/TextDropShadowCache.h
@@ -42,6 +42,17 @@
textSize = paint->getTextSize();
typeface = paint->getTypeface();
+
+ flags = 0;
+ if (paint->isFakeBoldText()) {
+ flags |= Font::kFakeBold;
+ }
+
+ const float skewX = paint->getTextSkewX();
+ italicStyle = *(uint32_t*) &skewX;
+
+ const float scaleXFloat = paint->getTextScaleX();
+ scaleX = *(uint32_t*) &scaleXFloat;
}
~ShadowText() {
@@ -51,6 +62,9 @@
uint32_t len;
float textSize;
SkTypeface* typeface;
+ uint32_t flags;
+ uint32_t italicStyle;
+ uint32_t scaleX;
const char16_t* text;
String16 str;
@@ -65,7 +79,13 @@
LTE_INT(radius) {
LTE_FLOAT(textSize) {
LTE_INT(typeface) {
- return strncmp16(text, rhs.text, len >> 1) < 0;
+ LTE_INT(flags) {
+ LTE_INT(italicStyle) {
+ LTE_INT(scaleX) {
+ return strncmp16(text, rhs.text, len >> 1) < 0;
+ }
+ }
+ }
}
}
}
diff --git a/libs/ui/KeyLayoutMap.cpp b/libs/ui/KeyLayoutMap.cpp
index 2ed0e66..8626a03 100644
--- a/libs/ui/KeyLayoutMap.cpp
+++ b/libs/ui/KeyLayoutMap.cpp
@@ -113,20 +113,23 @@
return NO_ERROR;
}
-status_t KeyLayoutMap::mapAxis(int32_t scanCode, int32_t* axis) const {
+status_t KeyLayoutMap::mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const {
ssize_t index = mAxes.indexOfKey(scanCode);
if (index < 0) {
#if DEBUG_MAPPING
LOGD("mapAxis: scanCode=%d ~ Failed.", scanCode);
#endif
- *axis = -1;
return NAME_NOT_FOUND;
}
- *axis = mAxes.valueAt(index);
+ *outAxisInfo = mAxes.valueAt(index);
#if DEBUG_MAPPING
- LOGD("mapAxis: scanCode=%d ~ Result axis=%d.", scanCode, *axis);
+ LOGD("mapAxis: scanCode=%d ~ Result mode=%d, axis=%d, highAxis=%d, "
+ "splitValue=%d, flatOverride=%d.",
+ scanCode,
+ outAxisInfo->mode, outAxisInfo->axis, outAxisInfo->highAxis,
+ outAxisInfo->splitValue, outAxisInfo->flatOverride);
#endif
return NO_ERROR;
}
@@ -249,19 +252,89 @@
return BAD_VALUE;
}
+ AxisInfo axisInfo;
+
mTokenizer->skipDelimiters(WHITESPACE);
- String8 axisToken = mTokenizer->nextToken(WHITESPACE);
- int32_t axis = getAxisByLabel(axisToken.string());
- if (axis < 0) {
- LOGE("%s: Expected axis label, got '%s'.", mTokenizer->getLocation().string(),
- axisToken.string());
- return BAD_VALUE;
+ String8 token = mTokenizer->nextToken(WHITESPACE);
+ if (token == "invert") {
+ axisInfo.mode = AxisInfo::MODE_INVERT;
+
+ mTokenizer->skipDelimiters(WHITESPACE);
+ String8 axisToken = mTokenizer->nextToken(WHITESPACE);
+ axisInfo.axis = getAxisByLabel(axisToken.string());
+ if (axisInfo.axis < 0) {
+ LOGE("%s: Expected inverted axis label, got '%s'.",
+ mTokenizer->getLocation().string(), axisToken.string());
+ return BAD_VALUE;
+ }
+ } else if (token == "split") {
+ axisInfo.mode = AxisInfo::MODE_SPLIT;
+
+ mTokenizer->skipDelimiters(WHITESPACE);
+ String8 splitToken = mTokenizer->nextToken(WHITESPACE);
+ axisInfo.splitValue = int32_t(strtol(splitToken.string(), &end, 0));
+ if (*end) {
+ LOGE("%s: Expected split value, got '%s'.",
+ mTokenizer->getLocation().string(), splitToken.string());
+ return BAD_VALUE;
+ }
+
+ mTokenizer->skipDelimiters(WHITESPACE);
+ String8 lowAxisToken = mTokenizer->nextToken(WHITESPACE);
+ axisInfo.axis = getAxisByLabel(lowAxisToken.string());
+ if (axisInfo.axis < 0) {
+ LOGE("%s: Expected low axis label, got '%s'.",
+ mTokenizer->getLocation().string(), lowAxisToken.string());
+ return BAD_VALUE;
+ }
+
+ mTokenizer->skipDelimiters(WHITESPACE);
+ String8 highAxisToken = mTokenizer->nextToken(WHITESPACE);
+ axisInfo.highAxis = getAxisByLabel(highAxisToken.string());
+ if (axisInfo.highAxis < 0) {
+ LOGE("%s: Expected high axis label, got '%s'.",
+ mTokenizer->getLocation().string(), highAxisToken.string());
+ return BAD_VALUE;
+ }
+ } else {
+ axisInfo.axis = getAxisByLabel(token.string());
+ if (axisInfo.axis < 0) {
+ LOGE("%s: Expected axis label, 'split' or 'invert', got '%s'.",
+ mTokenizer->getLocation().string(), token.string());
+ return BAD_VALUE;
+ }
+ }
+
+ for (;;) {
+ mTokenizer->skipDelimiters(WHITESPACE);
+ if (mTokenizer->isEol()) {
+ break;
+ }
+ String8 keywordToken = mTokenizer->nextToken(WHITESPACE);
+ if (keywordToken == "flat") {
+ mTokenizer->skipDelimiters(WHITESPACE);
+ String8 flatToken = mTokenizer->nextToken(WHITESPACE);
+ axisInfo.flatOverride = int32_t(strtol(flatToken.string(), &end, 0));
+ if (*end) {
+ LOGE("%s: Expected flat value, got '%s'.",
+ mTokenizer->getLocation().string(), flatToken.string());
+ return BAD_VALUE;
+ }
+ } else {
+ LOGE("%s: Expected keyword 'flat', got '%s'.",
+ mTokenizer->getLocation().string(), keywordToken.string());
+ return BAD_VALUE;
+ }
}
#if DEBUG_PARSER
- LOGD("Parsed axis: scanCode=%d, axis=%d.", scanCode, axis);
+ LOGD("Parsed axis: scanCode=%d, mode=%d, axis=%d, highAxis=%d, "
+ "splitValue=%d, flatOverride=%d.",
+ scanCode,
+ axisInfo.mode, axisInfo.axis, axisInfo.highAxis,
+ axisInfo.splitValue, axisInfo.flatOverride);
#endif
- mMap->mAxes.add(scanCode, axis);
+ mMap->mAxes.add(scanCode, axisInfo);
return NO_ERROR;
}
diff --git a/media/java/android/media/videoeditor/AudioTrack.java b/media/java/android/media/videoeditor/AudioTrack.java
index b2f547b..7069b23 100755
--- a/media/java/android/media/videoeditor/AudioTrack.java
+++ b/media/java/android/media/videoeditor/AudioTrack.java
@@ -140,7 +140,7 @@
try {
properties = mMANativeHelper.getMediaProperties(filename);
} catch (Exception e) {
- throw new IllegalArgumentException("Unsupported file or file not found");
+ throw new IllegalArgumentException(e.getMessage() + " : " + filename);
}
switch (mMANativeHelper.getFileType(properties.fileType)) {
case MediaProperties.FILE_3GP:
diff --git a/media/java/android/media/videoeditor/MediaVideoItem.java b/media/java/android/media/videoeditor/MediaVideoItem.java
index c91d796..4758de6 100755
--- a/media/java/android/media/videoeditor/MediaVideoItem.java
+++ b/media/java/android/media/videoeditor/MediaVideoItem.java
@@ -115,7 +115,7 @@
try {
properties = mMANativeHelper.getMediaProperties(filename);
} catch ( Exception e) {
- throw new IllegalArgumentException("Unsupported file or file not found: " + filename);
+ throw new IllegalArgumentException(e.getMessage() + " : " + filename);
}
switch (mMANativeHelper.getFileType(properties.fileType)) {
diff --git a/media/java/android/mtp/MtpClient.java b/media/java/android/mtp/MtpClient.java
index c4ee19e..40e2f9b 100644
--- a/media/java/android/mtp/MtpClient.java
+++ b/media/java/android/mtp/MtpClient.java
@@ -29,6 +29,7 @@
import java.io.IOException;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
/**
@@ -43,7 +44,10 @@
private final Context mContext;
private final UsbManager mUsbManager;
private final ArrayList<Listener> mListeners = new ArrayList<Listener>();
- private final ArrayList<MtpDevice> mDeviceList = new ArrayList<MtpDevice>();
+ // mDevices contains all MtpDevices that have been seen by our client,
+ // so we can inform when the device has been detached.
+ // mDevices is also used for synchronization in this class.
+ private final HashMap<String, MtpDevice> mDevices = new HashMap<String, MtpDevice>();
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
@Override
@@ -51,21 +55,21 @@
UsbDevice usbDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
String deviceName = usbDevice.getDeviceName();
- synchronized (mDeviceList) {
- MtpDevice mtpDevice = getDeviceLocked(deviceName);
+ synchronized (mDevices) {
+ MtpDevice mtpDevice = mDevices.get(deviceName);
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) {
if (mtpDevice == null) {
- mtpDevice = openDevice(usbDevice);
+ mtpDevice = openDeviceLocked(usbDevice);
}
if (mtpDevice != null) {
- mDeviceList.add(mtpDevice);
+ mDevices.put(deviceName, mtpDevice);
for (Listener listener : mListeners) {
listener.deviceAdded(mtpDevice);
}
}
} else if (mtpDevice != null) {
- mDeviceList.remove(mtpDevice);
+ mDevices.remove(deviceName);
for (Listener listener : mListeners) {
listener.deviceRemoved(mtpDevice);
}
@@ -127,16 +131,6 @@
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
context.registerReceiver(mUsbReceiver, filter);
-
- for (UsbDevice usbDevice : mUsbManager.getDeviceList().values()) {
- MtpDevice mtpDevice = getDeviceLocked(usbDevice.getDeviceName());
- if (mtpDevice == null) {
- mtpDevice = openDevice(usbDevice);
- }
- if (mtpDevice != null) {
- mDeviceList.add(mtpDevice);
- }
- }
}
/**
@@ -146,7 +140,7 @@
* @param device the device to open
* @return an MtpDevice for the device.
*/
- private MtpDevice openDevice(UsbDevice usbDevice) {
+ private MtpDevice openDeviceLocked(UsbDevice usbDevice) {
if (isCamera(usbDevice)) {
MtpDevice mtpDevice = new MtpDevice(usbDevice);
if (mtpDevice.open(mUsbManager)) {
@@ -170,7 +164,7 @@
* @param listener the listener to register
*/
public void addListener(Listener listener) {
- synchronized (mDeviceList) {
+ synchronized (mDevices) {
if (!mListeners.contains(listener)) {
mListeners.add(listener);
}
@@ -183,7 +177,7 @@
* @param listener the listener to unregister
*/
public void removeListener(Listener listener) {
- synchronized (mDeviceList) {
+ synchronized (mDevices) {
mListeners.remove(listener);
}
}
@@ -196,8 +190,8 @@
* @return the MtpDevice, or null if it does not exist
*/
public MtpDevice getDevice(String deviceName) {
- synchronized (mDeviceList) {
- return getDeviceLocked(deviceName);
+ synchronized (mDevices) {
+ return mDevices.get(deviceName);
}
}
@@ -209,28 +203,32 @@
* @return the MtpDevice, or null if it does not exist
*/
public MtpDevice getDevice(int id) {
- synchronized (mDeviceList) {
- return getDeviceLocked(UsbDevice.getDeviceName(id));
+ synchronized (mDevices) {
+ return mDevices.get(UsbDevice.getDeviceName(id));
}
}
- private MtpDevice getDeviceLocked(String deviceName) {
- for (MtpDevice device : mDeviceList) {
- if (device.getDeviceName().equals(deviceName)) {
- return device;
- }
- }
- return null;
- }
-
/**
* Retrieves a list of all currently connected {@link android.mtp.MtpDevice}.
*
* @return the list of MtpDevices
*/
public List<MtpDevice> getDeviceList() {
- synchronized (mDeviceList) {
- return new ArrayList<MtpDevice>(mDeviceList);
+ synchronized (mDevices) {
+ // Query the USB manager since devices might have attached
+ // before we added our listener.
+ for (UsbDevice usbDevice : mUsbManager.getDeviceList().values()) {
+ String deviceName = usbDevice.getDeviceName();
+ MtpDevice mtpDevice = mDevices.get(deviceName);
+ if (mtpDevice == null) {
+ mtpDevice = openDeviceLocked(usbDevice);
+ }
+ if (mtpDevice != null) {
+ mDevices.put(deviceName, mtpDevice);
+ }
+ }
+
+ return new ArrayList<MtpDevice>(mDevices.values());
}
}
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index 98de2f7..b4a4689 100644
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -20,6 +20,7 @@
import android.content.ContentValues;
import android.content.IContentProvider;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.media.MediaScanner;
@@ -62,8 +63,8 @@
// true if the database has been modified in the current MTP session
private boolean mDatabaseModified;
- // database for writable MTP device properties
- private SQLiteDatabase mDevicePropDb;
+ // SharedPreferences for writable MTP device properties
+ private SharedPreferences mDeviceProperties;
private static final int DEVICE_PROPERTIES_DATABASE_VERSION = 1;
// FIXME - this should be passed in via the constructor
@@ -96,9 +97,6 @@
private static final String PARENT_FORMAT_WHERE = PARENT_WHERE + " AND "
+ Files.FileColumns.FORMAT + "=?";
- private static final String[] DEVICE_PROPERTY_PROJECTION = new String[] { "_id", "value" };
- private static final String DEVICE_PROPERTY_WHERE = "code=?";
-
private final MediaScanner mMediaScanner;
static {
@@ -114,7 +112,7 @@
mMediaStoragePath = storagePath;
mObjectsUri = Files.getMtpObjectsUri(volumeName);
mMediaScanner = new MediaScanner(context);
- openDevicePropertiesDatabase(context);
+ initDeviceProperties(context);
}
@Override
@@ -126,19 +124,38 @@
}
}
- private void openDevicePropertiesDatabase(Context context) {
- mDevicePropDb = context.openOrCreateDatabase("device-properties", Context.MODE_PRIVATE, null);
- int version = mDevicePropDb.getVersion();
+ private void initDeviceProperties(Context context) {
+ final String devicePropertiesName = "device-properties";
+ mDeviceProperties = context.getSharedPreferences(devicePropertiesName, Context.MODE_PRIVATE);
+ File databaseFile = context.getDatabasePath(devicePropertiesName);
- // initialize if necessary
- if (version != DEVICE_PROPERTIES_DATABASE_VERSION) {
- mDevicePropDb.execSQL("CREATE TABLE properties (" +
- "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
- "code INTEGER UNIQUE ON CONFLICT REPLACE," +
- "value TEXT" +
- ");");
- mDevicePropDb.execSQL("CREATE INDEX property_index ON properties (code);");
- mDevicePropDb.setVersion(DEVICE_PROPERTIES_DATABASE_VERSION);
+ if (databaseFile.exists()) {
+ // for backward compatibility - read device properties from sqlite database
+ // and migrate them to shared prefs
+ SQLiteDatabase db = null;
+ Cursor c = null;
+ try {
+ db = context.openOrCreateDatabase("device-properties", Context.MODE_PRIVATE, null);
+ if (db != null) {
+ c = db.query("properties", new String[] { "_id", "code", "value" },
+ null, null, null, null, null);
+ if (c != null) {
+ SharedPreferences.Editor e = mDeviceProperties.edit();
+ while (c.moveToNext()) {
+ String name = c.getString(1);
+ String value = c.getString(2);
+ e.putString(name, value);
+ }
+ e.commit();
+ }
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "failed to migrate device properties", e);
+ } finally {
+ if (c != null) c.close();
+ if (db != null) db.close();
+ }
+ databaseFile.delete();
}
}
@@ -567,30 +584,15 @@
switch (property) {
case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
- // writable string properties kept in our device property database
- Cursor c = null;
- try {
- c = mDevicePropDb.query("properties", DEVICE_PROPERTY_PROJECTION,
- DEVICE_PROPERTY_WHERE, new String[] { Integer.toString(property) },
- null, null, null);
-
- if (c != null && c.moveToNext()) {
- String value = c.getString(1);
- int length = value.length();
- if (length > 255) {
- length = 255;
- }
- value.getChars(0, length, outStringValue, 0);
- outStringValue[length] = 0;
- } else {
- outStringValue[0] = 0;
- }
- return MtpConstants.RESPONSE_OK;
- } finally {
- if (c != null) {
- c.close();
- }
+ // writable string properties kept in shared preferences
+ String value = mDeviceProperties.getString(Integer.toString(property), "");
+ int length = value.length();
+ if (length > 255) {
+ length = 255;
}
+ value.getChars(0, length, outStringValue, 0);
+ outStringValue[length] = 0;
+ return MtpConstants.RESPONSE_OK;
case MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE:
// use screen size as max image size
@@ -612,16 +614,11 @@
switch (property) {
case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
- // writable string properties kept in our device property database
- try {
- ContentValues values = new ContentValues();
- values.put("code", property);
- values.put("value", stringValue);
- mDevicePropDb.insert("properties", "code", values);
- return MtpConstants.RESPONSE_OK;
- } catch (Exception e) {
- return MtpConstants.RESPONSE_GENERAL_ERROR;
- }
+ // writable string properties kept in shared prefs
+ SharedPreferences.Editor e = mDeviceProperties.edit();
+ e.putString(Integer.toString(property), stringValue);
+ return (e.commit() ? MtpConstants.RESPONSE_OK
+ : MtpConstants.RESPONSE_GENERAL_ERROR);
}
return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
diff --git a/media/jni/mediaeditor/VideoEditorOsal.cpp b/media/jni/mediaeditor/VideoEditorOsal.cpp
index 423e93f..035f59a 100755
--- a/media/jni/mediaeditor/VideoEditorOsal.cpp
+++ b/media/jni/mediaeditor/VideoEditorOsal.cpp
@@ -207,6 +207,7 @@
VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_AUDIOBITRATE_TOO_HIGH ),
VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_OUTPUT_FILE_SIZE_TOO_SMALL ),
VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_NOMORE_SPACE ),
+ VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_FILE_DRM_PROTECTED ),
// M4READER_Common.h
VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_READER_UNKNOWN_STREAM_TYPE ),
diff --git a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp b/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
index 73a7c9c..3b795ce 100755
--- a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
+++ b/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
@@ -204,10 +204,17 @@
result = getClipProperties(
pEnv, thiz, pFile, clipType, pClipProperties);
- // Check if the creation succeeded.
- videoEditJava_checkAndThrowIllegalArgumentException(
- &gotten, pEnv,(M4NO_ERROR != result),
- "Invalid File or File not found");
+ if (M4MCS_ERR_FILE_DRM_PROTECTED == result) {
+ // Check if the creation succeeded.
+ videoEditJava_checkAndThrowIllegalArgumentException(
+ &gotten, pEnv,(M4NO_ERROR != result),
+ "Invalid File - DRM Protected ");
+ } else {
+ // Check if the creation succeeded.
+ videoEditJava_checkAndThrowIllegalArgumentException(
+ &gotten, pEnv,(M4NO_ERROR != result),
+ "Invalid File or File not found ");
+ }
/**
* Max resolution supported is 1280 x 720.
diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp
index dbbf3b4..b24343f 100644
--- a/media/libstagefright/NuHTTPDataSource.cpp
+++ b/media/libstagefright/NuHTTPDataSource.cpp
@@ -1,3 +1,19 @@
+/*
+ * 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_NDEBUG 0
#define LOG_TAG "NuHTTPDataSource"
#include <utils/Log.h>
diff --git a/media/libstagefright/include/NuHTTPDataSource.h b/media/libstagefright/include/NuHTTPDataSource.h
index 082b589..2569568 100644
--- a/media/libstagefright/include/NuHTTPDataSource.h
+++ b/media/libstagefright/include/NuHTTPDataSource.h
@@ -1,3 +1,19 @@
+/*
+ * 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 NU_HTTP_DATA_SOURCE_H_
#define NU_HTTP_DATA_SOURCE_H_
diff --git a/native/include/android/input.h b/native/include/android/input.h
index f19e8be..86be54a 100644
--- a/native/include/android/input.h
+++ b/native/include/android/input.h
@@ -359,6 +359,11 @@
AMOTION_EVENT_AXIS_HAT_Y = 16,
AMOTION_EVENT_AXIS_LTRIGGER = 17,
AMOTION_EVENT_AXIS_RTRIGGER = 18,
+ AMOTION_EVENT_AXIS_THROTTLE = 19,
+ AMOTION_EVENT_AXIS_RUDDER = 20,
+ AMOTION_EVENT_AXIS_WHEEL = 21,
+ AMOTION_EVENT_AXIS_GAS = 22,
+ AMOTION_EVENT_AXIS_BRAKE = 23,
AMOTION_EVENT_AXIS_GENERIC_1 = 32,
AMOTION_EVENT_AXIS_GENERIC_2 = 33,
AMOTION_EVENT_AXIS_GENERIC_3 = 34,
diff --git a/opengl/java/com/google/android/gles_jni/EGLContextImpl.java b/opengl/java/com/google/android/gles_jni/EGLContextImpl.java
index 9cf5de7..cd36099 100644
--- a/opengl/java/com/google/android/gles_jni/EGLContextImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLContextImpl.java
@@ -32,4 +32,19 @@
public GL getGL() {
return mGLContext;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ EGLContextImpl that = (EGLContextImpl) o;
+
+ return mEGLContext == that.mEGLContext;
+ }
+
+ @Override
+ public int hashCode() {
+ return mEGLContext;
+ }
}
diff --git a/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java b/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java
index cb94888..e6c9817 100644
--- a/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java
@@ -24,4 +24,20 @@
public EGLDisplayImpl(int dpy) {
mEGLDisplay = dpy;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ EGLDisplayImpl that = (EGLDisplayImpl) o;
+
+ return mEGLDisplay == that.mEGLDisplay;
+
+ }
+
+ @Override
+ public int hashCode() {
+ return mEGLDisplay;
+ }
}
diff --git a/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java b/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java
index f6b90ab..e7f15dc 100644
--- a/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java
@@ -29,4 +29,20 @@
mEGLSurface = surface;
mNativePixelRef = 0;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ EGLSurfaceImpl that = (EGLSurfaceImpl) o;
+
+ return mEGLSurface == that.mEGLSurface;
+
+ }
+
+ @Override
+ public int hashCode() {
+ return mEGLSurface;
+ }
}
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel_title.xml b/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel_title.xml
index 1afb2e3..543f4ed 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel_title.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel_title.xml
@@ -22,7 +22,6 @@
android:layout_height="0dp"
android:orientation="vertical"
android:background="@drawable/notify_panel_clock_bg"
- android:clickable="true"
>
<LinearLayout
android:id="@+id/icons"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java
index 744f667..8b68240 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPeekPanel.java
@@ -18,11 +18,15 @@
import android.content.Context;
import android.util.AttributeSet;
+import android.util.Slog;
+import android.view.MotionEvent;
import android.widget.RelativeLayout;
import com.android.systemui.R;
public class NotificationPeekPanel extends RelativeLayout implements StatusBarPanel {
+ TabletStatusBar mBar;
+
public NotificationPeekPanel(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@@ -39,5 +43,16 @@
return x >= l && x < r && y >= t && y < b;
}
+ public void setBar(TabletStatusBar bar) {
+ mBar = bar;
+ }
+
+ // We don't really want to intercept the touch event, but we *do* want to reset the fade timer
+ // in case the user is interacting with some custom controls or something.
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ mBar.resetNotificationPeekFadeTimer();
+ return false;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 4557105..58c4d5a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -217,6 +217,8 @@
// Notification preview window
mNotificationPeekWindow = (NotificationPeekPanel) View.inflate(context,
R.layout.status_bar_notification_peek, null);
+ mNotificationPeekWindow.setBar(this);
+
mNotificationPeekRow = (ViewGroup) mNotificationPeekWindow.findViewById(R.id.content);
mNotificationPeekWindow.setVisibility(View.GONE);
mNotificationPeekWindow.setOnTouchListener(
@@ -1211,10 +1213,20 @@
}
}
- private class NotificationIconTouchListener implements View.OnTouchListener {
- final static int NOTIFICATION_PEEK_HOLD_THRESH = 200; // ms
- final static int NOTIFICATION_PEEK_FADE_DELAY = 5000; // ms
+ final static int NOTIFICATION_PEEK_HOLD_THRESH = 200; // ms
+ final static int NOTIFICATION_PEEK_FADE_DELAY = 3000; // ms
+ public void resetNotificationPeekFadeTimer() {
+ if (DEBUG) {
+ Slog.d(TAG, "setting peek fade timer for " + NOTIFICATION_PEEK_FADE_DELAY
+ + "ms from now");
+ }
+ mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PEEK);
+ mHandler.sendEmptyMessageDelayed(MSG_CLOSE_NOTIFICATION_PEEK,
+ NOTIFICATION_PEEK_FADE_DELAY);
+ }
+
+ private class NotificationIconTouchListener implements View.OnTouchListener {
VelocityTracker mVT;
int mPeekIndex;
float mInitialTouchX, mInitialTouchY;
@@ -1303,8 +1315,7 @@
}
if (peeking) {
- mHandler.sendEmptyMessageDelayed(MSG_CLOSE_NOTIFICATION_PEEK,
- NOTIFICATION_PEEK_FADE_DELAY);
+ resetNotificationPeekFadeTimer();
}
mVT.recycle();
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index ec89db3..64857ed 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -2187,7 +2187,7 @@
super.onDetachedFromWindow();
final Callback cb = getCallback();
- if (cb != null && !isDestroyed() && mFeatureId < 0) {
+ if (cb != null && mFeatureId < 0) {
cb.onDetachedFromWindow();
}
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index 2fe5980..e37a6b1 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -352,14 +352,13 @@
return NAME_NOT_FOUND;
}
-status_t EventHub::mapAxis(int32_t deviceId, int scancode,
- int32_t* outAxis) const
+status_t EventHub::mapAxis(int32_t deviceId, int scancode, AxisInfo* outAxisInfo) const
{
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
if (device && device->keyMap.haveKeyLayout()) {
- status_t err = device->keyMap.keyLayoutMap->mapAxis(scancode, outAxis);
+ status_t err = device->keyMap.keyLayoutMap->mapAxis(scancode, outAxisInfo);
if (err == NO_ERROR) {
return NO_ERROR;
}
@@ -369,14 +368,13 @@
device = getDeviceLocked(mBuiltInKeyboardId);
if (device && device->keyMap.haveKeyLayout()) {
- status_t err = device->keyMap.keyLayoutMap->mapAxis(scancode, outAxis);
+ status_t err = device->keyMap.keyLayoutMap->mapAxis(scancode, outAxisInfo);
if (err == NO_ERROR) {
return NO_ERROR;
}
}
}
- *outAxis = -1;
return NAME_NOT_FOUND;
}
diff --git a/services/input/EventHub.h b/services/input/EventHub.h
index 445c04b..ab42a1f 100644
--- a/services/input/EventHub.h
+++ b/services/input/EventHub.h
@@ -176,7 +176,7 @@
int32_t* outKeycode, uint32_t* outFlags) const = 0;
virtual status_t mapAxis(int32_t deviceId, int scancode,
- int32_t* outAxis) const = 0;
+ AxisInfo* outAxisInfo) const = 0;
// exclude a particular device from opening
// this can be used to ignore input devices for sensors
@@ -235,7 +235,7 @@
int32_t* outKeycode, uint32_t* outFlags) const;
virtual status_t mapAxis(int32_t deviceId, int scancode,
- int32_t* outAxis) const;
+ AxisInfo* outAxisInfo) const;
virtual void addExcludedDevice(const char* deviceName);
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index b92c3b5..00c3eb7 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -3854,7 +3854,10 @@
for (size_t i = 0; i < mAxes.size(); i++) {
const Axis& axis = mAxes.valueAt(i);
- info->addMotionRange(axis.axis, axis.min, axis.max, axis.flat, axis.fuzz);
+ info->addMotionRange(axis.axisInfo.axis, axis.min, axis.max, axis.flat, axis.fuzz);
+ if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
+ info->addMotionRange(axis.axisInfo.highAxis, axis.min, axis.max, axis.flat, axis.fuzz);
+ }
}
}
@@ -3865,18 +3868,29 @@
size_t numAxes = mAxes.size();
for (size_t i = 0; i < numAxes; i++) {
const Axis& axis = mAxes.valueAt(i);
- const char* label = getAxisLabel(axis.axis);
- char name[32];
+ const char* label = getAxisLabel(axis.axisInfo.axis);
if (label) {
- strncpy(name, label, sizeof(name));
- name[sizeof(name) - 1] = '\0';
+ dump.appendFormat(INDENT4 "%s", label);
} else {
- snprintf(name, sizeof(name), "%d", axis.axis);
+ dump.appendFormat(INDENT4 "%d", axis.axisInfo.axis);
}
- dump.appendFormat(INDENT4 "%s: min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f, "
- "scale=%0.3f, offset=%0.3f\n",
- name, axis.min, axis.max, axis.flat, axis.fuzz,
- axis.scale, axis.offset);
+ 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\n",
+ axis.min, axis.max, axis.flat, axis.fuzz);
+ 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\n",
mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz);
@@ -3891,25 +3905,38 @@
RawAbsoluteAxisInfo rawAxisInfo;
getEventHub()->getAbsoluteAxisInfo(getDeviceId(), abs, &rawAxisInfo);
if (rawAxisInfo.valid) {
- int32_t axisId;
- bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisId);
+ // Map axis.
+ AxisInfo axisInfo;
+ bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
if (!explicitlyMapped) {
// Axis is not explicitly mapped, will choose a generic axis later.
- axisId = -1;
+ 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 (isCenteredAxis(axisId)) {
+ 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);
+ } else if (isCenteredAxis(axisInfo.axis)) {
float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
- axis.initialize(rawAxisInfo, axisId, explicitlyMapped,
- scale, offset, -1.0f, 1.0f,
- rawAxisInfo.flat * scale, rawAxisInfo.fuzz * scale);
+ axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
+ scale, offset, scale, offset,
+ -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
} else {
float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
- axis.initialize(rawAxisInfo, axisId, explicitlyMapped,
- scale, 0.0f, 0.0f, 1.0f,
- rawAxisInfo.flat * scale, rawAxisInfo.fuzz * scale);
+ axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
+ scale, 0.0f, scale, 0.0f,
+ 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
}
// To eliminate noise while the joystick is at rest, filter out small variations
@@ -3934,14 +3961,14 @@
size_t numAxes = mAxes.size();
for (size_t i = 0; i < numAxes; i++) {
Axis& axis = mAxes.editValueAt(i);
- if (axis.axis < 0) {
+ if (axis.axisInfo.axis < 0) {
while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
&& haveAxis(nextGenericAxisId)) {
nextGenericAxisId += 1;
}
if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
- axis.axis = nextGenericAxisId;
+ axis.axisInfo.axis = nextGenericAxisId;
nextGenericAxisId += 1;
} else {
LOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
@@ -3954,10 +3981,13 @@
}
}
-bool JoystickInputMapper::haveAxis(int32_t axis) {
+bool JoystickInputMapper::haveAxis(int32_t axisId) {
size_t numAxes = mAxes.size();
for (size_t i = 0; i < numAxes; i++) {
- if (mAxes.valueAt(i).axis == axis) {
+ const Axis& axis = mAxes.valueAt(i);
+ if (axis.axisInfo.axis == axisId
+ || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
+ && axis.axisInfo.highAxis == axisId)) {
return true;
}
}
@@ -3987,6 +4017,8 @@
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;
@@ -4000,7 +4032,7 @@
size_t numAxes = mAxes.size();
for (size_t i = 0; i < numAxes; i++) {
Axis& axis = mAxes.editValueAt(i);
- axis.newValue = 0;
+ axis.resetValue();
}
sync(when, true /*force*/);
@@ -4014,10 +4046,34 @@
ssize_t index = mAxes.indexOfKey(rawEvent->scanCode);
if (index >= 0) {
Axis& axis = mAxes.editValueAt(index);
- float newValue = rawEvent->value * axis.scale + axis.offset;
- if (newValue != axis.newValue) {
- axis.newValue = newValue;
+ 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;
}
@@ -4033,7 +4089,7 @@
}
void JoystickInputMapper::sync(nsecs_t when, bool force) {
- if (!force && !haveAxesChangedSignificantly()) {
+ if (!filterAxes(force)) {
return;
}
@@ -4044,9 +4100,11 @@
size_t numAxes = mAxes.size();
for (size_t i = 0; i < numAxes; i++) {
- Axis& axis = mAxes.editValueAt(i);
- pointerCoords.setAxisValue(axis.axis, axis.newValue);
- axis.oldValue = axis.newValue;
+ const Axis& axis = mAxes.valueAt(i);
+ pointerCoords.setAxisValue(axis.axisInfo.axis, axis.currentValue);
+ if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
+ pointerCoords.setAxisValue(axis.axisInfo.highAxis, axis.highCurrentValue);
+ }
}
// Moving a joystick axis should not wake the devide because joysticks can
@@ -4061,12 +4119,49 @@
1, &pointerId, &pointerCoords, 0, 0, 0);
}
-bool JoystickInputMapper::haveAxesChangedSignificantly() {
+bool JoystickInputMapper::filterAxes(bool force) {
+ bool atLeastOneSignificantChange = force;
size_t numAxes = mAxes.size();
for (size_t i = 0; i < numAxes; i++) {
- const Axis& axis = mAxes.valueAt(i);
- if (axis.newValue != axis.oldValue
- && fabs(axis.newValue - axis.oldValue) > axis.filter) {
+ 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;
}
}
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index 655f0f0..e2cf08e7 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -1011,38 +1011,50 @@
private:
struct Axis {
RawAbsoluteAxisInfo rawAxisInfo;
+ AxisInfo axisInfo;
- int32_t axis; // axis id
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 oldValue; // previous value
- float newValue; // most recent value
-
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,
- int32_t axis, bool explicitlyMapped, float scale, float offset,
+ 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) {
this->rawAxisInfo = rawAxisInfo;
- this->axis = axis;
+ 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->filter = 0;
- this->oldValue = 0;
+ resetValue();
+ }
+
+ void resetValue() {
+ this->currentValue = 0;
this->newValue = 0;
+ this->highCurrentValue = 0;
+ this->highNewValue = 0;
}
};
@@ -1051,9 +1063,14 @@
void sync(nsecs_t when, bool force);
- bool haveAxis(int32_t axis);
+ bool haveAxis(int32_t axisId);
void pruneAxes(bool ignoreExplicitlyMappedAxes);
- bool haveAxesChangedSignificantly();
+ 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);
};
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 8404b3a..d77cb2f 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -592,7 +592,7 @@
}
virtual status_t mapAxis(int32_t deviceId, int scancode,
- int32_t* outAxis) const {
+ AxisInfo* outAxisInfo) const {
return NAME_NOT_FOUND;
}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java
index e7f431c..3c8432e 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextActivity.java
@@ -58,10 +58,12 @@
mScaledPaint = new Paint();
mScaledPaint.setAntiAlias(true);
mScaledPaint.setTextSize(16.0f);
+ mScaledPaint.setShadowLayer(3.0f, 3.0f, 3.0f, 0xff00ff00);
mSkewPaint = new Paint();
mSkewPaint.setAntiAlias(true);
- mSkewPaint.setTextSize(16.0f);
+ mSkewPaint.setTextSize(16.0f);
+ mSkewPaint.setShadowLayer(3.0f, 3.0f, 3.0f, 0xff000000);
}
@Override
@@ -106,11 +108,11 @@
mStrikePaint.setUnderlineText(true);
mSkewPaint.setTextSkewX(-0.25f);
- canvas.drawText("Hello OpenGL renderer!", 680, 200, mSkewPaint);
+ canvas.drawText("Hello OpenGL renderer!", 980, 200, mSkewPaint);
mSkewPaint.setTextSkewX(0.5f);
- canvas.drawText("Hello OpenGL renderer!", 680, 230, mSkewPaint);
+ canvas.drawText("Hello OpenGL renderer!", 980, 230, mSkewPaint);
mSkewPaint.setTextSkewX(0.0f);
- canvas.drawText("Hello OpenGL renderer!", 680, 260, mSkewPaint);
+ canvas.drawText("Hello OpenGL renderer!", 980, 260, mSkewPaint);
mScaledPaint.setTextScaleX(0.5f);
canvas.drawText("Hello OpenGL renderer!", 500, 200, mScaledPaint);
@@ -125,4 +127,4 @@
canvas.restore();
}
}
-}
\ No newline at end of file
+}
diff --git a/voip/java/android/net/rtp/AudioCodec.java b/voip/java/android/net/rtp/AudioCodec.java
index 3877aeb..85255c8 100644
--- a/voip/java/android/net/rtp/AudioCodec.java
+++ b/voip/java/android/net/rtp/AudioCodec.java
@@ -33,7 +33,6 @@
* </pre>
*
* @see AudioStream
- * @hide
*/
public class AudioCodec {
/**
diff --git a/voip/java/android/net/rtp/AudioGroup.java b/voip/java/android/net/rtp/AudioGroup.java
index 20c8969..3e7ace8 100644
--- a/voip/java/android/net/rtp/AudioGroup.java
+++ b/voip/java/android/net/rtp/AudioGroup.java
@@ -59,7 +59,6 @@
* the AudioGroups is in use.</p>
*
* @see AudioStream
- * @hide
*/
public class AudioGroup {
/**
diff --git a/voip/java/android/net/rtp/AudioStream.java b/voip/java/android/net/rtp/AudioStream.java
index b45cc5e..d761214 100644
--- a/voip/java/android/net/rtp/AudioStream.java
+++ b/voip/java/android/net/rtp/AudioStream.java
@@ -41,7 +41,6 @@
*
* @see RtpStream
* @see AudioGroup
- * @hide
*/
public class AudioStream extends RtpStream {
private AudioCodec mCodec;
diff --git a/voip/java/android/net/rtp/RtpStream.java b/voip/java/android/net/rtp/RtpStream.java
index 87d8bc6..e94ac42 100644
--- a/voip/java/android/net/rtp/RtpStream.java
+++ b/voip/java/android/net/rtp/RtpStream.java
@@ -27,7 +27,6 @@
*
* <p class="note">Using this class requires
* {@link android.Manifest.permission#INTERNET} permission.</p>
- * @hide
*/
public class RtpStream {
/**