diff options
Diffstat (limited to 'core/java')
| -rwxr-xr-x | core/java/android/hardware/input/InputManager.java | 4 | ||||
| -rw-r--r-- | core/java/android/os/Build.java | 4 | ||||
| -rw-r--r-- | core/java/android/text/style/TextAppearanceSpan.java | 41 | ||||
| -rw-r--r-- | core/java/android/util/TimeUtils.java | 19 | ||||
| -rw-r--r-- | core/java/android/view/GLES20DisplayList.java | 3 | ||||
| -rw-r--r-- | core/java/android/view/TextureView.java | 12 | ||||
| -rw-r--r-- | core/java/android/view/VelocityTracker.java | 18 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 101 | ||||
| -rw-r--r-- | core/java/android/webkit/HTML5VideoFullScreen.java | 18 | ||||
| -rw-r--r-- | core/java/android/webkit/HTML5VideoInline.java | 14 | ||||
| -rw-r--r-- | core/java/android/webkit/HTML5VideoView.java | 86 | ||||
| -rw-r--r-- | core/java/android/webkit/HTML5VideoViewProxy.java | 23 | ||||
| -rw-r--r-- | core/java/android/webkit/WebViewInputDispatcher.java | 2 | ||||
| -rw-r--r-- | core/java/android/widget/SpellChecker.java | 44 | ||||
| -rw-r--r-- | core/java/android/widget/TextView.java | 34 |
15 files changed, 326 insertions, 97 deletions
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java index 5ba1850..6448b55 100755 --- a/core/java/android/hardware/input/InputManager.java +++ b/core/java/android/hardware/input/InputManager.java @@ -96,14 +96,14 @@ public final class InputManager { * <keyboard-layouts xmlns:android="http://schemas.android.com/apk/res/android"> * <keyboard-layout android:name="keyboard_layout_english_us" * android:label="@string/keyboard_layout_english_us_label" - * android:kcm="@raw/keyboard_layout_english_us" /> + * android:keyboardLayout="@raw/keyboard_layout_english_us" /> * </keyboard-layouts> * </p><p> * The <code>android:name</code> attribute specifies an identifier by which * the keyboard layout will be known in the package. * The <code>android:label</code> attributes specifies a human-readable descriptive * label to describe the keyboard layout in the user interface, such as "English (US)". - * The <code>android:kcm</code> attribute refers to a + * The <code>android:keyboardLayout</code> attribute refers to a * <a href="http://source.android.com/tech/input/key-character-map-files.html"> * key character map</a> resource that defines the keyboard layout. * </p> diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 63275cf..2d5b625 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -370,7 +370,7 @@ public class Build { public static final int ICE_CREAM_SANDWICH_MR1 = 15; /** - * Next up on Android! + * Android 4.1. * * <p>Applications targeting this or a later release will get these * new changes in behavior:</p> @@ -381,7 +381,7 @@ public class Build { * exist in the application's manifest. * </ul> */ - public static final int JELLY_BEAN = CUR_DEVELOPMENT; + public static final int JELLY_BEAN = 16; } /** The type of build, like "user" or "eng". */ diff --git a/core/java/android/text/style/TextAppearanceSpan.java b/core/java/android/text/style/TextAppearanceSpan.java index 5fd7c57..ecbf4bc 100644 --- a/core/java/android/text/style/TextAppearanceSpan.java +++ b/core/java/android/text/style/TextAppearanceSpan.java @@ -68,24 +68,29 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl TextAppearance_textSize, -1); mStyle = a.getInt(com.android.internal.R.styleable.TextAppearance_textStyle, 0); - int tf = a.getInt(com.android.internal.R.styleable.TextAppearance_typeface, 0); - - switch (tf) { - case 1: - mTypeface = "sans"; - break; - - case 2: - mTypeface = "serif"; - break; - - case 3: - mTypeface = "monospace"; - break; - - default: - mTypeface = null; - break; + String family = a.getString(com.android.internal.R.styleable.TextAppearance_fontFamily); + if (family != null) { + mTypeface = family; + } else { + int tf = a.getInt(com.android.internal.R.styleable.TextAppearance_typeface, 0); + + switch (tf) { + case 1: + mTypeface = "sans"; + break; + + case 2: + mTypeface = "serif"; + break; + + case 3: + mTypeface = "monospace"; + break; + + default: + mTypeface = null; + break; + } } a.recycle(); diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java index 2883eca..c4ebec4 100644 --- a/core/java/android/util/TimeUtils.java +++ b/core/java/android/util/TimeUtils.java @@ -26,6 +26,7 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Calendar; import java.util.Collection; import java.util.TimeZone; import java.util.Date; @@ -381,4 +382,22 @@ public class TimeUtils { } formatDuration(time-now, pw, 0); } + + /** + * Convert a System.currentTimeMillis() value to a time of day value like + * that printed in logs. MM-DD HH:MM:SS.MMM + * + * @param millis since the epoch (1/1/1970) + * @return String representation of the time. + * @hide + */ + public static String logTimeOfDay(long millis) { + Calendar c = Calendar.getInstance(); + if (millis >= 0) { + c.setTimeInMillis(millis); + return String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c); + } else { + return Long.toString(millis); + } + } } diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java index f3618eb..0154556 100644 --- a/core/java/android/view/GLES20DisplayList.java +++ b/core/java/android/view/GLES20DisplayList.java @@ -131,7 +131,8 @@ class GLES20DisplayList extends DisplayList { @Override public void setAnimationMatrix(Matrix matrix) { try { - nSetAnimationMatrix(getNativeDisplayList(), matrix.native_instance); + nSetAnimationMatrix(getNativeDisplayList(), + (matrix != null) ? matrix.native_instance : 0); } catch (IllegalStateException e) { // invalid DisplayList okay: we'll set current values the next time we render to it } diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java index 651be2e..2048de2 100644 --- a/core/java/android/view/TextureView.java +++ b/core/java/android/view/TextureView.java @@ -561,7 +561,17 @@ public class TextureView extends View { applyUpdate(); applyTransformMatrix(); - mLayer.copyInto(bitmap); + // This case can happen if the app invokes setSurfaceTexture() before + // we are able to create the hardware layer. We can safely initialize + // the layer here thanks to the validate() call at the beginning of + // this method + if (mLayer == null && mUpdateSurface) { + getHardwareLayer(); + } + + if (mLayer != null) { + mLayer.copyInto(bitmap); + } } return bitmap; } diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java index 1c35e31..f703e34 100644 --- a/core/java/android/view/VelocityTracker.java +++ b/core/java/android/view/VelocityTracker.java @@ -298,6 +298,24 @@ public final class VelocityTracker implements Poolable<VelocityTracker> { return estimate(time, yCoeff); } + /** + * Gets the X coefficient with the specified index. + * @param index The index of the coefficient to return. + * @return The X coefficient, or 0 if the index is greater than the degree. + */ + public float getXCoeff(int index) { + return index <= degree ? xCoeff[index] : 0; + } + + /** + * Gets the Y coefficient with the specified index. + * @param index The index of the coefficient to return. + * @return The Y coefficient, or 0 if the index is greater than the degree. + */ + public float getYCoeff(int index) { + return index <= degree ? yCoeff[index] : 0; + } + private float estimate(float time, float[] c) { float a = 0; float scale = 1; diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index bf7d037..55ea938 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -2128,6 +2128,20 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal */ static final int ACCESSIBILITY_STATE_CHANGED = 0x00000080 << IMPORTANT_FOR_ACCESSIBILITY_SHIFT; + /** + * Flag indicating that view has an animation set on it. This is used to track whether an + * animation is cleared between successive frames, in order to tell the associated + * DisplayList to clear its animation matrix. + */ + static final int VIEW_IS_ANIMATING_TRANSFORM = 0x10000000; + + /** + * Flag indicating whether a view failed the quickReject() check in draw(). This condition + * is used to check whether later changes to the view's transform should invalidate the + * view to force the quickReject test to run again. + */ + static final int VIEW_QUICK_REJECTED = 0x20000000; + /* End of masks for mPrivateFlags2 */ static final int DRAG_MASK = DRAG_CAN_ACCEPT | DRAG_HOVERED; @@ -8560,6 +8574,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal if (mDisplayList != null) { mDisplayList.setCameraDistance(-Math.abs(distance) / dpi); } + if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) { + // View was rejected last time it was drawn by its parent; this may have changed + invalidateParentIfNeeded(); + } } /** @@ -8602,6 +8620,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal if (mDisplayList != null) { mDisplayList.setRotation(rotation); } + if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) { + // View was rejected last time it was drawn by its parent; this may have changed + invalidateParentIfNeeded(); + } } } @@ -8649,6 +8671,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal if (mDisplayList != null) { mDisplayList.setRotationY(rotationY); } + if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) { + // View was rejected last time it was drawn by its parent; this may have changed + invalidateParentIfNeeded(); + } } } @@ -8696,6 +8722,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal if (mDisplayList != null) { mDisplayList.setRotationX(rotationX); } + if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) { + // View was rejected last time it was drawn by its parent; this may have changed + invalidateParentIfNeeded(); + } } } @@ -8735,6 +8765,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal if (mDisplayList != null) { mDisplayList.setScaleX(scaleX); } + if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) { + // View was rejected last time it was drawn by its parent; this may have changed + invalidateParentIfNeeded(); + } } } @@ -8774,6 +8808,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal if (mDisplayList != null) { mDisplayList.setScaleY(scaleY); } + if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) { + // View was rejected last time it was drawn by its parent; this may have changed + invalidateParentIfNeeded(); + } } } @@ -8821,6 +8859,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal if (mDisplayList != null) { mDisplayList.setPivotX(pivotX); } + if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) { + // View was rejected last time it was drawn by its parent; this may have changed + invalidateParentIfNeeded(); + } } } @@ -8867,6 +8909,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal if (mDisplayList != null) { mDisplayList.setPivotY(pivotY); } + if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) { + // View was rejected last time it was drawn by its parent; this may have changed + invalidateParentIfNeeded(); + } } } @@ -9025,6 +9071,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } mBackgroundSizeChanged = true; invalidateParentIfNeeded(); + if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) { + // View was rejected last time it was drawn by its parent; this may have changed + invalidateParentIfNeeded(); + } } } @@ -9094,6 +9144,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } mBackgroundSizeChanged = true; invalidateParentIfNeeded(); + if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) { + // View was rejected last time it was drawn by its parent; this may have changed + invalidateParentIfNeeded(); + } } } @@ -9157,6 +9211,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } mBackgroundSizeChanged = true; invalidateParentIfNeeded(); + if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) { + // View was rejected last time it was drawn by its parent; this may have changed + invalidateParentIfNeeded(); + } } } @@ -9217,6 +9275,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal } mBackgroundSizeChanged = true; invalidateParentIfNeeded(); + if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) { + // View was rejected last time it was drawn by its parent; this may have changed + invalidateParentIfNeeded(); + } } } @@ -9301,6 +9363,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal if (mDisplayList != null) { mDisplayList.setTranslationX(translationX); } + if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) { + // View was rejected last time it was drawn by its parent; this may have changed + invalidateParentIfNeeded(); + } } } @@ -9338,6 +9404,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal if (mDisplayList != null) { mDisplayList.setTranslationY(translationY); } + if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) { + // View was rejected last time it was drawn by its parent; this may have changed + invalidateParentIfNeeded(); + } } } @@ -12777,16 +12847,27 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal if (a != null) { more = drawAnimation(parent, drawingTime, a, scalingRequired); concatMatrix = a.willChangeTransformationMatrix(); + if (concatMatrix) { + mPrivateFlags2 |= VIEW_IS_ANIMATING_TRANSFORM; + } transformToApply = parent.mChildTransformation; - } else if (!useDisplayListProperties && - (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { - final boolean hasTransform = - parent.getChildStaticTransformation(this, parent.mChildTransformation); - if (hasTransform) { - final int transformType = parent.mChildTransformation.getTransformationType(); - transformToApply = transformType != Transformation.TYPE_IDENTITY ? - parent.mChildTransformation : null; - concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0; + } else { + if ((mPrivateFlags2 & VIEW_IS_ANIMATING_TRANSFORM) == VIEW_IS_ANIMATING_TRANSFORM && + mDisplayList != null) { + // No longer animating: clear out old animation matrix + mDisplayList.setAnimationMatrix(null); + mPrivateFlags2 &= ~VIEW_IS_ANIMATING_TRANSFORM; + } + if (!useDisplayListProperties && + (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { + final boolean hasTransform = + parent.getChildStaticTransformation(this, parent.mChildTransformation); + if (hasTransform) { + final int transformType = parent.mChildTransformation.getTransformationType(); + transformToApply = transformType != Transformation.TYPE_IDENTITY ? + parent.mChildTransformation : null; + concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0; + } } } @@ -12798,8 +12879,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal if (!concatMatrix && canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) && (mPrivateFlags & DRAW_ANIMATION) == 0) { + mPrivateFlags2 |= VIEW_QUICK_REJECTED; return more; } + mPrivateFlags2 &= ~VIEW_QUICK_REJECTED; if (hardwareAccelerated) { // Clear INVALIDATED flag to allow invalidation to occur during rendering, but diff --git a/core/java/android/webkit/HTML5VideoFullScreen.java b/core/java/android/webkit/HTML5VideoFullScreen.java index 730ad08..62bc502 100644 --- a/core/java/android/webkit/HTML5VideoFullScreen.java +++ b/core/java/android/webkit/HTML5VideoFullScreen.java @@ -104,7 +104,9 @@ public class HTML5VideoFullScreen extends HTML5VideoView // After we return from this we can't use the surface any more. // The current Video View will be destroy when we play a new video. pauseAndDispatch(mProxy); + // TODO: handle full screen->inline mode transition without a reload. mPlayer.release(); + mPlayer = null; mSurfaceHolder = null; if (mMediaController != null) { mMediaController.hide(); @@ -128,12 +130,12 @@ public class HTML5VideoFullScreen extends HTML5VideoView return mVideoSurfaceView; } - HTML5VideoFullScreen(Context context, int videoLayerId, int position) { + HTML5VideoFullScreen(Context context, int videoLayerId, int position, boolean skipPrepare) { mVideoSurfaceView = new VideoSurfaceView(context); mFullScreenMode = FULLSCREEN_OFF; mVideoWidth = 0; mVideoHeight = 0; - init(videoLayerId, position); + init(videoLayerId, position, skipPrepare); } private void setMediaController(MediaController m) { @@ -156,8 +158,6 @@ public class HTML5VideoFullScreen extends HTML5VideoView } private void prepareForFullScreen() { - // So in full screen, we reset the MediaPlayer - mPlayer.reset(); MediaController mc = new FullScreenMediaController(mProxy.getContext(), mLayout); mc.setSystemUiVisibility(mLayout.getSystemUiVisibility()); setMediaController(mc); @@ -198,6 +198,7 @@ public class HTML5VideoFullScreen extends HTML5VideoView // after reading the MetaData if (mMediaController != null) { mMediaController.setEnabled(true); + mMediaController.show(); } if (mProgressView != null) { @@ -243,7 +244,7 @@ public class HTML5VideoFullScreen extends HTML5VideoView // Don't show the controller after exiting the full screen. mMediaController = null; - mCurrentState = STATE_RELEASED; + mCurrentState = STATE_RESETTED; } }; @@ -320,6 +321,13 @@ public class HTML5VideoFullScreen extends HTML5VideoView return 0; } + @Override + public void showControllerInFullScreen() { + if (mMediaController != null) { + mMediaController.show(0); + } + } + // Other listeners functions: private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener = new MediaPlayer.OnBufferingUpdateListener() { diff --git a/core/java/android/webkit/HTML5VideoInline.java b/core/java/android/webkit/HTML5VideoInline.java index 62e812e..2c7ea5d 100644 --- a/core/java/android/webkit/HTML5VideoInline.java +++ b/core/java/android/webkit/HTML5VideoInline.java @@ -21,7 +21,7 @@ public class HTML5VideoInline extends HTML5VideoView{ // associated with the surface texture can be used for showing the screen // shot when paused, so they are not singleton. private static SurfaceTexture mSurfaceTexture = null; - private int[] mTextureNames; + private static int[] mTextureNames = null; // Every time when the VideoLayer Id change, we need to recreate the // SurfaceTexture in order to delete the old video's decoder memory. private static int mVideoLayerUsingSurfaceTexture = -1; @@ -35,8 +35,7 @@ public class HTML5VideoInline extends HTML5VideoView{ } HTML5VideoInline(int videoLayerId, int position) { - init(videoLayerId, position); - mTextureNames = null; + init(videoLayerId, position, false); } @Override @@ -69,15 +68,14 @@ public class HTML5VideoInline extends HTML5VideoView{ // Inline Video specific FUNCTIONS: - @Override - public SurfaceTexture getSurfaceTexture(int videoLayerId) { + public static SurfaceTexture getSurfaceTexture(int videoLayerId) { // Create the surface texture. if (videoLayerId != mVideoLayerUsingSurfaceTexture || mSurfaceTexture == null || mTextureNames == null) { - if (mTextureNames != null) { - GLES20.glDeleteTextures(1, mTextureNames, 0); - } + // The GL texture will store in the VideoLayerManager at native side. + // They will be clean up when requested. + // The reason we recreated GL texture name is for screen shot support. mTextureNames = new int[1]; GLES20.glGenTextures(1, mTextureNames, 0); mSurfaceTexture = new SurfaceTexture(mTextureNames[0]); diff --git a/core/java/android/webkit/HTML5VideoView.java b/core/java/android/webkit/HTML5VideoView.java index 0d3b755..371feea 100644 --- a/core/java/android/webkit/HTML5VideoView.java +++ b/core/java/android/webkit/HTML5VideoView.java @@ -31,11 +31,10 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener { // NOTE: these values are in sync with VideoLayerAndroid.h in webkit side. // Please keep them in sync when changed. static final int STATE_INITIALIZED = 0; - static final int STATE_NOTPREPARED = 1; + static final int STATE_PREPARING = 1; static final int STATE_PREPARED = 2; static final int STATE_PLAYING = 3; - static final int STATE_RELEASED = 4; - protected int mCurrentState; + static final int STATE_RESETTED = 4; protected HTML5VideoViewProxy mProxy; @@ -46,11 +45,11 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener { // This is used to find the VideoLayer on the native side. protected int mVideoLayerId; - // Every video will have one MediaPlayer. Given the fact we only have one - // SurfaceTexture, there is only one MediaPlayer in action. Every time we - // switch videos, a new instance of MediaPlayer will be created in reset(). - // Switching between inline and full screen will also create a new instance. - protected MediaPlayer mPlayer; + // Given the fact we only have one SurfaceTexture, we cannot support multiple + // player at the same time. We may recreate a new one and abandon the old + // one at transition time. + protected static MediaPlayer mPlayer = null; + protected static int mCurrentState = -1; // We need to save such info. protected Uri mUri; @@ -60,10 +59,12 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener { // See http://www.whatwg.org/specs/web-apps/current-work/#event-media-timeupdate protected static Timer mTimer; + protected boolean mPauseDuringPreparing; + // The spec says the timer should fire every 250 ms or less. private static final int TIMEUPDATE_PERIOD = 250; // ms + private boolean mSkipPrepare = false; - protected boolean mPauseDuringPreparing; // common Video control FUNCTIONS: public void start() { if (mCurrentState == STATE_PREPARED) { @@ -83,7 +84,7 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener { public void pause() { if (isPlaying()) { mPlayer.pause(); - } else if (mCurrentState == STATE_NOTPREPARED) { + } else if (mCurrentState == STATE_PREPARING) { mPauseDuringPreparing = true; } // Delete the Timer to stop it since there is no stop call. @@ -124,11 +125,11 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener { } } - public void release() { - if (mCurrentState != STATE_RELEASED) { - mPlayer.release(); + public void reset() { + if (mCurrentState != STATE_RESETTED) { + mPlayer.reset(); } - mCurrentState = STATE_RELEASED; + mCurrentState = STATE_RESETTED; } public void stopPlayback() { @@ -142,9 +143,16 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener { } // Every time we start a new Video, we create a VideoView and a MediaPlayer - public void init(int videoLayerId, int position) { - mPlayer = new MediaPlayer(); - mCurrentState = STATE_INITIALIZED; + public void init(int videoLayerId, int position, boolean skipPrepare) { + if (mPlayer == null) { + mPlayer = new MediaPlayer(); + mCurrentState = STATE_INITIALIZED; + } + mSkipPrepare = skipPrepare; + // If we want to skip the prepare, then we keep the state. + if (!mSkipPrepare) { + mCurrentState = STATE_INITIALIZED; + } mProxy = null; mVideoLayerId = videoLayerId; mSaveSeekTime = position; @@ -195,17 +203,28 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener { } public void prepareDataCommon(HTML5VideoViewProxy proxy) { - try { - mPlayer.setDataSource(proxy.getContext(), mUri, mHeaders); - mPlayer.prepareAsync(); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } catch (IllegalStateException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); + if (!mSkipPrepare) { + try { + mPlayer.reset(); + mPlayer.setDataSource(proxy.getContext(), mUri, mHeaders); + mPlayer.prepareAsync(); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalStateException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + mCurrentState = STATE_PREPARING; + } else { + // If we skip prepare and the onPrepared happened in inline mode, we + // don't need to call prepare again, we just need to call onPrepared + // to refresh the state here. + if (mCurrentState >= STATE_PREPARED) { + onPrepared(mPlayer); + } + mSkipPrepare = false; } - mCurrentState = STATE_NOTPREPARED; } public void reprepareData(HTML5VideoViewProxy proxy) { @@ -294,10 +313,6 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener { return false; } - public SurfaceTexture getSurfaceTexture(int videoLayerId) { - return null; - } - public void deleteSurfaceTexture() { } @@ -332,14 +347,17 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener { return false; } - private boolean m_startWhenPrepared = false; + private boolean mStartWhenPrepared = false; public void setStartWhenPrepared(boolean willPlay) { - m_startWhenPrepared = willPlay; + mStartWhenPrepared = willPlay; } public boolean getStartWhenPrepared() { - return m_startWhenPrepared; + return mStartWhenPrepared; + } + + public void showControllerInFullScreen() { } } diff --git a/core/java/android/webkit/HTML5VideoViewProxy.java b/core/java/android/webkit/HTML5VideoViewProxy.java index 5fa4bad..90db308 100644 --- a/core/java/android/webkit/HTML5VideoViewProxy.java +++ b/core/java/android/webkit/HTML5VideoViewProxy.java @@ -112,13 +112,14 @@ class HTML5VideoViewProxy extends Handler mBaseLayer = layer; int currentVideoLayerId = mHTML5VideoView.getVideoLayerId(); - SurfaceTexture surfTexture = mHTML5VideoView.getSurfaceTexture(currentVideoLayerId); + SurfaceTexture surfTexture = + HTML5VideoInline.getSurfaceTexture(currentVideoLayerId); int textureName = mHTML5VideoView.getTextureName(); if (layer != 0 && surfTexture != null && currentVideoLayerId != -1) { int playerState = mHTML5VideoView.getCurrentState(); if (mHTML5VideoView.getPlayerBuffering()) - playerState = HTML5VideoView.STATE_NOTPREPARED; + playerState = HTML5VideoView.STATE_PREPARING; boolean foundInTree = nativeSendSurfaceTexture(surfTexture, layer, currentVideoLayerId, textureName, playerState); @@ -145,6 +146,7 @@ class HTML5VideoViewProxy extends Handler HTML5VideoViewProxy proxy, WebViewClassic webView) { // Save the inline video info and inherit it in the full screen int savePosition = 0; + boolean canSkipPrepare = false; if (mHTML5VideoView != null) { // We don't allow enter full screen mode while the previous // full screen video hasn't finished yet. @@ -156,15 +158,20 @@ class HTML5VideoViewProxy extends Handler // save the current position. if (layerId == mHTML5VideoView.getVideoLayerId()) { savePosition = mHTML5VideoView.getCurrentPosition(); + int playerState = mHTML5VideoView.getCurrentState(); + canSkipPrepare = (playerState == HTML5VideoView.STATE_PREPARING + || playerState == HTML5VideoView.STATE_PREPARED + || playerState == HTML5VideoView.STATE_PLAYING) + && !mHTML5VideoView.isFullScreenMode(); + } + if (!canSkipPrepare) { + mHTML5VideoView.reset(); } - mHTML5VideoView.release(); } mHTML5VideoView = new HTML5VideoFullScreen(proxy.getContext(), - layerId, savePosition); + layerId, savePosition, canSkipPrepare); mCurrentProxy = proxy; - mHTML5VideoView.setVideoURI(url, mCurrentProxy); - mHTML5VideoView.enterFullScreenVideoState(layerId, proxy, webView); } @@ -217,8 +224,7 @@ class HTML5VideoViewProxy extends Handler if (!backFromFullScreenMode) { mHTML5VideoView.pauseAndDispatch(mCurrentProxy); } - // release the media player to avoid finalize error - mHTML5VideoView.release(); + mHTML5VideoView.reset(); } mCurrentProxy = proxy; mHTML5VideoView = new HTML5VideoInline(videoLayerId, time); @@ -273,6 +279,7 @@ class HTML5VideoViewProxy extends Handler } public static void end() { + mHTML5VideoView.showControllerInFullScreen(); if (mCurrentProxy != null) { if (isVideoSelfEnded) mCurrentProxy.dispatchOnEnded(); diff --git a/core/java/android/webkit/WebViewInputDispatcher.java b/core/java/android/webkit/WebViewInputDispatcher.java index 9541435..9328d8c 100644 --- a/core/java/android/webkit/WebViewInputDispatcher.java +++ b/core/java/android/webkit/WebViewInputDispatcher.java @@ -334,6 +334,7 @@ final class WebViewInputDispatcher { DispatchEvent d = obtainDispatchEventLocked(eventToEnqueue, eventType, 0, webKitXOffset, webKitYOffset, webKitScale); + updateStateTrackersLocked(d, event); enqueueEventLocked(d); } return true; @@ -787,7 +788,6 @@ final class WebViewInputDispatcher { flags = d.mFlags; - updateStateTrackersLocked(d, event); if (event == d.mEvent) { d.mEvent = null; // retain ownership of event, don't recycle it yet } diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java index ebf8a4a..7ca02e1 100644 --- a/core/java/android/widget/SpellChecker.java +++ b/core/java/android/widget/SpellChecker.java @@ -343,6 +343,36 @@ public class SpellChecker implements SpellCheckerSessionListener { if (!isInDictionary && looksLikeTypo) { createMisspelledSuggestionSpan( editable, suggestionsInfo, spellCheckSpan, offset, length); + } else { + // Valid word -- isInDictionary || !looksLikeTypo + if (mIsSentenceSpellCheckSupported) { + // Allow the spell checker to remove existing misspelled span by + // overwriting the span over the same place + final int spellCheckSpanStart = editable.getSpanStart(spellCheckSpan); + final int spellCheckSpanEnd = editable.getSpanEnd(spellCheckSpan); + final int start; + final int end; + if (offset != USE_SPAN_RANGE && length != USE_SPAN_RANGE) { + start = spellCheckSpanStart + offset; + end = start + length; + } else { + start = spellCheckSpanStart; + end = spellCheckSpanEnd; + } + if (spellCheckSpanStart >= 0 && spellCheckSpanEnd > spellCheckSpanStart + && end > start) { + final Long key = Long.valueOf(TextUtils.packRangeInLong(start, end)); + final SuggestionSpan tempSuggestionSpan = mSuggestionSpanCache.get(key); + if (tempSuggestionSpan != null) { + if (DBG) { + Log.i(TAG, "Remove existing misspelled span. " + + editable.subSequence(start, end)); + } + editable.removeSpan(tempSuggestionSpan); + mSuggestionSpanCache.remove(key); + } + } + } } return spellCheckSpan; } @@ -473,8 +503,16 @@ public class SpellChecker implements SpellCheckerSessionListener { private Object mRange = new Object(); public void parse(int start, int end) { - if (end > start) { - setRangeSpan((Editable) mTextView.getText(), start, end); + final int max = mTextView.length(); + final int parseEnd; + if (end > max) { + Log.w(TAG, "Parse invalid region, from " + start + " to " + end); + parseEnd = max; + } else { + parseEnd = end; + } + if (parseEnd > start) { + setRangeSpan((Editable) mTextView.getText(), start, parseEnd); parse(); } } @@ -612,6 +650,8 @@ public class SpellChecker implements SpellCheckerSessionListener { break; } if (spellCheckEnd <= spellCheckStart) { + Log.w(TAG, "Trying to spellcheck invalid region, from " + + start + " to " + end); break; } if (createSpellCheckSpan) { diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 555c974..098a034 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -154,6 +154,7 @@ import java.util.Locale; * @attr ref android.R.styleable#TextView_textColorLink * @attr ref android.R.styleable#TextView_textSize * @attr ref android.R.styleable#TextView_textScaleX + * @attr ref android.R.styleable#TextView_fontFamily * @attr ref android.R.styleable#TextView_typeface * @attr ref android.R.styleable#TextView_textStyle * @attr ref android.R.styleable#TextView_cursorVisible @@ -464,6 +465,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener ColorStateList textColorHint = null; ColorStateList textColorLink = null; int textSize = 15; + String fontFamily = null; int typefaceIndex = -1; int styleIndex = -1; boolean allCaps = false; @@ -516,6 +518,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener typefaceIndex = appearance.getInt(attr, -1); break; + case com.android.internal.R.styleable.TextAppearance_fontFamily: + fontFamily = appearance.getString(attr); + break; + case com.android.internal.R.styleable.TextAppearance_textStyle: styleIndex = appearance.getInt(attr, -1); break; @@ -781,6 +787,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener styleIndex = a.getInt(attr, styleIndex); break; + case com.android.internal.R.styleable.TextView_fontFamily: + fontFamily = a.getString(attr); + break; + case com.android.internal.R.styleable.TextView_password: password = a.getBoolean(attr, password); break; @@ -1051,7 +1061,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener typefaceIndex = MONOSPACE; } - setTypefaceByIndex(typefaceIndex, styleIndex); + setTypefaceFromAttrs(fontFamily, typefaceIndex, styleIndex); if (shadowcolor != 0) { setShadowLayer(r, dx, dy, shadowcolor); @@ -1111,8 +1121,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } - private void setTypefaceByIndex(int typefaceIndex, int styleIndex) { + private void setTypefaceFromAttrs(String familyName, int typefaceIndex, int styleIndex) { Typeface tf = null; + if (familyName != null) { + tf = Typeface.create(familyName, styleIndex); + if (tf != null) { + setTypeface(tf); + return; + } + } switch (typefaceIndex) { case SANS: tf = Typeface.SANS_SERIF; @@ -2160,14 +2177,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener setLinkTextColor(colors); } + String familyName; int typefaceIndex, styleIndex; + familyName = appearance.getString(com.android.internal.R.styleable. + TextAppearance_fontFamily); typefaceIndex = appearance.getInt(com.android.internal.R.styleable. TextAppearance_typeface, -1); styleIndex = appearance.getInt(com.android.internal.R.styleable. TextAppearance_textStyle, -1); - setTypefaceByIndex(typefaceIndex, styleIndex); + setTypefaceFromAttrs(familyName, typefaceIndex, styleIndex); if (appearance.getBoolean(com.android.internal.R.styleable.TextAppearance_textAllCaps, false)) { @@ -2269,6 +2289,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @see #getTypeface() * + * @attr ref android.R.styleable#TextView_fontFamily * @attr ref android.R.styleable#TextView_typeface * @attr ref android.R.styleable#TextView_textStyle */ @@ -2290,6 +2311,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @see #setTypeface(Typeface) * + * @attr ref android.R.styleable#TextView_fontFamily * @attr ref android.R.styleable#TextView_typeface * @attr ref android.R.styleable#TextView_textStyle */ @@ -3690,15 +3712,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener boolean forceUpdate = false; if (isPassword) { setTransformationMethod(PasswordTransformationMethod.getInstance()); - setTypefaceByIndex(MONOSPACE, 0); + setTypefaceFromAttrs(null /* fontFamily */, MONOSPACE, 0); } else if (isVisiblePassword) { if (mTransformation == PasswordTransformationMethod.getInstance()) { forceUpdate = true; } - setTypefaceByIndex(MONOSPACE, 0); + setTypefaceFromAttrs(null /* fontFamily */, MONOSPACE, 0); } else if (wasPassword || wasVisiblePassword) { // not in password mode, clean up typeface and transformation - setTypefaceByIndex(-1, -1); + setTypefaceFromAttrs(null /* fontFamily */, -1, -1); if (mTransformation == PasswordTransformationMethod.getInstance()) { forceUpdate = true; } |
