Merge "Fix issue 2363154: Speech synthesis fails to start over A2DP after media server process crash."
diff --git a/core/java/android/app/BackupAgent.java b/core/java/android/app/BackupAgent.java
index b207998..2a58677 100644
--- a/core/java/android/app/BackupAgent.java
+++ b/core/java/android/app/BackupAgent.java
@@ -21,6 +21,7 @@
import android.backup.BackupDataOutput;
import android.content.Context;
import android.content.ContextWrapper;
+import android.os.Binder;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -116,7 +117,9 @@
public void doBackup(ParcelFileDescriptor oldState,
ParcelFileDescriptor data,
ParcelFileDescriptor newState) throws RemoteException {
- // !!! TODO - real implementation; for now just invoke the callbacks directly
+ // Ensure that we're running with the app's normal permission level
+ long token = Binder.clearCallingIdentity();
+
if (DEBUG) Log.v(TAG, "doBackup() invoked");
BackupDataOutput output = new BackupDataOutput(data.getFileDescriptor());
try {
@@ -127,12 +130,16 @@
} catch (RuntimeException ex) {
Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex);
throw ex;
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
public void doRestore(ParcelFileDescriptor data, int appVersionCode,
ParcelFileDescriptor newState) throws RemoteException {
- // !!! TODO - real implementation; for now just invoke the callbacks directly
+ // Ensure that we're running with the app's normal permission level
+ long token = Binder.clearCallingIdentity();
+
if (DEBUG) Log.v(TAG, "doRestore() invoked");
BackupDataInput input = new BackupDataInput(data.getFileDescriptor());
try {
@@ -143,6 +150,8 @@
} catch (RuntimeException ex) {
Log.d(TAG, "onRestore (" + BackupAgent.this.getClass().getName() + ") threw", ex);
throw ex;
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
}
diff --git a/core/java/android/provider/Calendar.java b/core/java/android/provider/Calendar.java
index 3296bbf..cbd8a26 100644
--- a/core/java/android/provider/Calendar.java
+++ b/core/java/android/provider/Calendar.java
@@ -62,7 +62,7 @@
public static final String EVENT_BEGIN_TIME = "beginTime";
public static final String EVENT_END_TIME = "endTime";
- public static final String AUTHORITY = "calendar";
+ public static final String AUTHORITY = "com.android.calendar";
/**
* The content:// style URL for the top-level calendar authority
@@ -1413,4 +1413,25 @@
// TODO: fill out this class when we actually start utilizing extendedproperties
// in the calendar application.
}
+
+ /**
+ * A table provided for sync adapters to use for storing private sync state data.
+ *
+ * @see SyncStateContract
+ */
+ public static final class SyncState implements SyncStateContract.Columns {
+ /**
+ * This utility class cannot be instantiated
+ */
+ private SyncState() {}
+
+ public static final String CONTENT_DIRECTORY =
+ SyncStateContract.Constants.CONTENT_DIRECTORY;
+
+ /**
+ * The content:// style URI for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.withAppendedPath(Calendar.CONTENT_URI, CONTENT_DIRECTORY);
+ }
}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index d5bb572..35f1ac6 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -412,6 +412,7 @@
*/
public void setSupportZoom(boolean support) {
mSupportZoom = support;
+ mWebView.updateMultiTouchSupport(mContext);
}
/**
@@ -426,6 +427,7 @@
*/
public void setBuiltInZoomControls(boolean enabled) {
mBuiltInZoomControls = enabled;
+ mWebView.updateMultiTouchSupport(mContext);
}
/**
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 2d9b52e..56650a6 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -21,6 +21,7 @@
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnCancelListener;
+import android.content.pm.PackageManager;
import android.database.DataSetObserver;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -48,6 +49,7 @@
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
import android.view.SoundEffectConstants;
import android.view.VelocityTracker;
import android.view.View;
@@ -362,6 +364,7 @@
private static final int TOUCH_DOUBLE_TAP_MODE = 6;
private static final int TOUCH_DONE_MODE = 7;
private static final int TOUCH_SELECT_MODE = 8;
+ private static final int TOUCH_PINCH_DRAG = 9;
// Whether to forward the touch events to WebCore
private boolean mForwardTouchEvents = false;
@@ -460,6 +463,18 @@
private static final int MOTIONLESS_TRUE = 2;
private int mHeldMotionless;
+ // whether support multi-touch
+ private static boolean mSupportMultiTouch;
+ // use the framework's ScaleGestureDetector to handle multi-touch
+ private ScaleGestureDetector mScaleDetector;
+ // minimum scale change during multi-touch zoom
+ private static float PREVIEW_SCALE_INCREMENT = 0.01f;
+
+ // the anchor point in the document space where VIEW_SIZE_CHANGED should
+ // apply to
+ private int mAnchorX;
+ private int mAnchorY;
+
/**
* Private message ids
*/
@@ -469,7 +484,7 @@
private static final int SWITCH_TO_LONGPRESS = 4;
private static final int RELEASE_SINGLE_TAP = 5;
private static final int REQUEST_FORM_DATA = 6;
- private static final int RESUME_WEBCORE_UPDATE = 7;
+ private static final int RESUME_WEBCORE_PRIORITY = 7;
private static final int DRAG_HELD_MOTIONLESS = 8;
private static final int AWAKEN_SCROLL_BARS = 9;
@@ -488,7 +503,7 @@
static final int MOVE_OUT_OF_PLUGIN = 19;
static final int CLEAR_TEXT_ENTRY = 20;
static final int UPDATE_TEXT_SELECTION_MSG_ID = 21;
-
+ static final int SHOW_RECT_MSG_ID = 22;
static final int LONG_PRESS_CENTER = 23;
static final int PREVENT_TOUCH_ID = 24;
static final int WEBCORE_NEED_TOUCH_EVENTS = 25;
@@ -510,7 +525,7 @@
"SWITCH_TO_LONGPRESS", // = 4;
"RELEASE_SINGLE_TAP", // = 5;
"REQUEST_FORM_DATA", // = 6;
- "RESUME_WEBCORE_UPDATE", // = 7;
+ "RESUME_WEBCORE_PRIORITY", // = 7;
"DRAG_HELD_MOTIONLESS", // = 8;
"AWAKEN_SCROLL_BARS", // = 9;
"SCROLL_TO_MSG_ID", // = 10;
@@ -525,7 +540,7 @@
"MOVE_OUT_OF_PLUGIN", // = 19;
"CLEAR_TEXT_ENTRY", // = 20;
"UPDATE_TEXT_SELECTION_MSG_ID", // = 21;
- "22", // = 22;
+ "SHOW_RECT_MSG_ID", // = 22;
"LONG_PRESS_CENTER", // = 23;
"PREVENT_TOUCH_ID", // = 24;
"WEBCORE_NEED_TOUCH_EVENTS", // = 25;
@@ -570,13 +585,13 @@
// ideally mZoomOverviewWidth should be mContentWidth. But sites like espn,
// engadget always have wider mContentWidth no matter what viewport size is.
int mZoomOverviewWidth = DEFAULT_VIEWPORT_WIDTH;
- float mLastScale;
+ float mTextWrapScale;
// default scale. Depending on the display density.
static int DEFAULT_SCALE_PERCENT;
private float mDefaultScale;
- // set to true temporarily while the zoom control is being dragged
+ // set to true temporarily during ScaleGesture triggered zoom
private boolean mPreviewZoomOnly = false;
// computed scale and inverse, from mZoomWidth.
@@ -803,6 +818,20 @@
params;
frameParams.gravity = Gravity.RIGHT;
}
+ updateMultiTouchSupport(context);
+ }
+
+ void updateMultiTouchSupport(Context context) {
+ WebSettings settings = getSettings();
+ mSupportMultiTouch = context.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)
+ && settings.supportZoom() && settings.getBuiltInZoomControls();
+ if (mSupportMultiTouch && (mScaleDetector == null)) {
+ mScaleDetector = new ScaleGestureDetector(context,
+ new ScaleDetectorListener());
+ } else if (!mSupportMultiTouch && (mScaleDetector != null)) {
+ mScaleDetector = null;
+ }
}
private void updateZoomButtonsEnabled() {
@@ -842,6 +871,7 @@
mDefaultScale = density;
mActualScale = density;
mInvActualScale = 1 / density;
+ mTextWrapScale = density;
DEFAULT_MAX_ZOOM_SCALE = 4.0f * density;
DEFAULT_MIN_ZOOM_SCALE = 0.25f * density;
mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE;
@@ -862,7 +892,7 @@
mDefaultScale = density;
mMaxZoomScale *= scaleFactor;
mMinZoomScale *= scaleFactor;
- setNewZoomScale(mActualScale * scaleFactor, false);
+ setNewZoomScale(mActualScale * scaleFactor, true, false);
}
}
@@ -1229,9 +1259,8 @@
b.putInt("scrollX", mScrollX);
b.putInt("scrollY", mScrollY);
b.putFloat("scale", mActualScale);
- if (mInZoomOverview) {
- b.putFloat("lastScale", mLastScale);
- }
+ b.putFloat("textwrapScale", mTextWrapScale);
+ b.putBoolean("overview", mInZoomOverview);
return true;
}
return false;
@@ -1276,13 +1305,8 @@
// onSizeChanged() is called, the rest will be set
// correctly
mActualScale = scale;
- float lastScale = b.getFloat("lastScale", -1.0f);
- if (lastScale > 0) {
- mInZoomOverview = true;
- mLastScale = lastScale;
- } else {
- mInZoomOverview = false;
- }
+ mTextWrapScale = b.getFloat("textwrapScale", scale);
+ mInZoomOverview = b.getBoolean("overview");
invalidate();
return true;
}
@@ -2012,12 +2036,18 @@
contentSizeChanged(updateLayout);
}
- private void setNewZoomScale(float scale, boolean force) {
+ private void setNewZoomScale(float scale, boolean updateTextWrapScale,
+ boolean force) {
if (scale < mMinZoomScale) {
scale = mMinZoomScale;
} else if (scale > mMaxZoomScale) {
scale = mMaxZoomScale;
}
+ if (updateTextWrapScale) {
+ mTextWrapScale = scale;
+ // reset mLastHeightSent to force VIEW_SIZE_CHANGED sent to WebKit
+ mLastHeightSent = 0;
+ }
if (scale != mActualScale || force) {
if (mDrawHistory) {
// If history Picture is drawn, don't update scroll. They will
@@ -2027,9 +2057,7 @@
}
mActualScale = scale;
mInvActualScale = 1 / scale;
- if (!mPreviewZoomOnly) {
- sendViewSizeZoom();
- }
+ sendViewSizeZoom();
} else {
// update our scroll so we don't appear to jump
// i.e. keep the center of the doc in the center of the view
@@ -2057,10 +2085,9 @@
mScrollX = pinLocX(Math.round(sx));
mScrollY = pinLocY(Math.round(sy));
- if (!mPreviewZoomOnly) {
- sendViewSizeZoom();
- sendOurVisibleRect();
- }
+ // update webkit
+ sendViewSizeZoom();
+ sendOurVisibleRect();
}
}
}
@@ -2070,6 +2097,8 @@
private Rect mLastGlobalRect;
private Rect sendOurVisibleRect() {
+ if (mPreviewZoomOnly) return mLastVisibleRectSent;
+
Rect rect = new Rect();
calcOurContentVisibleRect(rect);
// Rect.equals() checks for null input.
@@ -2123,6 +2152,8 @@
int mWidth;
int mHeight;
int mTextWrapWidth;
+ int mAnchorX;
+ int mAnchorY;
float mScale;
boolean mIgnoreHeight;
}
@@ -2134,6 +2165,8 @@
* @return true if new values were sent
*/
private boolean sendViewSizeZoom() {
+ if (mPreviewZoomOnly) return false;
+
int viewWidth = getViewWidth();
int newWidth = Math.round(viewWidth * mInvActualScale);
int newHeight = Math.round(getViewHeight() * mInvActualScale);
@@ -2153,16 +2186,15 @@
ViewSizeData data = new ViewSizeData();
data.mWidth = newWidth;
data.mHeight = newHeight;
- // while in zoom overview mode, the text are wrapped to the screen
- // width matching mLastScale. So that we don't trigger re-flow while
- // toggling between overview mode and normal mode.
- data.mTextWrapWidth = mInZoomOverview ? Math.round(viewWidth
- / mLastScale) : newWidth;
+ data.mTextWrapWidth = Math.round(viewWidth / mTextWrapScale);;
data.mScale = mActualScale;
data.mIgnoreHeight = mZoomScale != 0 && !mHeightCanMeasure;
+ data.mAnchorX = mAnchorX;
+ data.mAnchorY = mAnchorY;
mWebViewCore.sendMessage(EventHub.VIEW_SIZE_CHANGED, data);
mLastWidthSent = newWidth;
mLastHeightSent = newHeight;
+ mAnchorX = mAnchorY = 0;
return true;
}
return false;
@@ -3100,13 +3132,13 @@
canvas.scale(mActualScale, mActualScale);
}
- mWebViewCore.drawContentPicture(canvas, color, animateZoom,
- animateScroll);
+ mWebViewCore.drawContentPicture(canvas, color,
+ (animateZoom || mPreviewZoomOnly), animateScroll);
drawLayers(canvas);
if (mNativeClass == 0) return;
- if (mShiftIsPressed && !animateZoom) {
+ if (mShiftIsPressed && !(animateZoom || mPreviewZoomOnly)) {
if (mTouchSelection || mExtendSelection) {
nativeDrawSelectionRegion(canvas);
}
@@ -3227,10 +3259,14 @@
rebuildWebTextView();
if (!inEditingMode()) return;
imm.showSoftInput(mWebTextView, 0);
- if (mInZoomOverview) {
- // if in zoom overview mode, call doDoubleTap() to bring it back
- // to normal mode so that user can enter text.
- doDoubleTap();
+ // bring it back to the default scale so that user can enter text
+ if (mActualScale < mDefaultScale) {
+ mInZoomOverview = false;
+ mZoomCenterX = mLastTouchX;
+ mZoomCenterY = mLastTouchY;
+ // do not change text wrap scale so that there is no reflow
+ setNewZoomScale(mDefaultScale, false, false);
+ didUpdateTextViewBounds(true);
}
}
else { // used by plugins
@@ -3872,6 +3908,25 @@
return changed;
}
+ private static class PostScale implements Runnable {
+ final WebView mWebView;
+ final boolean mUpdateTextWrap;
+
+ public PostScale(WebView webView, boolean updateTextWrap) {
+ mWebView = webView;
+ mUpdateTextWrap = updateTextWrap;
+ }
+
+ public void run() {
+ if (mWebView.mWebViewCore != null) {
+ // we always force, in case our height changed, in which case we
+ // still want to send the notification over to webkit.
+ mWebView.setNewZoomScale(mWebView.mActualScale,
+ mUpdateTextWrap, true);
+ }
+ }
+ }
+
@Override
protected void onSizeChanged(int w, int h, int ow, int oh) {
super.onSizeChanged(w, h, ow, oh);
@@ -3879,6 +3934,8 @@
if (mZoomScale == 0) { // unless we're already zooming
mZoomCenterX = getViewWidth() * .5f;
mZoomCenterY = getViewHeight() * .5f;
+ mAnchorX = viewToContentX((int) mZoomCenterX + mScrollX);
+ mAnchorY = viewToContentY((int) mZoomCenterY + mScrollY);
}
// adjust the max viewport width depending on the view dimensions. This
@@ -3911,15 +3968,9 @@
// requestLayout() is blocked during layout. As setNewZoomScale() will
// call its child View to reposition itself through ViewManager's
// scaleAll(), we need to post a Runnable to ensure requestLayout().
- post(new Runnable() {
- public void run() {
- // we always force, in case our height changed, in which case we
- // still want to send the notification over to webkit
- if (mWebViewCore != null) {
- setNewZoomScale(mActualScale, true);
- }
- }
- });
+ // <b/>
+ // only update the text wrap scale if width changed.
+ post(new PostScale(this, w != ow));
}
@Override
@@ -4127,6 +4178,76 @@
private DragTracker mDragTracker;
private DragTrackerHandler mDragTrackerHandler;
+ private class ScaleDetectorListener implements
+ ScaleGestureDetector.OnScaleGestureListener {
+
+ public boolean onScaleBegin(ScaleGestureDetector detector) {
+ // cancel the single touch handling
+ cancelTouch();
+ if (mZoomButtonsController.isVisible()) {
+ mZoomButtonsController.setVisible(false);
+ }
+ // reset the zoom overview mode so that the page won't auto grow
+ mInZoomOverview = false;
+ // If it is in password mode, turn it off so it does not draw
+ // misplaced.
+ if (inEditingMode() && nativeFocusCandidateIsPassword()) {
+ mWebTextView.setInPassword(false);
+ }
+ return true;
+ }
+
+ public void onScaleEnd(ScaleGestureDetector detector) {
+ if (mPreviewZoomOnly) {
+ mPreviewZoomOnly = false;
+ mAnchorX = viewToContentX((int) mZoomCenterX + mScrollX);
+ mAnchorY = viewToContentY((int) mZoomCenterY + mScrollY);
+ // don't reflow when zoom in; when zoom out, do reflow if the
+ // new scale is almost minimum scale;
+ boolean reflowNow = (mActualScale - mMinZoomScale <= 0.01f)
+ || ((mActualScale <= 0.8 * mTextWrapScale));
+ // force zoom after mPreviewZoomOnly is set to false so that the
+ // new view size will be passed to the WebKit
+ setNewZoomScale(mActualScale, reflowNow, true);
+ // call invalidate() to draw without zoom filter
+ invalidate();
+ }
+ // adjust the edit text view if needed
+ if (inEditingMode() && didUpdateTextViewBounds(false)
+ && nativeFocusCandidateIsPassword()) {
+ // If it is a password field, start drawing the
+ // WebTextView once again.
+ mWebTextView.setInPassword(true);
+ }
+ // start a drag, TOUCH_PINCH_DRAG, can't use TOUCH_INIT_MODE as it
+ // may trigger the unwanted click, can't use TOUCH_DRAG_MODE as it
+ // may trigger the unwanted fling.
+ mTouchMode = TOUCH_PINCH_DRAG;
+ startTouch(detector.getFocusX(), detector.getFocusY(),
+ mLastTouchTime);
+ }
+
+ public boolean onScale(ScaleGestureDetector detector) {
+ float scale = (float) (Math.round(detector.getScaleFactor()
+ * mActualScale * 100) / 100.0);
+ if (Math.abs(scale - mActualScale) >= PREVIEW_SCALE_INCREMENT) {
+ mPreviewZoomOnly = true;
+ // limit the scale change per step
+ if (scale > mActualScale) {
+ scale = Math.min(scale, mActualScale * 1.25f);
+ } else {
+ scale = Math.max(scale, mActualScale * 0.8f);
+ }
+ mZoomCenterX = detector.getFocusX();
+ mZoomCenterY = detector.getFocusY();
+ setNewZoomScale(scale, false, false);
+ invalidate();
+ return true;
+ }
+ return false;
+ }
+ }
+
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (mNativeClass == 0 || !isClickable() || !isLongClickable()) {
@@ -4138,11 +4259,45 @@
+ mTouchMode);
}
- int action = ev.getAction();
- float x = ev.getX();
- float y = ev.getY();
+ int action;
+ float x, y;
long eventTime = ev.getEventTime();
+ // FIXME: we may consider to give WebKit an option to handle multi-touch
+ // events later.
+ if (mSupportMultiTouch && ev.getPointerCount() > 1) {
+ if (mMinZoomScale < mMaxZoomScale) {
+ mScaleDetector.onTouchEvent(ev);
+ if (mScaleDetector.isInProgress()) {
+ mLastTouchTime = eventTime;
+ return true;
+ }
+ x = mScaleDetector.getFocusX();
+ y = mScaleDetector.getFocusY();
+ action = ev.getAction() & MotionEvent.ACTION_MASK;
+ if (action == MotionEvent.ACTION_POINTER_DOWN) {
+ cancelTouch();
+ action = MotionEvent.ACTION_DOWN;
+ } else if (action == MotionEvent.ACTION_POINTER_UP) {
+ // set mLastTouchX/Y to the remaining point
+ mLastTouchX = x;
+ mLastTouchY = y;
+ } else if (action == MotionEvent.ACTION_MOVE) {
+ // negative x or y indicate it is on the edge, skip it.
+ if (x < 0 || y < 0) {
+ return true;
+ }
+ }
+ } else {
+ // if the page disallow zoom, skip multi-pointer action
+ return true;
+ }
+ } else {
+ action = ev.getAction();
+ x = ev.getX();
+ y = ev.getY();
+ }
+
// Due to the touch screen edge effect, a touch closer to the edge
// always snapped to the edge. As getViewWidth() can be different from
// getWidth() due to the scrollbar, adjusting the point to match
@@ -4179,7 +4334,7 @@
// fling's velocity
mScroller.abortAnimation();
mTouchMode = TOUCH_DRAG_START_MODE;
- mPrivateHandler.removeMessages(RESUME_WEBCORE_UPDATE);
+ mPrivateHandler.removeMessages(RESUME_WEBCORE_PRIORITY);
} else if (mShiftIsPressed) {
mSelectX = mScrollX + (int) x;
mSelectY = mScrollY + (int) y;
@@ -4201,6 +4356,7 @@
// continue, mTouchMode should be still TOUCH_INIT_MODE
}
} else {
+ mPreviewZoomOnly = false;
mTouchMode = TOUCH_INIT_MODE;
mPreventDrag = mForwardTouchEvents ? PREVENT_DRAG_MAYBE_YES
: PREVENT_DRAG_NO;
@@ -4219,16 +4375,7 @@
mPrivateHandler.sendMessageDelayed(mPrivateHandler
.obtainMessage(SWITCH_TO_SHORTPRESS), TAP_TIMEOUT);
}
- // Remember where the motion event started
- mLastTouchX = x;
- mLastTouchY = y;
- mLastTouchTime = eventTime;
- mVelocityTracker = VelocityTracker.obtain();
- mSnapScrollMode = SNAP_NONE;
- if (mDragTracker != null) {
- mDragTrackerHandler = new DragTrackerHandler(x, y,
- mDragTracker);
- }
+ startTouch(x, y, eventTime);
break;
}
case MotionEvent.ACTION_MOVE: {
@@ -4291,7 +4438,7 @@
deltaX = 0;
deltaY = 0;
- WebViewCore.pauseUpdate(mWebViewCore);
+ WebViewCore.reducePriority(mWebViewCore);
if (!mDragFromTextInput) {
nativeHideCursor();
}
@@ -4454,7 +4601,7 @@
|| computeVerticalScrollExtent() < computeVerticalScrollRange())) {
// we will not rewrite drag code here, but we
// will try fling if it applies.
- WebViewCore.pauseUpdate(mWebViewCore);
+ WebViewCore.reducePriority(mWebViewCore);
// fall through to TOUCH_DRAG_MODE
} else {
break;
@@ -4494,7 +4641,7 @@
break;
}
mLastVelocity = 0;
- WebViewCore.resumeUpdate(mWebViewCore);
+ WebViewCore.resumePriority(mWebViewCore);
break;
case TOUCH_DRAG_START_MODE:
case TOUCH_DONE_MODE:
@@ -4511,33 +4658,49 @@
break;
}
case MotionEvent.ACTION_CANCEL: {
- if (mDragTrackerHandler != null) {
- mDragTrackerHandler.stopDrag();
- mDragTrackerHandler = null;
- }
- // we also use mVelocityTracker == null to tell us that we are
- // not "moving around", so we can take the slower/prettier
- // mode in the drawing code
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
- if (mTouchMode == TOUCH_DRAG_MODE) {
- WebViewCore.resumeUpdate(mWebViewCore);
- }
- mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
- mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
- mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS);
- mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
- mHeldMotionless = MOTIONLESS_TRUE;
- mTouchMode = TOUCH_DONE_MODE;
- nativeHideCursor();
+ cancelTouch();
break;
}
}
return true;
}
+ private void startTouch(float x, float y, long eventTime) {
+ // Remember where the motion event started
+ mLastTouchX = x;
+ mLastTouchY = y;
+ mLastTouchTime = eventTime;
+ mVelocityTracker = VelocityTracker.obtain();
+ mSnapScrollMode = SNAP_NONE;
+ if (mDragTracker != null) {
+ mDragTrackerHandler = new DragTrackerHandler(x, y, mDragTracker);
+ }
+ }
+
+ private void cancelTouch() {
+ if (mDragTrackerHandler != null) {
+ mDragTrackerHandler.stopDrag();
+ mDragTrackerHandler = null;
+ }
+ // we also use mVelocityTracker == null to tell us that we are
+ // not "moving around", so we can take the slower/prettier
+ // mode in the drawing code
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
+ if (mTouchMode == TOUCH_DRAG_MODE) {
+ WebViewCore.resumePriority(mWebViewCore);
+ }
+ mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
+ mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
+ mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS);
+ mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
+ mHeldMotionless = MOTIONLESS_TRUE;
+ mTouchMode = TOUCH_DONE_MODE;
+ nativeHideCursor();
+ }
+
private long mTrackballFirstTime = 0;
private long mTrackballLastTime = 0;
private float mTrackballRemainsX = 0.0f;
@@ -4853,7 +5016,7 @@
vy = vy * 3 / 4;
}
if ((maxX == 0 && vy == 0) || (maxY == 0 && vx == 0)) {
- WebViewCore.resumeUpdate(mWebViewCore);
+ WebViewCore.resumePriority(mWebViewCore);
return;
}
float currentVelocity = mScroller.getCurrVelocity();
@@ -4887,7 +5050,7 @@
// want to calculate how long the animation is going to run to precisely
// resume the webcore update.
final int time = mScroller.getDuration();
- mPrivateHandler.sendEmptyMessageDelayed(RESUME_WEBCORE_UPDATE, time);
+ mPrivateHandler.sendEmptyMessageDelayed(RESUME_WEBCORE_PRIORITY, time);
awakenScrollBars(time);
invalidate();
}
@@ -4902,7 +5065,7 @@
scale = mDefaultScale;
}
- setNewZoomScale(scale, false);
+ setNewZoomScale(scale, true, false);
if (oldScale != mActualScale) {
// use mZoomPickerScale to see zoom preview first
@@ -4910,9 +5073,6 @@
mInvInitialZoomScale = 1.0f / oldScale;
mInvFinalZoomScale = 1.0f / mActualScale;
mZoomScale = mActualScale;
- if (!mInZoomOverview) {
- mLastScale = scale;
- }
invalidate();
return true;
} else {
@@ -5010,18 +5170,13 @@
public boolean zoomIn() {
// TODO: alternatively we can disallow this during draw history mode
switchOutDrawHistory();
+ mInZoomOverview = false;
// Center zooming to the center of the screen.
- if (mInZoomOverview) {
- // if in overview mode, bring it back to normal mode
- mLastTouchX = getViewWidth() * .5f;
- mLastTouchY = getViewHeight() * .5f;
- doDoubleTap();
- return true;
- } else {
- mZoomCenterX = getViewWidth() * .5f;
- mZoomCenterY = getViewHeight() * .5f;
- return zoomWithPreview(mActualScale * 1.25f);
- }
+ mZoomCenterX = getViewWidth() * .5f;
+ mZoomCenterY = getViewHeight() * .5f;
+ mAnchorX = viewToContentX((int) mZoomCenterX + mScrollX);
+ mAnchorY = viewToContentY((int) mZoomCenterY + mScrollY);
+ return zoomWithPreview(mActualScale * 1.25f);
}
/**
@@ -5031,20 +5186,12 @@
public boolean zoomOut() {
// TODO: alternatively we can disallow this during draw history mode
switchOutDrawHistory();
- float scale = mActualScale * 0.8f;
- if (scale < (mMinZoomScale + 0.1f)
- && mWebViewCore.getSettings().getUseWideViewPort()
- && mZoomOverviewWidth > Math.ceil(getViewWidth()
- * mInvActualScale)) {
- // when zoom out to min scale, switch to overview mode
- doDoubleTap();
- return true;
- } else {
- // Center zooming to the center of the screen.
- mZoomCenterX = getViewWidth() * .5f;
- mZoomCenterY = getViewHeight() * .5f;
- return zoomWithPreview(scale);
- }
+ // Center zooming to the center of the screen.
+ mZoomCenterX = getViewWidth() * .5f;
+ mZoomCenterY = getViewHeight() * .5f;
+ mAnchorX = viewToContentX((int) mZoomCenterX + mScrollX);
+ mAnchorY = viewToContentY((int) mZoomCenterY + mScrollY);
+ return zoomWithPreview(mActualScale * 0.8f);
}
private void updateSelection() {
@@ -5088,7 +5235,7 @@
mLastTouchTime = eventTime;
if (!mScroller.isFinished()) {
abortAnimation();
- mPrivateHandler.removeMessages(RESUME_WEBCORE_UPDATE);
+ mPrivateHandler.removeMessages(RESUME_WEBCORE_PRIORITY);
}
mSnapScrollMode = SNAP_NONE;
mVelocityTracker = VelocityTracker.obtain();
@@ -5168,15 +5315,21 @@
}
}
+ // Rule for double tap:
+ // 1. if the current scale is not same as the text wrap scale and layout
+ // algorithm is NARROW_COLUMNS, fit to column;
+ // 2. if the current state is not overview mode, change to overview mode;
+ // 3. if the current state is overview mode, change to default scale.
private void doDoubleTap() {
if (mWebViewCore.getSettings().getUseWideViewPort() == false) {
return;
}
mZoomCenterX = mLastTouchX;
mZoomCenterY = mLastTouchY;
- mInZoomOverview = !mInZoomOverview;
- // remove the zoom control after double tap
+ mAnchorX = viewToContentX((int) mZoomCenterX + mScrollX);
+ mAnchorY = viewToContentY((int) mZoomCenterY + mScrollY);
WebSettings settings = getSettings();
+ // remove the zoom control after double tap
if (settings.getBuiltInZoomControls()) {
if (mZoomButtonsController.isVisible()) {
mZoomButtonsController.setVisible(false);
@@ -5190,28 +5343,45 @@
}
}
settings.setDoubleTapToastCount(0);
- if (mInZoomOverview) {
+ boolean zoomToDefault = false;
+ if ((settings.getLayoutAlgorithm() == WebSettings.LayoutAlgorithm.NARROW_COLUMNS)
+ && (Math.abs(mActualScale - mTextWrapScale) >= 0.01f)) {
+ setNewZoomScale(mActualScale, true, true);
+ float overviewScale = (float) getViewWidth() / mZoomOverviewWidth;
+ if (Math.abs(mActualScale - overviewScale) < 0.01f) {
+ mInZoomOverview = true;
+ }
+ } else if (!mInZoomOverview) {
float newScale = (float) getViewWidth() / mZoomOverviewWidth;
- if (Math.abs(mActualScale - newScale) < 0.01f) {
- // reset mInZoomOverview to false if scale doesn't change
- mInZoomOverview = false;
- } else {
+ if (Math.abs(mActualScale - newScale) >= 0.01f) {
+ mInZoomOverview = true;
// Force the titlebar fully reveal in overview mode
if (mScrollY < getTitleHeight()) mScrollY = 0;
zoomWithPreview(newScale);
+ } else if (Math.abs(mActualScale - mDefaultScale) >= 0.01f) {
+ zoomToDefault = true;
}
} else {
- // mLastTouchX and mLastTouchY are the point in the current viewport
- int contentX = viewToContentX((int) mLastTouchX + mScrollX);
- int contentY = viewToContentY((int) mLastTouchY + mScrollY);
- int left = nativeGetBlockLeftEdge(contentX, contentY, mActualScale);
+ zoomToDefault = true;
+ }
+ if (zoomToDefault) {
+ mInZoomOverview = false;
+ int left = nativeGetBlockLeftEdge(mAnchorX, mAnchorY, mActualScale);
if (left != NO_LEFTEDGE) {
- // add a 5pt padding to the left edge. Re-calculate the zoom
- // center so that the new scroll x will be on the left edge.
- mZoomCenterX = left < 5 ? 0 : (left - 5) * mLastScale
- * mActualScale / (mLastScale - mActualScale);
+ // add a 5pt padding to the left edge.
+ int viewLeft = contentToViewX(left < 5 ? 0 : (left - 5))
+ - mScrollX;
+ // Re-calculate the zoom center so that the new scroll x will be
+ // on the left edge.
+ if (viewLeft > 0) {
+ mZoomCenterX = viewLeft * mDefaultScale
+ / (mDefaultScale - mActualScale);
+ } else {
+ scrollBy(viewLeft, 0);
+ mZoomCenterX = 0;
+ }
}
- zoomWithPreview(mLastScale);
+ zoomWithPreview(mDefaultScale);
}
}
@@ -5503,9 +5673,6 @@
boolean hasRestoreState = restoreState != null;
if (hasRestoreState) {
mInZoomOverview = false;
- mLastScale = mInitialScaleInPercent > 0
- ? mInitialScaleInPercent / 100.0f
- : restoreState.mTextWrapScale;
if (restoreState.mMinScale == 0) {
if (restoreState.mMobileSite) {
if (draw.mMinPrefWidth >
@@ -5513,6 +5680,8 @@
mMinZoomScale = (float) viewWidth
/ draw.mMinPrefWidth;
mMinZoomScaleFixed = false;
+ mInZoomOverview = useWideViewport &&
+ settings.getLoadWithOverviewMode();
} else {
mMinZoomScale = restoreState.mDefaultScale;
mMinZoomScaleFixed = true;
@@ -5530,17 +5699,29 @@
} else {
mMaxZoomScale = restoreState.mMaxScale;
}
- setNewZoomScale(mLastScale, false);
+ if (mInitialScaleInPercent > 0) {
+ setNewZoomScale(mInitialScaleInPercent / 100.0f,
+ mInitialScaleInPercent != mTextWrapScale * 100,
+ false);
+ } else if (restoreState.mViewScale > 0) {
+ mTextWrapScale = restoreState.mTextWrapScale;
+ setNewZoomScale(restoreState.mViewScale, false,
+ false);
+ } else {
+ mInZoomOverview = useWideViewport
+ && settings.getLoadWithOverviewMode();
+ float scale;
+ if (mInZoomOverview) {
+ scale = (float) viewWidth
+ / DEFAULT_VIEWPORT_WIDTH;
+ } else {
+ scale = restoreState.mTextWrapScale;
+ }
+ setNewZoomScale(scale, Math.abs(scale
+ - mTextWrapScale) >= 0.01f, false);
+ }
setContentScrollTo(restoreState.mScrollX,
restoreState.mScrollY);
- if (useWideViewport
- && settings.getLoadWithOverviewMode()) {
- if (restoreState.mViewScale == 0
- || (restoreState.mMobileSite
- && mMinZoomScale < restoreState.mDefaultScale)) {
- mInZoomOverview = true;
- }
- }
// As we are on a new page, remove the WebTextView. This
// is necessary for page loads driven by webkit, and in
// particular when the user was on a password field, so
@@ -5570,11 +5751,14 @@
mPictureListener.onNewPicture(WebView.this, capturePicture());
}
if (useWideViewport) {
- // limit mZoomOverviewWidth to sMaxViewportWidth so that
- // if the page doesn't behave well, the WebView won't go
- // insane.
+ // limit mZoomOverviewWidth upper bound to
+ // sMaxViewportWidth so that if the page doesn't behave
+ // well, the WebView won't go insane. limit the lower
+ // bound to match the default scale for mobile sites.
mZoomOverviewWidth = Math.min(sMaxViewportWidth, Math
- .max(draw.mMinPrefWidth, draw.mViewPoint.x));
+ .max((int) (viewWidth / mDefaultScale), Math
+ .max(draw.mMinPrefWidth,
+ draw.mViewPoint.x)));
}
if (!mMinZoomScaleFixed) {
mMinZoomScale = (float) viewWidth / mZoomOverviewWidth;
@@ -5585,7 +5769,8 @@
if (Math.abs((viewWidth * mInvActualScale)
- mZoomOverviewWidth) > 1) {
setNewZoomScale((float) viewWidth
- / mZoomOverviewWidth, false);
+ / mZoomOverviewWidth, Math.abs(mActualScale
+ - mTextWrapScale) < 0.01f, false);
}
}
if (draw.mFocusSizeChanged && inEditingMode()) {
@@ -5710,8 +5895,8 @@
mWebTextView.setAdapterCustom(adapter);
}
break;
- case RESUME_WEBCORE_UPDATE:
- WebViewCore.resumeUpdate(mWebViewCore);
+ case RESUME_WEBCORE_PRIORITY:
+ WebViewCore.resumePriority(mWebViewCore);
break;
case LONG_PRESS_CENTER:
@@ -5789,7 +5974,7 @@
doMotionUp(msg.arg1, msg.arg2);
break;
- case SHOW_FULLSCREEN:
+ case SHOW_FULLSCREEN: {
WebViewCore.PluginFullScreenData data
= (WebViewCore.PluginFullScreenData) msg.obj;
if (data.mNpp != 0 && data.mView != null) {
@@ -5837,15 +6022,19 @@
if (width > viewWidth || height > viewHeight) {
mZoomCenterX = viewWidth * .5f;
mZoomCenterY = viewHeight * .5f;
+ // do not change text wrap scale so that there is no
+ // reflow
setNewZoomScale(mActualScale
/ Math.max((float) width / viewWidth,
- (float) height / viewHeight), false);
+ (float) height / viewHeight), false,
+ false);
}
// Now update the bound
mFullScreenHolder.updateBound(contentToViewX(data.mDocX)
- mScrollX, contentToViewY(data.mDocY) - mScrollY,
contentToViewDimension(data.mDocWidth),
contentToViewDimension(data.mDocHeight));
+ }
break;
case HIDE_FULLSCREEN:
@@ -5862,6 +6051,44 @@
}
break;
+ case SHOW_RECT_MSG_ID: {
+ WebViewCore.ShowRectData data = (WebViewCore.ShowRectData) msg.obj;
+ int x = mScrollX;
+ int left = contentToViewDimension(data.mLeft);
+ int width = contentToViewDimension(data.mWidth);
+ int maxWidth = contentToViewDimension(data.mContentWidth);
+ int viewWidth = getViewWidth();
+ if (width < viewWidth) {
+ // center align
+ x += left + width / 2 - mScrollX - viewWidth / 2;
+ } else {
+ x += (int) (left + data.mXPercentInDoc * width
+ - mScrollX - data.mXPercentInView * viewWidth);
+ }
+ // use the passing content width to cap x as the current
+ // mContentWidth may not be updated yet
+ x = Math.max(0,
+ (Math.min(maxWidth, x + viewWidth)) - viewWidth);
+ int y = mScrollY;
+ int top = contentToViewDimension(data.mTop);
+ int height = contentToViewDimension(data.mHeight);
+ int maxHeight = contentToViewDimension(data.mContentHeight);
+ int viewHeight = getViewHeight();
+ if (height < viewHeight) {
+ // middle align
+ y += top + height / 2 - mScrollY - viewHeight / 2;
+ } else {
+ y += (int) (top + data.mYPercentInDoc * height
+ - mScrollY - data.mYPercentInView * viewHeight);
+ }
+ // use the passing content height to cap y as the current
+ // mContentHeight may not be updated yet
+ y = Math.max(0,
+ (Math.min(maxHeight, y + viewHeight) - viewHeight));
+ scrollTo(x, y);
+ }
+ break;
+
default:
super.handleMessage(msg);
break;
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index d509bb4..6700d71 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -482,8 +482,8 @@
should this be called nativeSetViewPortSize?
*/
private native void nativeSetSize(int width, int height, int screenWidth,
- float scale, int realScreenWidth, int screenHeight,
- boolean ignoreHeight);
+ float scale, int realScreenWidth, int screenHeight, int anchorX,
+ int anchorY, boolean ignoreHeight);
private native int nativeGetContentMinPrefWidth();
@@ -1033,6 +1033,7 @@
(WebView.ViewSizeData) msg.obj;
viewSizeChanged(data.mWidth, data.mHeight,
data.mTextWrapWidth, data.mScale,
+ data.mAnchorX, data.mAnchorY,
data.mIgnoreHeight);
break;
}
@@ -1584,7 +1585,7 @@
// notify webkit that our virtual view size changed size (after inv-zoom)
private void viewSizeChanged(int w, int h, int textwrapWidth, float scale,
- boolean ignoreHeight) {
+ int anchorX, int anchorY, boolean ignoreHeight) {
if (DebugFlags.WEB_VIEW_CORE) {
Log.v(LOGTAG, "viewSizeChanged w=" + w + "; h=" + h
+ "; textwrapWidth=" + textwrapWidth + "; scale=" + scale);
@@ -1616,12 +1617,14 @@
Math.max(WebView.DEFAULT_VIEWPORT_WIDTH,
nativeGetContentMinPrefWidth())));
}
- } else {
+ } else if (mViewportWidth > 0) {
width = Math.max(w, mViewportWidth);
+ } else {
+ width = textwrapWidth;
}
}
nativeSetSize(width, width == w ? h : Math.round((float) width * h / w),
- textwrapWidth, scale, w, h, ignoreHeight);
+ textwrapWidth, scale, w, h, anchorX, anchorY, ignoreHeight);
// Remember the current width and height
boolean needInvalidate = (mCurrentViewWidth == 0);
mCurrentViewWidth = w;
@@ -1778,7 +1781,7 @@
return result;
}
- static void pauseUpdate(WebViewCore core) {
+ static void reducePriority(WebViewCore core) {
// remove the pending REDUCE_PRIORITY and RESUME_PRIORITY messages
sWebCoreHandler.removeMessages(WebCoreThread.REDUCE_PRIORITY);
sWebCoreHandler.removeMessages(WebCoreThread.RESUME_PRIORITY);
@@ -1786,7 +1789,7 @@
.obtainMessage(WebCoreThread.REDUCE_PRIORITY));
}
- static void resumeUpdate(WebViewCore core) {
+ static void resumePriority(WebViewCore core) {
// remove the pending REDUCE_PRIORITY and RESUME_PRIORITY messages
sWebCoreHandler.removeMessages(WebCoreThread.REDUCE_PRIORITY);
sWebCoreHandler.removeMessages(WebCoreThread.RESUME_PRIORITY);
@@ -2070,14 +2073,12 @@
mRestoreState.mScrollY = mRestoredY;
mRestoreState.mMobileSite = (0 == mViewportWidth);
if (mRestoredScale > 0) {
+ mRestoreState.mViewScale = mRestoredScale / 100.0f;
if (mRestoredScreenWidthScale > 0) {
mRestoreState.mTextWrapScale =
mRestoredScreenWidthScale / 100.0f;
- // 0 will trigger WebView to turn on zoom overview mode
- mRestoreState.mViewScale = 0;
} else {
- mRestoreState.mViewScale = mRestoreState.mTextWrapScale =
- mRestoredScale / 100.0f;
+ mRestoreState.mTextWrapScale = mRestoreState.mViewScale;
}
} else {
if (mViewportInitialScale > 0) {
@@ -2110,6 +2111,7 @@
data.mTextWrapWidth = data.mWidth;
data.mScale = -1.0f;
data.mIgnoreHeight = false;
+ data.mAnchorX = data.mAnchorY = 0;
// send VIEW_SIZE_CHANGED to the front of the queue so that we can
// avoid pushing the wrong picture to the WebView side. If there is
// a VIEW_SIZE_CHANGED in the queue, probably from WebView side,
@@ -2145,6 +2147,7 @@
data.mTextWrapWidth = Math.round(webViewWidth
/ mRestoreState.mTextWrapScale);
data.mIgnoreHeight = false;
+ data.mAnchorX = data.mAnchorY = 0;
// send VIEW_SIZE_CHANGED to the front of the queue so that we
// can avoid pushing the wrong picture to the WebView side.
mEventHub.removeMessages(EventHub.VIEW_SIZE_CHANGED);
@@ -2364,6 +2367,40 @@
childView.removeView();
}
+ // called by JNI
+ static class ShowRectData {
+ int mLeft;
+ int mTop;
+ int mWidth;
+ int mHeight;
+ int mContentWidth;
+ int mContentHeight;
+ float mXPercentInDoc;
+ float mXPercentInView;
+ float mYPercentInDoc;
+ float mYPercentInView;
+ }
+
+ private void showRect(int left, int top, int width, int height,
+ int contentWidth, int contentHeight, float xPercentInDoc,
+ float xPercentInView, float yPercentInDoc, float yPercentInView) {
+ if (mWebView != null) {
+ ShowRectData data = new ShowRectData();
+ data.mLeft = left;
+ data.mTop = top;
+ data.mWidth = width;
+ data.mHeight = height;
+ data.mContentWidth = contentWidth;
+ data.mContentHeight = contentHeight;
+ data.mXPercentInDoc = xPercentInDoc;
+ data.mXPercentInView = xPercentInView;
+ data.mYPercentInDoc = yPercentInDoc;
+ data.mYPercentInView = yPercentInView;
+ Message.obtain(mWebView.mPrivateHandler, WebView.SHOW_RECT_MSG_ID,
+ data).sendToTarget();
+ }
+ }
+
private native void nativePause();
private native void nativeResume();
private native void nativeFreeMemory();
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index bb7677df..2f61cbe 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -166,6 +166,7 @@
OMX_U32 flags;
OMX_TICKS timestamp;
OMX_PTR platform_private;
+ OMX_PTR data_ptr;
} extended_buffer_data;
} u;
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index ac2f662..82dd2b5 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -94,6 +94,7 @@
kRequiresFlushCompleteEmulation = 16,
kRequiresAllocateBufferOnOutputPorts = 32,
kRequiresFlushBeforeShutdown = 64,
+ kDefersOutputBufferAllocation = 128,
};
struct BufferInfo {
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 2686489..986dcb2 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -301,8 +301,8 @@
quirks |= kRequiresAllocateBufferOnOutputPorts;
}
if (!strncmp(componentName, "OMX.qcom.video.decoder.", 23)) {
- // XXX Required on P....on only.
quirks |= kRequiresAllocateBufferOnOutputPorts;
+ quirks |= kDefersOutputBufferAllocation;
}
if (!strncmp(componentName, "OMX.TI.", 7)) {
@@ -1237,8 +1237,15 @@
info.mMediaBuffer = NULL;
if (portIndex == kPortIndexOutput) {
- info.mMediaBuffer = new MediaBuffer(info.mData, info.mSize);
- info.mMediaBuffer->setObserver(this);
+ if (!(mOMXLivesLocally
+ && (mQuirks & kRequiresAllocateBufferOnOutputPorts)
+ && (mQuirks & kDefersOutputBufferAllocation))) {
+ // If the node does not fill in the buffer ptr at this time,
+ // we will defer creating the MediaBuffer until receiving
+ // the first FILL_BUFFER_DONE notification instead.
+ info.mMediaBuffer = new MediaBuffer(info.mData, info.mSize);
+ info.mMediaBuffer->setObserver(this);
+ }
}
mPortBuffers[portIndex].push(info);
@@ -1346,6 +1353,22 @@
} else if (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) {
CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
+ if (info->mMediaBuffer == NULL) {
+ CHECK(mOMXLivesLocally);
+ CHECK(mQuirks & kRequiresAllocateBufferOnOutputPorts);
+ CHECK(mQuirks & kDefersOutputBufferAllocation);
+
+ // The qcom video decoders on Nexus don't actually allocate
+ // output buffer memory on a call to OMX_AllocateBuffer
+ // the "pBuffer" member of the OMX_BUFFERHEADERTYPE
+ // structure is only filled in later.
+
+ info->mMediaBuffer = new MediaBuffer(
+ msg.u.extended_buffer_data.data_ptr,
+ info->mSize);
+ info->mMediaBuffer->setObserver(this);
+ }
+
MediaBuffer *buffer = info->mMediaBuffer;
buffer->set_range(
diff --git a/media/libstagefright/SampleIterator.cpp b/media/libstagefright/SampleIterator.cpp
index faad42ba..7155c61 100644
--- a/media/libstagefright/SampleIterator.cpp
+++ b/media/libstagefright/SampleIterator.cpp
@@ -54,6 +54,10 @@
status_t SampleIterator::seekTo(uint32_t sampleIndex) {
LOGV("seekTo(%d)", sampleIndex);
+ if (sampleIndex >= mTable->mNumSampleSizes) {
+ return ERROR_END_OF_STREAM;
+ }
+
if (mTable->mSampleToChunkOffset < 0
|| mTable->mChunkOffsetOffset < 0
|| mTable->mSampleSizeOffset < 0
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index 313a9ed..dfba74f 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -276,8 +276,6 @@
}
const char *StagefrightMetadataRetriever::extractMetadata(int keyCode) {
- LOGV("extractMetadata %d", keyCode);
-
if (mExtractor == NULL) {
return NULL;
}
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 918d055c..9ca060d 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -365,6 +365,7 @@
msg.u.extended_buffer_data.flags = pBuffer->nFlags;
msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp;
msg.u.extended_buffer_data.platform_private = pBuffer->pPlatformPrivate;
+ msg.u.extended_buffer_data.data_ptr = pBuffer->pBuffer;
mDispatcher->post(msg);
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index c22c21b..d2f8ced 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -1111,10 +1111,10 @@
if (cur_c == NULL) {
// no current context
if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
- // calling eglMakeCurrent( ..., EGL_NO_CONTEXT, !=0, !=0);
- return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+ // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
+ return setError(EGL_BAD_MATCH, EGL_FALSE);
}
- // not an error, there is just not current context.
+ // not an error, there is just no current context.
return EGL_TRUE;
}
}