diff options
Diffstat (limited to 'core/java')
18 files changed, 230 insertions, 257 deletions
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 5f5ba50..e420bfd 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -399,6 +399,25 @@ public final class BluetoothAdapter { } /** + * Get a {@link BluetoothDevice} object for the given Bluetooth hardware + * address. + * <p>Valid Bluetooth hardware addresses must be 6 bytes. This method + * expects the address in network byte order (MSB first). + * <p>A {@link BluetoothDevice} will always be returned for a valid + * hardware address, even if this adapter has never seen that device. + * + * @param address Bluetooth MAC address (6 bytes) + * @throws IllegalArgumentException if address is invalid + */ + public BluetoothDevice getRemoteDevice(byte[] address) { + if (address == null || address.length != 6) { + throw new IllegalArgumentException("Bluetooth address must have 6 bytes"); + } + return new BluetoothDevice(String.format("%02X:%02X:%02X:%02X:%02X:%02X", + address[0], address[1], address[2], address[3], address[4], address[5])); + } + + /** * Return true if Bluetooth is currently enabled and ready for use. * <p>Equivalent to: * <code>getBluetoothState() == STATE_ON</code> @@ -1281,7 +1300,7 @@ public final class BluetoothAdapter { } /** - * Validate a Bluetooth address, such as "00:43:A8:23:10:F0" + * Validate a String Bluetooth address, such as "00:43:A8:23:10:F0" * <p>Alphabetic characters must be uppercase to be valid. * * @param address Bluetooth address as string diff --git a/core/java/android/inputmethodservice/ExtractEditText.java b/core/java/android/inputmethodservice/ExtractEditText.java index 72431f3..10c1195 100644 --- a/core/java/android/inputmethodservice/ExtractEditText.java +++ b/core/java/android/inputmethodservice/ExtractEditText.java @@ -158,25 +158,46 @@ public class ExtractEditText extends EditText { } /** - * Delete the range of text, supposedly valid + * {@inheritDoc} * @hide */ @Override protected void deleteText_internal(int start, int end) { - // Do not call the super method. This will change the source TextView instead, which - // will update the ExtractTextView. + // Do not call the super method. + // This will change the source TextView instead, which will update the ExtractTextView. mIME.onExtractedDeleteText(start, end); } /** - * Replaces the range of text [start, end[ by replacement text + * {@inheritDoc} * @hide */ @Override protected void replaceText_internal(int start, int end, CharSequence text) { - // Do not call the super method. This will change the source TextView instead, which - // will update the ExtractTextView. + // Do not call the super method. + // This will change the source TextView instead, which will update the ExtractTextView. mIME.onExtractedReplaceText(start, end, text); } + /** + * {@inheritDoc} + * @hide + */ + @Override + protected void setSpan_internal(Object span, int start, int end, int flags) { + // Do not call the super method. + // This will change the source TextView instead, which will update the ExtractTextView. + mIME.onExtractedSetSpan(span, start, end, flags); + } + + /** + * {@inheritDoc} + * @hide + */ + @Override + protected void setCursorPosition_internal(int start, int end) { + // Do not call the super method. + // This will change the source TextView instead, which will update the ExtractTextView. + mIME.onExtractedSelectionChanged(start, end); + } } diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 02839db..53cdf21 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -2006,6 +2006,22 @@ public class InputMethodService extends AbstractInputMethodService { } /** + * @hide + */ + public void onExtractedSetSpan(Object span, int start, int end, int flags) { + InputConnection conn = getCurrentInputConnection(); + if (conn != null) { + if (!conn.setSelection(start, end)) return; + CharSequence text = conn.getSelectedText(InputConnection.GET_TEXT_WITH_STYLES); + if (text instanceof Spannable) { + ((Spannable) text).setSpan(span, 0, text.length(), flags); + conn.setComposingRegion(start, end); + conn.commitText(text, 1); + } + } + } + + /** * This is called when the user has clicked on the extracted text view, * when running in fullscreen mode. The default implementation hides * the candidates view when this happens, but only if the extracted text diff --git a/core/java/android/speech/tts/AudioPlaybackQueueItem.java b/core/java/android/speech/tts/AudioPlaybackQueueItem.java index 668b459..1a1fda8 100644 --- a/core/java/android/speech/tts/AudioPlaybackQueueItem.java +++ b/core/java/android/speech/tts/AudioPlaybackQueueItem.java @@ -15,27 +15,91 @@ */ package android.speech.tts; +import android.content.Context; +import android.media.MediaPlayer; +import android.net.Uri; +import android.os.ConditionVariable; import android.speech.tts.TextToSpeechService.UtteranceProgressDispatcher; import android.util.Log; class AudioPlaybackQueueItem extends PlaybackQueueItem { - private final BlockingMediaPlayer mPlayer; + private static final String TAG = "TTS.AudioQueueItem"; + + private final Context mContext; + private final Uri mUri; + private final int mStreamType; + + private final ConditionVariable mDone; + private MediaPlayer mPlayer; + private volatile boolean mFinished; AudioPlaybackQueueItem(UtteranceProgressDispatcher dispatcher, - Object callerIdentity, BlockingMediaPlayer player) { + Object callerIdentity, + Context context, Uri uri, int streamType) { super(dispatcher, callerIdentity); - mPlayer = player; + + mContext = context; + mUri = uri; + mStreamType = streamType; + + mDone = new ConditionVariable(); + mPlayer = null; + mFinished = false; } @Override public void run() { - getDispatcher().dispatchOnStart(); - // TODO: This can be avoided. Will be fixed later in this CL. - mPlayer.startAndWait(); - getDispatcher().dispatchOnDone(); + final UtteranceProgressDispatcher dispatcher = getDispatcher(); + + dispatcher.dispatchOnStart(); + mPlayer = MediaPlayer.create(mContext, mUri); + if (mPlayer == null) { + dispatcher.dispatchOnError(); + return; + } + + try { + mPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { + @Override + public boolean onError(MediaPlayer mp, int what, int extra) { + Log.w(TAG, "Audio playback error: " + what + ", " + extra); + mDone.open(); + return true; + } + }); + mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + @Override + public void onCompletion(MediaPlayer mp) { + mFinished = true; + mDone.open(); + } + }); + mPlayer.setAudioStreamType(mStreamType); + mPlayer.start(); + mDone.block(); + finish(); + } catch (IllegalArgumentException ex) { + Log.w(TAG, "MediaPlayer failed", ex); + mDone.open(); + } + + if (mFinished) { + dispatcher.dispatchOnDone(); + } else { + dispatcher.dispatchOnError(); + } + } + + private void finish() { + try { + mPlayer.stop(); + } catch (IllegalStateException ex) { + // Do nothing, the player is already stopped + } + mPlayer.release(); } @Override void stop(boolean isError) { - mPlayer.stop(); + mDone.open(); } } diff --git a/core/java/android/speech/tts/BlockingMediaPlayer.java b/core/java/android/speech/tts/BlockingMediaPlayer.java deleted file mode 100644 index 1ccc6e4..0000000 --- a/core/java/android/speech/tts/BlockingMediaPlayer.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package android.speech.tts; - -import android.content.Context; -import android.media.MediaPlayer; -import android.net.Uri; -import android.os.ConditionVariable; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.util.Log; - -/** - * A media player that allows blocking to wait for it to finish. - */ -class BlockingMediaPlayer { - - private static final String TAG = "BlockMediaPlayer"; - - private static final String MEDIA_PLAYER_THREAD_NAME = "TTS-MediaPlayer"; - - private final Context mContext; - private final Uri mUri; - private final int mStreamType; - private final ConditionVariable mDone; - // Only accessed on the Handler thread - private MediaPlayer mPlayer; - private volatile boolean mFinished; - - /** - * Creates a new blocking media player. - * Creating a blocking media player is a cheap operation. - * - * @param context - * @param uri - * @param streamType - */ - public BlockingMediaPlayer(Context context, Uri uri, int streamType) { - mContext = context; - mUri = uri; - mStreamType = streamType; - mDone = new ConditionVariable(); - } - - /** - * Starts playback and waits for it to finish. - * Can be called from any thread. - * - * @return {@code true} if the playback finished normally, {@code false} if the playback - * failed or {@link #stop} was called before the playback finished. - */ - public boolean startAndWait() { - HandlerThread thread = new HandlerThread(MEDIA_PLAYER_THREAD_NAME); - thread.start(); - Handler handler = new Handler(thread.getLooper()); - mFinished = false; - handler.post(new Runnable() { - @Override - public void run() { - startPlaying(); - } - }); - mDone.block(); - handler.post(new Runnable() { - @Override - public void run() { - finish(); - // No new messages should get posted to the handler thread after this - Looper.myLooper().quit(); - } - }); - return mFinished; - } - - /** - * Stops playback. Can be called multiple times. - * Can be called from any thread. - */ - public void stop() { - mDone.open(); - } - - /** - * Starts playback. - * Called on the handler thread. - */ - private void startPlaying() { - mPlayer = MediaPlayer.create(mContext, mUri); - if (mPlayer == null) { - Log.w(TAG, "Failed to play " + mUri); - mDone.open(); - return; - } - try { - mPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { - @Override - public boolean onError(MediaPlayer mp, int what, int extra) { - Log.w(TAG, "Audio playback error: " + what + ", " + extra); - mDone.open(); - return true; - } - }); - mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { - @Override - public void onCompletion(MediaPlayer mp) { - mFinished = true; - mDone.open(); - } - }); - mPlayer.setAudioStreamType(mStreamType); - mPlayer.start(); - } catch (IllegalArgumentException ex) { - Log.w(TAG, "MediaPlayer failed", ex); - mDone.open(); - } - } - - /** - * Stops playback and release the media player. - * Called on the handler thread. - */ - private void finish() { - try { - mPlayer.stop(); - } catch (IllegalStateException ex) { - // Do nothing, the player is already stopped - } - mPlayer.release(); - } - -}
\ No newline at end of file diff --git a/core/java/android/speech/tts/MessageParams.java b/core/java/android/speech/tts/MessageParams.java deleted file mode 100644 index f83b793..0000000 --- a/core/java/android/speech/tts/MessageParams.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package android.speech.tts; - -import android.speech.tts.TextToSpeechService.UtteranceProgressDispatcher; - -abstract class MessageParams { - static final int TYPE_SYNTHESIS = 1; - static final int TYPE_AUDIO = 2; - static final int TYPE_SILENCE = 3; - - private final UtteranceProgressDispatcher mDispatcher; - private final Object mCallerIdentity; - - MessageParams(UtteranceProgressDispatcher dispatcher, Object callerIdentity) { - mDispatcher = dispatcher; - mCallerIdentity = callerIdentity; - } - - UtteranceProgressDispatcher getDispatcher() { - return mDispatcher; - } - - Object getCallerIdentity() { - return mCallerIdentity; - } - - @Override - public String toString() { - return "MessageParams[" + hashCode() + "]"; - } - - abstract int getType(); -} diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java index ba8485a..4c1a0af 100644 --- a/core/java/android/speech/tts/TextToSpeechService.java +++ b/core/java/android/speech/tts/TextToSpeechService.java @@ -694,12 +694,12 @@ public abstract class TextToSpeechService extends Service { } private class AudioSpeechItem extends SpeechItem { - private final BlockingMediaPlayer mPlayer; - + private final AudioPlaybackQueueItem mItem; public AudioSpeechItem(Object callerIdentity, int callerUid, int callerPid, Bundle params, Uri uri) { super(callerIdentity, callerUid, callerPid, params); - mPlayer = new BlockingMediaPlayer(TextToSpeechService.this, uri, getStreamType()); + mItem = new AudioPlaybackQueueItem(this, getCallerIdentity(), + TextToSpeechService.this, uri, getStreamType()); } @Override @@ -709,8 +709,7 @@ public abstract class TextToSpeechService extends Service { @Override protected int playImpl() { - mAudioPlaybackHandler.enqueue(new AudioPlaybackQueueItem( - this, getCallerIdentity(), mPlayer)); + mAudioPlaybackHandler.enqueue(mItem); return TextToSpeech.SUCCESS; } diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java index 231f913..b708750 100644 --- a/core/java/android/text/SpannableStringBuilder.java +++ b/core/java/android/text/SpannableStringBuilder.java @@ -863,6 +863,17 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable return new String(buf); } + /** + * Return a String containing a copy of the chars in this buffer, limited to the + * [start, end[ range. + * @hide + */ + public String substring(int start, int end) { + char[] buf = new char[end - start]; + getChars(start, end, buf, 0); + return new String(buf); + } + private TextWatcher[] sendTextWillChange(int start, int before, int after) { TextWatcher[] recip = getSpans(start, start + before, TextWatcher.class); int n = recip.length; diff --git a/core/java/android/text/method/WordIterator.java b/core/java/android/text/method/WordIterator.java index 239d9e8..11226a9 100644 --- a/core/java/android/text/method/WordIterator.java +++ b/core/java/android/text/method/WordIterator.java @@ -18,6 +18,7 @@ package android.text.method; import android.text.Selection; +import android.text.SpannableStringBuilder; import java.text.BreakIterator; import java.util.Locale; @@ -58,7 +59,11 @@ public class WordIterator implements Selection.PositionIterator { mOffsetShift = Math.max(0, start - WINDOW_WIDTH); final int windowEnd = Math.min(charSequence.length(), end + WINDOW_WIDTH); - mString = charSequence.toString().substring(mOffsetShift, windowEnd); + if (charSequence instanceof SpannableStringBuilder) { + mString = ((SpannableStringBuilder) charSequence).substring(mOffsetShift, windowEnd); + } else { + mString = charSequence.subSequence(mOffsetShift, windowEnd).toString(); + } mIterator.setText(mString); } diff --git a/core/java/android/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java index ed2af10..0f26a34 100644 --- a/core/java/android/text/style/SuggestionSpan.java +++ b/core/java/android/text/style/SuggestionSpan.java @@ -92,11 +92,6 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan { private float mAutoCorrectionUnderlineThickness; private int mAutoCorrectionUnderlineColor; - /* - * TODO: If switching IME is required, needs to add parameters for ids of InputMethodInfo - * and InputMethodSubtype. - */ - /** * @param context Context for the application * @param suggestions Suggestions for the string under the span @@ -146,6 +141,16 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan { } private void initStyle(Context context) { + if (context == null) { + mMisspelledUnderlineThickness = 0; + mEasyCorrectUnderlineThickness = 0; + mAutoCorrectionUnderlineThickness = 0; + mMisspelledUnderlineColor = Color.BLACK; + mEasyCorrectUnderlineColor = Color.BLACK; + mAutoCorrectionUnderlineColor = Color.BLACK; + return; + } + int defStyle = com.android.internal.R.attr.textAppearanceMisspelledSuggestion; TypedArray typedArray = context.obtainStyledAttributes( null, com.android.internal.R.styleable.SuggestionSpan, defStyle, 0); @@ -169,7 +174,6 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan { com.android.internal.R.styleable.SuggestionSpan_textUnderlineThickness, 0); mAutoCorrectionUnderlineColor = typedArray.getColor( com.android.internal.R.styleable.SuggestionSpan_textUnderlineColor, Color.BLACK); - } public SuggestionSpan(Parcel src) { diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 443acf6..3f793bb 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -441,6 +441,8 @@ public abstract class HardwareRenderer { } boolean mDirtyRegionsEnabled; + boolean mUpdateDirtyRegions; + final boolean mVsyncDisabled; final int mGlVersion; @@ -675,6 +677,12 @@ public abstract class HardwareRenderer { initCaches(); + enableDirtyRegions(); + + return mEglContext.getGL(); + } + + private void enableDirtyRegions() { // If mDirtyRegions is set, this means we have an EGL configuration // with EGL_SWAP_BEHAVIOR_PRESERVED_BIT set if (sDirtyRegions) { @@ -690,8 +698,6 @@ public abstract class HardwareRenderer { // configuration (see RENDER_DIRTY_REGIONS) mDirtyRegionsEnabled = GLES20Canvas.isBackBufferPreserved(); } - - return mEglContext.getGL(); } abstract void initCaches(); @@ -745,6 +751,9 @@ public abstract class HardwareRenderer { if (!createSurface(holder)) { return; } + + mUpdateDirtyRegions = true; + if (mCanvas != null) { setEnabled(true); } @@ -943,6 +952,10 @@ public abstract class HardwareRenderer { fallback(true); return SURFACE_STATE_ERROR; } else { + if (mUpdateDirtyRegions) { + enableDirtyRegions(); + mUpdateDirtyRegions = false; + } return SURFACE_STATE_UPDATED; } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 7a9d82c..72966ef 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -3257,8 +3257,9 @@ public final class ViewRootImpl extends Handler implements ViewParent, } // If the Control modifier is held, try to interpret the key as a shortcut. - if (event.getAction() == KeyEvent.ACTION_UP + if (event.getAction() == KeyEvent.ACTION_DOWN && event.isCtrlPressed() + && event.getRepeatCount() == 0 && !KeyEvent.isModifierKey(event.getKeyCode())) { if (mView.dispatchKeyShortcutEvent(event)) { finishInputEvent(q, true); diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 40cb248..a284a17 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -2496,11 +2496,12 @@ public class WebView extends AbsoluteLayout } /** - * Return the reading level scale of the WebView + * Compute the reading level scale of the WebView + * @param scale The current scale. * @return The reading level scale. */ - /*package*/ float getReadingLevelScale() { - return mZoomManager.getReadingLevelScale(); + /*package*/ float computeReadingLevelScale(float scale) { + return mZoomManager.computeReadingLevelScale(scale); } /** diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index 0f749bc..14da23e 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -2514,7 +2514,7 @@ public final class WebViewCore { if (mSettings.isNarrowColumnLayout()) { // In case of automatic text reflow in fixed view port mode. mInitialViewState.mTextWrapScale = - mWebView.getReadingLevelScale(); + mWebView.computeReadingLevelScale(data.mScale); } } else { // Scale is given such as when page is restored, use it. diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java index 14bdc42..8ffba64 100644 --- a/core/java/android/webkit/ZoomManager.java +++ b/core/java/android/webkit/ZoomManager.java @@ -316,7 +316,12 @@ class ZoomManager { * Returns the zoom scale used for reading text on a double-tap. */ public final float getReadingLevelScale() { - return mDisplayDensity * mDoubleTapZoomFactor; + return computeScaleWithLimits(computeReadingLevelScale(getZoomOverviewScale())); + } + + /* package */ final float computeReadingLevelScale(float scale) { + return Math.max(mDisplayDensity * mDoubleTapZoomFactor, + scale + MIN_DOUBLE_TAP_SCALE_INCREMENT); } public final float getInvDefaultScale() { @@ -678,7 +683,7 @@ class ZoomManager { } zoomToOverview(); } else { - zoomToReadingLevelOrMore(); + zoomToReadingLevel(); } } @@ -709,9 +714,8 @@ class ZoomManager { !mWebView.getSettings().getUseFixedViewport()); } - private void zoomToReadingLevelOrMore() { - final float zoomScale = Math.max(getReadingLevelScale(), - mActualScale + MIN_DOUBLE_TAP_SCALE_INCREMENT); + private void zoomToReadingLevel() { + final float readingScale = getReadingLevelScale(); int left = mWebView.nativeGetBlockLeftEdge(mAnchorX, mAnchorY, mActualScale); if (left != WebView.NO_LEFTEDGE) { @@ -721,13 +725,13 @@ class ZoomManager { // Re-calculate the zoom center so that the new scroll x will be // on the left edge. if (viewLeft > 0) { - mZoomCenterX = viewLeft * zoomScale / (zoomScale - mActualScale); + mZoomCenterX = viewLeft * readingScale / (readingScale - mActualScale); } else { mWebView.scrollBy(viewLeft, 0); mZoomCenterX = 0; } } - startZoomAnimation(zoomScale, + startZoomAnimation(readingScale, !mWebView.getSettings().getUseFixedViewport()); } diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java index 9d541e0..7d0f98e 100644 --- a/core/java/android/widget/NumberPicker.java +++ b/core/java/android/widget/NumberPicker.java @@ -774,6 +774,7 @@ public class NumberPicker extends LinearLayout { mBeginEditOnUpEvent = false; mAdjustScrollerOnUpEvent = true; if (mSelectorWheelState == SELECTOR_WHEEL_STATE_LARGE) { + mSelectorWheelPaint.setAlpha(SELECTOR_WHEEL_BRIGHT_ALPHA); boolean scrollersFinished = mFlingScroller.isFinished() && mAdjustScroller.isFinished(); if (!scrollersFinished) { @@ -1608,23 +1609,11 @@ public class NumberPicker extends LinearLayout { */ private void fling(int velocityY) { mPreviousScrollerY = 0; - Scroller flingScroller = mFlingScroller; - if (mWrapSelectorWheel) { - if (velocityY > 0) { - flingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE); - } else { - flingScroller.fling(0, Integer.MAX_VALUE, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE); - } + if (velocityY > 0) { + mFlingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE); } else { - if (velocityY > 0) { - int maxY = mTextSize * (mValue - mMinValue); - flingScroller.fling(0, 0, 0, velocityY, 0, 0, 0, maxY); - } else { - int startY = mTextSize * (mMaxValue - mValue); - int maxY = startY; - flingScroller.fling(0, startY, 0, velocityY, 0, 0, 0, maxY); - } + mFlingScroller.fling(0, Integer.MAX_VALUE, 0, velocityY, 0, 0, 0, Integer.MAX_VALUE); } invalidate(); diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java index 4bd7165..31da5b5 100644 --- a/core/java/android/widget/SpellChecker.java +++ b/core/java/android/widget/SpellChecker.java @@ -19,6 +19,7 @@ package android.widget; import android.content.Context; import android.text.Editable; import android.text.Selection; +import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.method.WordIterator; import android.text.style.SpellCheckSpan; @@ -220,7 +221,6 @@ public class SpellChecker implements SpellCheckerSessionListener { TextInfo[] textInfos = new TextInfo[mLength]; int textInfosCount = 0; - final String text = editable.toString(); for (int i = 0; i < mLength; i++) { final SpellCheckSpan spellCheckSpan = mSpellCheckSpans[i]; if (spellCheckSpan.isSpellCheckInProgress()) continue; @@ -230,7 +230,9 @@ public class SpellChecker implements SpellCheckerSessionListener { // Do not check this word if the user is currently editing it if (start >= 0 && end > start && (selectionEnd < start || selectionStart > end)) { - final String word = text.substring(start, end); + final String word = (editable instanceof SpannableStringBuilder) ? + ((SpannableStringBuilder) editable).substring(start, end) : + editable.subSequence(start, end).toString(); spellCheckSpan.setSpellCheckInProgress(true); textInfos[textInfosCount++] = new TextInfo(word, mCookie, mIds[i]); } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index babd8e7..5b73a74 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -5517,7 +5517,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * call performClick(), but that won't do anything in * this case.) */ - if (hasOnClickListeners()) { + if (!hasOnClickListeners()) { if (mMovement != null && mText instanceof Editable && mLayout != null && onCheckIsTextEditor()) { InputMethodManager imm = InputMethodManager.peekInstance(); @@ -5554,7 +5554,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * call performClick(), but that won't do anything in * this case.) */ - if (hasOnClickListeners()) { + if (!hasOnClickListeners()) { View v = focusSearch(FOCUS_DOWN); if (v != null) { @@ -9835,7 +9835,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener highlightTextDifferences(mSuggestionInfos[i], spanUnionStart, spanUnionEnd); } - // Add to dictionary item is there a span with the misspelled flag + // Add to dictionary item if there is a span with the misspelled flag if (misspelledSpan != null) { final int misspelledStart = spannable.getSpanStart(misspelledSpan); final int misspelledEnd = spannable.getSpanEnd(misspelledSpan); @@ -9921,7 +9921,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final int spanStart = editable.getSpanStart(suggestionInfo.suggestionSpan); final int spanEnd = editable.getSpanEnd(suggestionInfo.suggestionSpan); - if (spanStart < 0 || spanEnd < 0) { + if (spanStart < 0 || spanEnd <= spanStart) { // Span has been removed hide(); return; @@ -9989,14 +9989,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // way to assign them a valid range after replacement if (suggestionSpansStarts[i] <= spanStart && suggestionSpansEnds[i] >= spanEnd) { - // TODO The ExtractEditText should restore these spans in the original text - editable.setSpan(suggestionSpans[i], suggestionSpansStarts[i], + setSpan_internal(suggestionSpans[i], suggestionSpansStarts[i], suggestionSpansEnds[i] + lengthDifference, suggestionSpansFlags[i]); } } // Move cursor at the end of the replaced word - Selection.setSelection(editable, spanEnd + lengthDifference); + final int newCursorPosition = spanEnd + lengthDifference; + setCursorPosition_internal(newCursorPosition, newCursorPosition); } hide(); @@ -11469,6 +11469,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener ((Editable) mText).replace(start, end, text); } + /** + * Sets a span on the specified range of text + * @hide + */ + protected void setSpan_internal(Object span, int start, int end, int flags) { + ((Editable) mText).setSpan(span, start, end, flags); + } + + /** + * Moves the cursor to the specified offset position in text + * @hide + */ + protected void setCursorPosition_internal(int start, int end) { + Selection.setSelection(((Editable) mText), start, end); + } + @ViewDebug.ExportedProperty(category = "text") private CharSequence mText; private CharSequence mTransformed; |