diff options
36 files changed, 1104 insertions, 382 deletions
diff --git a/api/current.txt b/api/current.txt index 24c7d76ef0df..d3333f025f34 100644 --- a/api/current.txt +++ b/api/current.txt @@ -377,9 +377,11 @@ package android { field public static final int drawSelectorOnTop = 16843004; // 0x10100fc field public static final int drawable = 16843161; // 0x1010199 field public static final int drawableBottom = 16843118; // 0x101016e + field public static final int drawableEnd = 16843687; // 0x10103a7 field public static final int drawableLeft = 16843119; // 0x101016f field public static final int drawablePadding = 16843121; // 0x1010171 field public static final int drawableRight = 16843120; // 0x1010170 + field public static final int drawableStart = 16843686; // 0x10103a6 field public static final int drawableTop = 16843117; // 0x101016d field public static final int drawingCacheQuality = 16842984; // 0x10100e8 field public static final int dropDownAnchor = 16843363; // 0x1010263 @@ -26421,7 +26423,9 @@ package android.widget { method protected void onTextChanged(java.lang.CharSequence, int, int, int); method public boolean onTextContextMenuItem(int); method public void removeTextChangedListener(android.text.TextWatcher); + method protected void resetResolvedDrawables(); method protected void resetResolvedLayoutDirection(); + method protected void resolveDrawables(); method public void setAllCaps(boolean); method public final void setAutoLinkMask(int); method public void setCompoundDrawablePadding(int); diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index b0930b2ae287..8bd173893794 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -124,6 +124,22 @@ public class NetworkStatsHistory implements Parcelable { return bucketDuration; } + public long getStart() { + if (bucketCount > 0) { + return bucketStart[0]; + } else { + return Long.MAX_VALUE; + } + } + + public long getEnd() { + if (bucketCount > 0) { + return bucketStart[bucketCount - 1] + bucketDuration; + } else { + return Long.MIN_VALUE; + } + } + /** * Return specific stats entry. */ @@ -253,9 +269,20 @@ public class NetworkStatsHistory implements Parcelable { * Return interpolated data usage across the requested range. Interpolates * across buckets, so values may be rounded slightly. */ - public long[] getTotalData(long start, long end, long[] outTotal) { - long rx = 0; - long tx = 0; + public Entry getValues(long start, long end, Entry recycle) { + return getValues(start, end, Long.MAX_VALUE, recycle); + } + + /** + * Return interpolated data usage across the requested range. Interpolates + * across buckets, so values may be rounded slightly. + */ + public Entry getValues(long start, long end, long now, Entry recycle) { + final Entry entry = recycle != null ? recycle : new Entry(); + entry.bucketStart = start; + entry.bucketDuration = end - start; + entry.rxBytes = 0; + entry.txBytes = 0; for (int i = bucketCount - 1; i >= 0; i--) { final long curStart = bucketStart[i]; @@ -266,19 +293,19 @@ public class NetworkStatsHistory implements Parcelable { // bucket is newer than record; keep looking if (curStart > end) continue; + // include full value for active buckets, otherwise only fractional + final boolean activeBucket = curStart < now && curEnd > now; final long overlap = Math.min(curEnd, end) - Math.max(curStart, start); - if (overlap > 0) { - rx += this.rxBytes[i] * overlap / bucketDuration; - tx += this.txBytes[i] * overlap / bucketDuration; + if (activeBucket || overlap == bucketDuration) { + entry.rxBytes += rxBytes[i]; + entry.txBytes += txBytes[i]; + } else if (overlap > 0) { + entry.rxBytes += rxBytes[i] * overlap / bucketDuration; + entry.txBytes += txBytes[i] * overlap / bucketDuration; } } - if (outTotal == null || outTotal.length != 2) { - outTotal = new long[2]; - } - outTotal[0] = rx; - outTotal[1] = tx; - return outTotal; + return entry; } /** diff --git a/core/java/android/net/http/AndroidHttpClient.java b/core/java/android/net/http/AndroidHttpClient.java index 641a576edd45..c534e58f37e1 100644 --- a/core/java/android/net/http/AndroidHttpClient.java +++ b/core/java/android/net/http/AndroidHttpClient.java @@ -65,7 +65,7 @@ import android.util.Base64; import android.util.Log; /** - * Subclass of the Apache {@link DefaultHttpClient} that is configured with + * Implementation of the Apache {@link DefaultHttpClient} that is configured with * reasonable default settings and registered schemes for Android, and * also lets the user add {@link HttpRequestInterceptor} classes. * Don't create this directly, use the {@link #newInstance} factory method. diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java index 8ef4295de33a..12109417b2d5 100644 --- a/core/java/android/speech/tts/AudioPlaybackHandler.java +++ b/core/java/android/speech/tts/AudioPlaybackHandler.java @@ -384,7 +384,7 @@ class AudioPlaybackHandler { } count += written; } - + param.mBytesWritten += count; param.mLogger.onPlaybackStart(); } @@ -396,14 +396,16 @@ class AudioPlaybackHandler { params.mLogger.onWriteData(); } - // Flush all remaining data to the audio track, stop it and release - // all it's resources. + // Wait for the audio track to stop playing, and then release it's resources. private void handleSynthesisDone(SynthesisMessageParams params) { if (DBG) Log.d(TAG, "handleSynthesisDone()"); final AudioTrack audioTrack = params.getAudioTrack(); try { if (audioTrack != null) { + if (DBG) Log.d(TAG, "Waiting for audio track to complete : " + + audioTrack.hashCode()); + blockUntilDone(params); if (DBG) Log.d(TAG, "Releasing audio track [" + audioTrack.hashCode() + "]"); // The last call to AudioTrack.write( ) will return only after // all data from the audioTrack has been sent to the mixer, so @@ -417,6 +419,18 @@ class AudioPlaybackHandler { } } + private static void blockUntilDone(SynthesisMessageParams params) { + if (params.mAudioTrack == null || params.mBytesWritten <= 0) { + return; + } + + final AudioTrack track = params.mAudioTrack; + final int bytesPerFrame = getBytesPerFrame(params.mAudioFormat); + final int lengthInBytes = params.mBytesWritten; + + blockUntilDone(track, bytesPerFrame, lengthInBytes); + } + private void handleSynthesisCompleteDataAvailable(MessageParams msg) { final SynthesisMessageParams params = (SynthesisMessageParams) msg; if (DBG) Log.d(TAG, "completeAudioAvailable(" + params + ")"); @@ -455,13 +469,18 @@ class AudioPlaybackHandler { } - private static void blockUntilDone(AudioTrack audioTrack, int bytesPerFrame, int length) { - int lengthInFrames = length / bytesPerFrame; + private static void blockUntilDone(AudioTrack audioTrack, int bytesPerFrame, + int lengthInBytes) { + int lengthInFrames = lengthInBytes / bytesPerFrame; int currentPosition = 0; while ((currentPosition = audioTrack.getPlaybackHeadPosition()) < lengthInFrames) { + if (audioTrack.getPlayState() != AudioTrack.PLAYSTATE_PLAYING) { + break; + } + long estimatedTimeMs = ((lengthInFrames - currentPosition) * 1000) / audioTrack.getSampleRate(); - audioTrack.getPlayState(); + if (DBG) Log.d(TAG, "About to sleep for : " + estimatedTimeMs + " ms," + " Playback position : " + currentPosition); try { diff --git a/core/java/android/speech/tts/SynthesisMessageParams.java b/core/java/android/speech/tts/SynthesisMessageParams.java index caf02ef3eb56..ffe70e27378e 100644 --- a/core/java/android/speech/tts/SynthesisMessageParams.java +++ b/core/java/android/speech/tts/SynthesisMessageParams.java @@ -32,7 +32,9 @@ final class SynthesisMessageParams extends MessageParams { final float mPan; final EventLogger mLogger; - public volatile AudioTrack mAudioTrack; + volatile AudioTrack mAudioTrack; + // Not volatile, accessed only from the synthesis thread. + int mBytesWritten; private final LinkedList<ListEntry> mDataBufferList = new LinkedList<ListEntry>(); @@ -52,6 +54,7 @@ final class SynthesisMessageParams extends MessageParams { // initially null. mAudioTrack = null; + mBytesWritten = 0; } @Override diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 766b520f2b40..6b4e4542cd5e 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -16,11 +16,6 @@ package android.widget; -import com.android.internal.util.FastMath; -import com.android.internal.widget.EditableInputConnection; - -import org.xmlpull.v1.XmlPullParserException; - import android.R; import android.content.ClipData; import android.content.ClipData.Item; @@ -132,6 +127,11 @@ import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; import android.widget.RemoteViews.RemoteView; +import com.android.internal.util.FastMath; +import com.android.internal.widget.EditableInputConnection; + +import org.xmlpull.v1.XmlPullParserException; + import java.io.IOException; import java.lang.ref.WeakReference; import java.text.BreakIterator; @@ -260,9 +260,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener class Drawables { final Rect mCompoundRect = new Rect(); - Drawable mDrawableTop, mDrawableBottom, mDrawableLeft, mDrawableRight; - int mDrawableSizeTop, mDrawableSizeBottom, mDrawableSizeLeft, mDrawableSizeRight; - int mDrawableWidthTop, mDrawableWidthBottom, mDrawableHeightLeft, mDrawableHeightRight; + Drawable mDrawableTop, mDrawableBottom, mDrawableLeft, mDrawableRight, + mDrawableStart, mDrawableEnd; + int mDrawableSizeTop, mDrawableSizeBottom, mDrawableSizeLeft, mDrawableSizeRight, + mDrawableSizeStart, mDrawableSizeEnd; + int mDrawableWidthTop, mDrawableWidthBottom, mDrawableHeightLeft, mDrawableHeightRight, + mDrawableHeightStart, mDrawableHeightEnd; int mDrawablePadding; } private Drawables mDrawables; @@ -352,6 +355,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener INHERIT, GRAVITY, TEXT_START, TEXT_END, CENTER, VIEW_START, VIEW_END; } + private boolean bResolvedDrawables = false; + /* * Kick-start the font cache for the zygote process (to pay the cost of * initializing freetype for our default font only once). @@ -494,7 +499,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener int buffertype = 0; boolean selectallonfocus = false; Drawable drawableLeft = null, drawableTop = null, drawableRight = null, - drawableBottom = null; + drawableBottom = null, drawableStart = null, drawableEnd = null; int drawablePadding = 0; int ellipsize = -1; boolean singleLine = false; @@ -571,6 +576,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener drawableBottom = a.getDrawable(attr); break; + case com.android.internal.R.styleable.TextView_drawableStart: + drawableStart = a.getDrawable(attr); + break; + + case com.android.internal.R.styleable.TextView_drawableEnd: + drawableEnd = a.getDrawable(attr); + break; + case com.android.internal.R.styleable.TextView_drawablePadding: drawablePadding = a.getDimensionPixelSize(attr, drawablePadding); break; @@ -980,6 +993,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener setCompoundDrawablesWithIntrinsicBounds( drawableLeft, drawableTop, drawableRight, drawableBottom); + setRelativeDrawablesIfNeeded(drawableStart, drawableEnd); setCompoundDrawablePadding(drawablePadding); // Same as setSingleLine(), but make sure the transformation method and the maximum number @@ -1105,6 +1119,42 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener setTypeface(tf, styleIndex); } + private void setRelativeDrawablesIfNeeded(Drawable start, Drawable end) { + boolean hasRelativeDrawables = (start != null) || (end != null); + if (hasRelativeDrawables) { + Drawables dr = mDrawables; + if (dr == null) { + mDrawables = dr = new Drawables(); + } + final Rect compoundRect = dr.mCompoundRect; + int[] state = getDrawableState(); + if (start != null) { + start.setBounds(0, 0, start.getIntrinsicWidth(), start.getIntrinsicHeight()); + start.setState(state); + start.copyBounds(compoundRect); + start.setCallback(this); + + dr.mDrawableStart = start; + dr.mDrawableSizeStart = compoundRect.width(); + dr.mDrawableHeightStart = compoundRect.height(); + } else { + dr.mDrawableSizeStart = dr.mDrawableHeightStart = 0; + } + if (end != null) { + end.setBounds(0, 0, end.getIntrinsicWidth(), end.getIntrinsicHeight()); + end.setState(state); + end.copyBounds(compoundRect); + end.setCallback(this); + + dr.mDrawableEnd = end; + dr.mDrawableSizeEnd = compoundRect.width(); + dr.mDrawableHeightEnd = compoundRect.height(); + } else { + dr.mDrawableSizeEnd = dr.mDrawableHeightEnd = 0; + } + } + } + @Override public void setEnabled(boolean enabled) { if (enabled == isEnabled()) { @@ -1119,6 +1169,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } super.setEnabled(enabled); + prepareCursorControllers(); } /** @@ -1410,6 +1461,40 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** + * Returns the start padding of the view, plus space for the start + * Drawable if any. + * + * @hide + */ + public int getCompoundPaddingStart() { + resolveDrawables(); + switch(getResolvedLayoutDirection()) { + default: + case LAYOUT_DIRECTION_LTR: + return getCompoundPaddingLeft(); + case LAYOUT_DIRECTION_RTL: + return getCompoundPaddingRight(); + } + } + + /** + * Returns the end padding of the view, plus space for the end + * Drawable if any. + * + * @hide + */ + public int getCompoundPaddingEnd() { + resolveDrawables(); + switch(getResolvedLayoutDirection()) { + default: + case LAYOUT_DIRECTION_LTR: + return getCompoundPaddingRight(); + case LAYOUT_DIRECTION_RTL: + return getCompoundPaddingLeft(); + } + } + + /** * Returns the extended top padding of the view, including both the * top Drawable if any and any extra space to keep more than maxLines * of text from showing. It is only valid to call this after measuring. @@ -1492,6 +1577,26 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** + * Returns the total start padding of the view, including the start + * Drawable if any. + * + * @hide + */ + public int getTotalPaddingStart() { + return getCompoundPaddingStart(); + } + + /** + * Returns the total end padding of the view, including the end + * Drawable if any. + * + * @hide + */ + public int getTotalPaddingEnd() { + return getCompoundPaddingEnd(); + } + + /** * Returns the total top padding of the view, including the top * Drawable if any, the extra space to keep more than maxLines * from showing, and the vertical offset for gravity, if any. @@ -1678,6 +1783,185 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** + * Sets the Drawables (if any) to appear to the start of, above, + * to the end of, and below the text. Use null if you do not + * want a Drawable there. The Drawables must already have had + * {@link Drawable#setBounds} called. + * + * @attr ref android.R.styleable#TextView_drawableStart + * @attr ref android.R.styleable#TextView_drawableTop + * @attr ref android.R.styleable#TextView_drawableEnd + * @attr ref android.R.styleable#TextView_drawableBottom + * + * @hide + */ + public void setCompoundDrawablesRelative(Drawable start, Drawable top, + Drawable end, Drawable bottom) { + Drawables dr = mDrawables; + + final boolean drawables = start != null || top != null + || end != null || bottom != null; + + if (!drawables) { + // Clearing drawables... can we free the data structure? + if (dr != null) { + if (dr.mDrawablePadding == 0) { + mDrawables = null; + } else { + // We need to retain the last set padding, so just clear + // out all of the fields in the existing structure. + if (dr.mDrawableStart != null) dr.mDrawableStart.setCallback(null); + dr.mDrawableStart = null; + if (dr.mDrawableTop != null) dr.mDrawableTop.setCallback(null); + dr.mDrawableTop = null; + if (dr.mDrawableEnd != null) dr.mDrawableEnd.setCallback(null); + dr.mDrawableEnd = null; + if (dr.mDrawableBottom != null) dr.mDrawableBottom.setCallback(null); + dr.mDrawableBottom = null; + dr.mDrawableSizeStart = dr.mDrawableHeightStart = 0; + dr.mDrawableSizeEnd = dr.mDrawableHeightEnd = 0; + dr.mDrawableSizeTop = dr.mDrawableWidthTop = 0; + dr.mDrawableSizeBottom = dr.mDrawableWidthBottom = 0; + } + } + } else { + if (dr == null) { + mDrawables = dr = new Drawables(); + } + + if (dr.mDrawableStart != start && dr.mDrawableStart != null) { + dr.mDrawableStart.setCallback(null); + } + dr.mDrawableStart = start; + + if (dr.mDrawableTop != top && dr.mDrawableTop != null) { + dr.mDrawableTop.setCallback(null); + } + dr.mDrawableTop = top; + + if (dr.mDrawableEnd != end && dr.mDrawableEnd != null) { + dr.mDrawableEnd.setCallback(null); + } + dr.mDrawableEnd = end; + + if (dr.mDrawableBottom != bottom && dr.mDrawableBottom != null) { + dr.mDrawableBottom.setCallback(null); + } + dr.mDrawableBottom = bottom; + + final Rect compoundRect = dr.mCompoundRect; + int[] state; + + state = getDrawableState(); + + if (start != null) { + start.setState(state); + start.copyBounds(compoundRect); + start.setCallback(this); + dr.mDrawableSizeStart = compoundRect.width(); + dr.mDrawableHeightStart = compoundRect.height(); + } else { + dr.mDrawableSizeStart = dr.mDrawableHeightStart = 0; + } + + if (end != null) { + end.setState(state); + end.copyBounds(compoundRect); + end.setCallback(this); + dr.mDrawableSizeEnd = compoundRect.width(); + dr.mDrawableHeightEnd = compoundRect.height(); + } else { + dr.mDrawableSizeEnd = dr.mDrawableHeightEnd = 0; + } + + if (top != null) { + top.setState(state); + top.copyBounds(compoundRect); + top.setCallback(this); + dr.mDrawableSizeTop = compoundRect.height(); + dr.mDrawableWidthTop = compoundRect.width(); + } else { + dr.mDrawableSizeTop = dr.mDrawableWidthTop = 0; + } + + if (bottom != null) { + bottom.setState(state); + bottom.copyBounds(compoundRect); + bottom.setCallback(this); + dr.mDrawableSizeBottom = compoundRect.height(); + dr.mDrawableWidthBottom = compoundRect.width(); + } else { + dr.mDrawableSizeBottom = dr.mDrawableWidthBottom = 0; + } + } + + resolveDrawables(); + invalidate(); + requestLayout(); + } + + /** + * Sets the Drawables (if any) to appear to the start of, above, + * to the end of, and below the text. Use 0 if you do not + * want a Drawable there. The Drawables' bounds will be set to + * their intrinsic bounds. + * + * @param start Resource identifier of the start Drawable. + * @param top Resource identifier of the top Drawable. + * @param end Resource identifier of the end Drawable. + * @param bottom Resource identifier of the bottom Drawable. + * + * @attr ref android.R.styleable#TextView_drawableStart + * @attr ref android.R.styleable#TextView_drawableTop + * @attr ref android.R.styleable#TextView_drawableEnd + * @attr ref android.R.styleable#TextView_drawableBottom + * + * @hide + */ + public void setCompoundDrawablesRelativeWithIntrinsicBounds(int start, int top, int end, + int bottom) { + resetResolvedDrawables(); + final Resources resources = getContext().getResources(); + setCompoundDrawablesRelativeWithIntrinsicBounds( + start != 0 ? resources.getDrawable(start) : null, + top != 0 ? resources.getDrawable(top) : null, + end != 0 ? resources.getDrawable(end) : null, + bottom != 0 ? resources.getDrawable(bottom) : null); + } + + /** + * Sets the Drawables (if any) to appear to the start of, above, + * to the end of, and below the text. Use null if you do not + * want a Drawable there. The Drawables' bounds will be set to + * their intrinsic bounds. + * + * @attr ref android.R.styleable#TextView_drawableStart + * @attr ref android.R.styleable#TextView_drawableTop + * @attr ref android.R.styleable#TextView_drawableEnd + * @attr ref android.R.styleable#TextView_drawableBottom + * + * @hide + */ + public void setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable start, Drawable top, + Drawable end, Drawable bottom) { + + resetResolvedDrawables(); + if (start != null) { + start.setBounds(0, 0, start.getIntrinsicWidth(), start.getIntrinsicHeight()); + } + if (end != null) { + end.setBounds(0, 0, end.getIntrinsicWidth(), end.getIntrinsicHeight()); + } + if (top != null) { + top.setBounds(0, 0, top.getIntrinsicWidth(), top.getIntrinsicHeight()); + } + if (bottom != null) { + bottom.setBounds(0, 0, bottom.getIntrinsicWidth(), bottom.getIntrinsicHeight()); + } + setCompoundDrawablesRelative(start, top, end, bottom); + } + + /** * Returns drawables for the left, top, right, and bottom borders. */ public Drawable[] getCompoundDrawables() { @@ -1692,6 +1976,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** + * Returns drawables for the start, top, end, and bottom borders. + * + * @hide + */ + public Drawable[] getCompoundDrawablesRelative() { + final Drawables dr = mDrawables; + if (dr != null) { + return new Drawable[] { + dr.mDrawableStart, dr.mDrawableTop, dr.mDrawableEnd, dr.mDrawableBottom + }; + } else { + return new Drawable[] { null, null, null, null }; + } + } + + /** * Sets the size of the padding between the compound drawables and * the text. * @@ -2494,6 +2794,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (dr.mDrawableRight != null && dr.mDrawableRight.isStateful()) { dr.mDrawableRight.setState(state); } + if (dr.mDrawableStart != null && dr.mDrawableStart.isStateful()) { + dr.mDrawableStart.setState(state); + } + if (dr.mDrawableEnd != null && dr.mDrawableEnd.isStateful()) { + dr.mDrawableEnd.setState(state); + } } } @@ -2841,8 +3147,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // Do not change the movement method for text that support text selection as it // would prevent an arbitrary cursor displacement. - final boolean hasTextSelection = this instanceof EditText || mTextIsSelectable; - if (mLinksClickable && !hasTextSelection) { + if (mLinksClickable && !textCanBeSelected()) { setMovementMethod(LinkMovementMethod.getInstance()); } } @@ -3546,7 +3851,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mErrorWasChanged = true; final Drawables dr = mDrawables; if (dr != null) { - setCompoundDrawables(dr.mDrawableLeft, dr.mDrawableTop, icon, dr.mDrawableBottom); + switch (getResolvedLayoutDirection()) { + default: + case LAYOUT_DIRECTION_LTR: + setCompoundDrawables(dr.mDrawableLeft, dr.mDrawableTop, icon, + dr.mDrawableBottom); + break; + case LAYOUT_DIRECTION_RTL: + setCompoundDrawables(icon, dr.mDrawableTop, dr.mDrawableRight, + dr.mDrawableBottom); + break; + } } else { setCompoundDrawables(null, null, icon, null); } @@ -4048,6 +4363,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mSelectionModifierCursorController != null) { observer.addOnTouchModeChangeListener(mSelectionModifierCursorController); } + + // Resolve drawables as the layout direction has been resolved + resolveDrawables(); } @Override @@ -4077,6 +4395,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } hideControllers(); + + resetResolvedDrawables(); } @Override @@ -4111,7 +4431,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final boolean verified = super.verifyDrawable(who); if (!verified && mDrawables != null) { return who == mDrawables.mDrawableLeft || who == mDrawables.mDrawableTop || - who == mDrawables.mDrawableRight || who == mDrawables.mDrawableBottom; + who == mDrawables.mDrawableRight || who == mDrawables.mDrawableBottom || + who == mDrawables.mDrawableStart || who == mDrawables.mDrawableEnd; } return verified; } @@ -4132,6 +4453,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mDrawables.mDrawableBottom != null) { mDrawables.mDrawableBottom.jumpToCurrentState(); } + if (mDrawables.mDrawableStart != null) { + mDrawables.mDrawableStart.jumpToCurrentState(); + } + if (mDrawables.mDrawableEnd != null) { + mDrawables.mDrawableEnd.jumpToCurrentState(); + } } } @@ -4192,7 +4519,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mDrawables != null) { final Drawables drawables = mDrawables; if (who == drawables.mDrawableLeft || who == drawables.mDrawableRight || - who == drawables.mDrawableTop || who == drawables.mDrawableBottom) { + who == drawables.mDrawableTop || who == drawables.mDrawableBottom || + who == drawables.mDrawableStart || who == drawables.mDrawableEnd) { return getResolvedLayoutDirection(); } } @@ -4211,6 +4539,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (dr.mDrawableTop != null) dr.mDrawableTop.mutate().setAlpha(alpha); if (dr.mDrawableRight != null) dr.mDrawableRight.mutate().setAlpha(alpha); if (dr.mDrawableBottom != null) dr.mDrawableBottom.mutate().setAlpha(alpha); + if (dr.mDrawableStart != null) dr.mDrawableStart.mutate().setAlpha(alpha); + if (dr.mDrawableEnd != null) dr.mDrawableEnd.mutate().setAlpha(alpha); } return true; } @@ -4228,7 +4558,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * {@link android.R.styleable#TextView_textIsSelectable} XML attribute to make this TextView * selectable (text is not selectable by default). * - * Note that the content of an EditText is always selectable. + * Note that this method simply returns the state of this flag. Although this flag has to be set + * in order to select text in non-editable TextView, the content of an {@link EditText} can + * always be selected, independently of the value of this flag. * * @return True if the text displayed in this TextView can be selected by the user. * @@ -4465,12 +4797,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener selStart = getSelectionStart(); selEnd = getSelectionEnd(); - if ((isCursorVisible() || mTextIsSelectable) && selStart >= 0 && isEnabled()) { + if (selStart >= 0) { if (mHighlightPath == null) mHighlightPath = new Path(); if (selStart == selEnd) { - if (!mTextIsSelectable && + if (isCursorVisible() && (SystemClock.uptimeMillis() - mShowCursor) % (2 * BLINK) < BLINK) { if (mHighlightPathBogus) { mHighlightPath.reset(); @@ -4489,7 +4821,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener highlight = mHighlightPath; drawCursor = mCursorCount > 0; } - } else { + } else if (textCanBeSelected()) { if (mHighlightPathBogus) { mHighlightPath.reset(); mLayout.getSelectionPath(selStart, selEnd, mHighlightPath); @@ -7450,9 +7782,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public boolean onTouchEvent(MotionEvent event) { final int action = event.getActionMasked(); - if (hasInsertionController()) { - getInsertionController().onTouchEvent(event); - } if (hasSelectionController()) { getSelectionController().onTouchEvent(event); } @@ -7880,7 +8209,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // prepareCursorController() relies on this method. // If you change this condition, make sure prepareCursorController is called anywhere // the value of this condition might be changed. - return mText instanceof Spannable && mMovement != null && mMovement.canSelectArbitrarily(); + if (mMovement == null || !mMovement.canSelectArbitrarily()) return false; + return isTextEditable() || (mTextIsSelectable && mText instanceof Spannable && isEnabled()); } private boolean canCut() { @@ -7968,6 +8298,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final int minOffset = extractRangeStartFromLong(lastTouchOffsets); final int maxOffset = extractRangeEndFromLong(lastTouchOffsets); + // Safety check in case standard touch event handling has been bypassed + if (minOffset < 0 || minOffset >= mText.length()) return false; + if (maxOffset < 0 || maxOffset >= mText.length()) return false; + int selectionStart, selectionEnd; // If a URLSpan (web address, email, phone...) is found at that position, select it. @@ -9723,13 +10057,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public void hide(); /** - * This method is called by {@link #onTouchEvent(MotionEvent)} and gives the controller - * a chance to become active and/or visible. - * @param event The touch event - */ - public boolean onTouchEvent(MotionEvent event); - - /** * Called when the view is detached from window. Perform house keeping task, such as * stopping Runnable thread that would otherwise keep a reference on the context, thus * preventing the activity from being recycled. @@ -9756,10 +10083,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } - public boolean onTouchEvent(MotionEvent ev) { - return false; - } - public void onTouchModeChanged(boolean isInTouchMode) { if (!isInTouchMode) { hide(); @@ -9818,52 +10141,49 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mEndHandle != null) mEndHandle.hide(); } - public boolean onTouchEvent(MotionEvent event) { + public void onTouchEvent(MotionEvent event) { // This is done even when the View does not have focus, so that long presses can start // selection and tap can move cursor from this tap position. - if (isTextEditable() || mTextIsSelectable) { - switch (event.getActionMasked()) { - case MotionEvent.ACTION_DOWN: - final float x = event.getX(); - final float y = event.getY(); - - // Remember finger down position, to be able to start selection from there - mMinTouchOffset = mMaxTouchOffset = getOffsetForPosition(x, y); - - // Double tap detection - long duration = SystemClock.uptimeMillis() - mPreviousTapUpTime; - if (duration <= ViewConfiguration.getDoubleTapTimeout() && - isPositionOnText(x, y)) { - final float deltaX = x - mPreviousTapPositionX; - final float deltaY = y - mPreviousTapPositionY; - final float distanceSquared = deltaX * deltaX + deltaY * deltaY; - if (distanceSquared < mSquaredTouchSlopDistance) { - showSuggestions(); - mDiscardNextActionUp = true; - } + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + final float x = event.getX(); + final float y = event.getY(); + + // Remember finger down position, to be able to start selection from there + mMinTouchOffset = mMaxTouchOffset = getOffsetForPosition(x, y); + + // Double tap detection + long duration = SystemClock.uptimeMillis() - mPreviousTapUpTime; + if (duration <= ViewConfiguration.getDoubleTapTimeout() && + isPositionOnText(x, y)) { + final float deltaX = x - mPreviousTapPositionX; + final float deltaY = y - mPreviousTapPositionY; + final float distanceSquared = deltaX * deltaX + deltaY * deltaY; + if (distanceSquared < mSquaredTouchSlopDistance) { + showSuggestions(); + mDiscardNextActionUp = true; } + } - mPreviousTapPositionX = x; - mPreviousTapPositionY = y; + mPreviousTapPositionX = x; + mPreviousTapPositionY = y; - break; + break; - case MotionEvent.ACTION_POINTER_DOWN: - case MotionEvent.ACTION_POINTER_UP: - // Handle multi-point gestures. Keep min and max offset positions. - // Only activated for devices that correctly handle multi-touch. - if (mContext.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT)) { - updateMinAndMaxOffsets(event); - } - break; + case MotionEvent.ACTION_POINTER_DOWN: + case MotionEvent.ACTION_POINTER_UP: + // Handle multi-point gestures. Keep min and max offset positions. + // Only activated for devices that correctly handle multi-touch. + if (mContext.getPackageManager().hasSystemFeature( + PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT)) { + updateMinAndMaxOffsets(event); + } + break; - case MotionEvent.ACTION_UP: - mPreviousTapUpTime = SystemClock.uptimeMillis(); - break; - } + case MotionEvent.ACTION_UP: + mPreviousTapUpTime = SystemClock.uptimeMillis(); + break; } - return false; } /** @@ -10285,6 +10605,68 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return (dir == Character.DIRECTIONALITY_LEFT_TO_RIGHT); } + /** + * Subclasses will need to override this method to implement their own way of resolving + * drawables depending on the layout direction. + * + * A call to the super method will be required from the subclasses implementation. + * + */ + protected void resolveDrawables() { + // No need to resolve twice + if (bResolvedDrawables) { + return; + } + // No drawable to resolve + if (mDrawables == null) { + return; + } + // No relative drawable to resolve + if (mDrawables.mDrawableStart == null && mDrawables.mDrawableEnd == null) { + bResolvedDrawables = true; + return; + } + + Drawables dr = mDrawables; + switch(getResolvedLayoutDirection()) { + case LAYOUT_DIRECTION_RTL: + if (dr.mDrawableStart != null) { + dr.mDrawableRight = dr.mDrawableStart; + + dr.mDrawableSizeRight = dr.mDrawableSizeStart; + dr.mDrawableHeightRight = dr.mDrawableHeightStart; + } + if (dr.mDrawableEnd != null) { + dr.mDrawableLeft = dr.mDrawableEnd; + + dr.mDrawableSizeLeft = dr.mDrawableSizeEnd; + dr.mDrawableHeightLeft = dr.mDrawableHeightEnd; + } + break; + + case LAYOUT_DIRECTION_LTR: + default: + if (dr.mDrawableStart != null) { + dr.mDrawableLeft = dr.mDrawableStart; + + dr.mDrawableSizeLeft = dr.mDrawableSizeStart; + dr.mDrawableHeightLeft = dr.mDrawableHeightStart; + } + if (dr.mDrawableEnd != null) { + dr.mDrawableRight = dr.mDrawableEnd; + + dr.mDrawableSizeRight = dr.mDrawableSizeEnd; + dr.mDrawableHeightRight = dr.mDrawableHeightEnd; + } + break; + } + bResolvedDrawables = true; + } + + protected void resetResolvedDrawables() { + bResolvedDrawables = false; + } + @ViewDebug.ExportedProperty(category = "text") private CharSequence mText; private CharSequence mTransformed; diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 9c2133f0fd68..cfc5041cddbc 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -3015,6 +3015,10 @@ <attr name="drawableLeft" format="reference|color" /> <!-- The drawable to be drawn to the right of the text. --> <attr name="drawableRight" format="reference|color" /> + <!-- The drawable to be drawn to the start of the text. --> + <attr name="drawableStart" format="reference|color" /> + <!-- The drawable to be drawn to the end of the text. --> + <attr name="drawableEnd" format="reference|color" /> <!-- The padding between the drawables and the text. --> <attr name="drawablePadding" format="dimension" /> <!-- Extra spacing between lines of text. --> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index f7701f287213..6dedc83eb087 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1826,4 +1826,7 @@ <public type="color" name="holo_purple" /> <public type="color" name="holo_blue_bright" /> + <public type="attr" name="drawableStart" /> + <public type="attr" name="drawableEnd" /> + </resources> diff --git a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java index 16bb00060eef..9403d95700d4 100644 --- a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java +++ b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java @@ -55,7 +55,7 @@ public class NetworkStatsHistoryTest extends TestCase { stats.recordData(TEST_START, TEST_START + SECOND_IN_MILLIS, 1024L, 2048L); assertEquals(1, stats.size()); - assertEntry(stats, 0, 1024L, 2048L); + assertValues(stats, 0, 1024L, 2048L); } public void testRecordEqualBuckets() throws Exception { @@ -67,8 +67,8 @@ public class NetworkStatsHistoryTest extends TestCase { stats.recordData(recordStart, recordStart + bucketDuration, 1024L, 128L); assertEquals(2, stats.size()); - assertEntry(stats, 0, 512L, 64L); - assertEntry(stats, 1, 512L, 64L); + assertValues(stats, 0, 512L, 64L); + assertValues(stats, 1, 512L, 64L); } public void testRecordTouchingBuckets() throws Exception { @@ -83,11 +83,11 @@ public class NetworkStatsHistoryTest extends TestCase { assertEquals(3, stats.size()); // first bucket should have (1/20 of value) - assertEntry(stats, 0, 50L, 250L); + assertValues(stats, 0, 50L, 250L); // second bucket should have (15/20 of value) - assertEntry(stats, 1, 750L, 3750L); + assertValues(stats, 1, 750L, 3750L); // final bucket should have (4/20 of value) - assertEntry(stats, 2, 200L, 1000L); + assertValues(stats, 2, 200L, 1000L); } public void testRecordGapBuckets() throws Exception { @@ -102,8 +102,8 @@ public class NetworkStatsHistoryTest extends TestCase { // we should have two buckets, far apart from each other assertEquals(2, stats.size()); - assertEntry(stats, 0, 128L, 256L); - assertEntry(stats, 1, 64L, 512L); + assertValues(stats, 0, 128L, 256L); + assertValues(stats, 1, 64L, 512L); // now record something in middle, spread across two buckets final long middleStart = TEST_START + DAY_IN_MILLIS; @@ -112,10 +112,10 @@ public class NetworkStatsHistoryTest extends TestCase { // now should have four buckets, with new record in middle two buckets assertEquals(4, stats.size()); - assertEntry(stats, 0, 128L, 256L); - assertEntry(stats, 1, 1024L, 1024L); - assertEntry(stats, 2, 1024L, 1024L); - assertEntry(stats, 3, 64L, 512L); + assertValues(stats, 0, 128L, 256L); + assertValues(stats, 1, 1024L, 1024L); + assertValues(stats, 2, 1024L, 1024L); + assertValues(stats, 3, 64L, 512L); } public void testRecordOverlapBuckets() throws Exception { @@ -129,13 +129,11 @@ public class NetworkStatsHistoryTest extends TestCase { // should have two buckets, with some data mixed together assertEquals(2, stats.size()); - assertEntry(stats, 0, 768L, 768L); - assertEntry(stats, 1, 512L, 512L); + assertValues(stats, 0, 768L, 768L); + assertValues(stats, 1, 512L, 512L); } public void testRecordEntireGapIdentical() throws Exception { - final long[] total = new long[2]; - // first, create two separate histories far apart final NetworkStatsHistory stats1 = new NetworkStatsHistory(HOUR_IN_MILLIS); stats1.recordData(TEST_START, TEST_START + 2 * HOUR_IN_MILLIS, 2000L, 1000L); @@ -150,19 +148,16 @@ public class NetworkStatsHistoryTest extends TestCase { stats.recordEntireHistory(stats2); // first verify that totals match up - stats.getTotalData(TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, total); - assertTotalEquals(total, 3000L, 1500L); + assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, 3000L, 1500L); // now inspect internal buckets - assertEntry(stats, 0, 1000L, 500L); - assertEntry(stats, 1, 1000L, 500L); - assertEntry(stats, 2, 500L, 250L); - assertEntry(stats, 3, 500L, 250L); + assertValues(stats, 0, 1000L, 500L); + assertValues(stats, 1, 1000L, 500L); + assertValues(stats, 2, 500L, 250L); + assertValues(stats, 3, 500L, 250L); } public void testRecordEntireOverlapVaryingBuckets() throws Exception { - final long[] total = new long[2]; - // create history just over hour bucket boundary final NetworkStatsHistory stats1 = new NetworkStatsHistory(HOUR_IN_MILLIS); stats1.recordData(TEST_START, TEST_START + MINUTE_IN_MILLIS * 60, 600L, 600L); @@ -177,17 +172,16 @@ public class NetworkStatsHistoryTest extends TestCase { stats.recordEntireHistory(stats2); // first verify that totals match up - stats.getTotalData(TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, total); - assertTotalEquals(total, 650L, 650L); + assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, 650L, 650L); // now inspect internal buckets - assertEntry(stats, 0, 10L, 10L); - assertEntry(stats, 1, 20L, 20L); - assertEntry(stats, 2, 20L, 20L); - assertEntry(stats, 3, 20L, 20L); - assertEntry(stats, 4, 20L, 20L); - assertEntry(stats, 5, 20L, 20L); - assertEntry(stats, 6, 10L, 10L); + assertValues(stats, 0, 10L, 10L); + assertValues(stats, 1, 20L, 20L); + assertValues(stats, 2, 20L, 20L); + assertValues(stats, 3, 20L, 20L); + assertValues(stats, 4, 20L, 20L); + assertValues(stats, 5, 20L, 20L); + assertValues(stats, 6, 10L, 10L); // now combine using 15min buckets stats = new NetworkStatsHistory(HOUR_IN_MILLIS / 4); @@ -195,14 +189,13 @@ public class NetworkStatsHistoryTest extends TestCase { stats.recordEntireHistory(stats2); // first verify that totals match up - stats.getTotalData(TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, total); - assertTotalEquals(total, 650L, 650L); + assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, 650L, 650L); // and inspect buckets - assertEntry(stats, 0, 200L, 200L); - assertEntry(stats, 1, 150L, 150L); - assertEntry(stats, 2, 150L, 150L); - assertEntry(stats, 3, 150L, 150L); + assertValues(stats, 0, 200L, 200L); + assertValues(stats, 1, 150L, 150L); + assertValues(stats, 2, 150L, 150L); + assertValues(stats, 3, 150L, 150L); } public void testRemove() throws Exception { @@ -241,27 +234,20 @@ public class NetworkStatsHistoryTest extends TestCase { // record uniform data across day stats.recordData(TEST_START, TEST_START + DAY_IN_MILLIS, 2400L, 4800L); - final long[] total = new long[2]; - // verify that total outside range is 0 - stats.getTotalData(TEST_START - WEEK_IN_MILLIS, TEST_START - DAY_IN_MILLIS, total); - assertTotalEquals(total, 0, 0); + assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START - DAY_IN_MILLIS, 0L, 0L); // verify total in first hour - stats.getTotalData(TEST_START, TEST_START + HOUR_IN_MILLIS, total); - assertTotalEquals(total, 100, 200); + assertValues(stats, TEST_START, TEST_START + HOUR_IN_MILLIS, 100L, 200L); // verify total across 1.5 hours - stats.getTotalData(TEST_START, TEST_START + (long) (1.5 * HOUR_IN_MILLIS), total); - assertTotalEquals(total, 150, 300); + assertValues(stats, TEST_START, TEST_START + (long) (1.5 * HOUR_IN_MILLIS), 150L, 300L); // verify total beyond end - stats.getTotalData(TEST_START + (23 * HOUR_IN_MILLIS), TEST_START + WEEK_IN_MILLIS, total); - assertTotalEquals(total, 100, 200); + assertValues(stats, TEST_START + (23 * HOUR_IN_MILLIS), TEST_START + WEEK_IN_MILLIS, 100L, 200L); // verify everything total - stats.getTotalData(TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, total); - assertTotalEquals(total, 2400, 4800); + assertValues(stats, TEST_START - WEEK_IN_MILLIS, TEST_START + WEEK_IN_MILLIS, 2400L, 4800L); } @@ -302,16 +288,18 @@ public class NetworkStatsHistoryTest extends TestCase { } } - private static void assertTotalEquals(long[] total, long rxBytes, long txBytes) { - assertEquals("unexpected rxBytes", rxBytes, total[0]); - assertEquals("unexpected txBytes", txBytes, total[1]); - } - - private static void assertEntry( + private static void assertValues( NetworkStatsHistory stats, int index, long rxBytes, long txBytes) { final NetworkStatsHistory.Entry entry = stats.getValues(index, null); assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); assertEquals("unexpected txBytes", txBytes, entry.txBytes); } + private static void assertValues( + NetworkStatsHistory stats, long start, long end, long rxBytes, long txBytes) { + final NetworkStatsHistory.Entry entry = stats.getValues(start, end, null); + assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); + assertEquals("unexpected txBytes", txBytes, entry.txBytes); + } + } diff --git a/include/media/IStreamSource.h b/include/media/IStreamSource.h index d310cee3096d..cc63356803df 100644 --- a/include/media/IStreamSource.h +++ b/include/media/IStreamSource.h @@ -51,6 +51,17 @@ struct IStreamListener : public IInterface { // will be suppressed until media time reaches this timestamp. static const char *const kKeyResumeAtPTS; + // When signalling a discontinuity you can optionally + // signal that this is a "hard" discontinuity, i.e. the format + // or configuration of subsequent stream data differs from that + // currently active. To do so, include a non-zero int32_t value + // under the key "kKeyFormatChange" when issuing the DISCONTINUITY + // command. + // The new logical stream must start with proper codec initialization + // information for playback to continue, i.e. SPS and PPS in the case + // of AVC video etc. + static const char *const kKeyFormatChange; + virtual void issueCommand( Command cmd, bool synchronous, const sp<AMessage> &msg = NULL) = 0; }; diff --git a/libs/rs/driver/rsdBcc.cpp b/libs/rs/driver/rsdBcc.cpp index 62eb24ef7c8f..bbf283668386 100644 --- a/libs/rs/driver/rsdBcc.cpp +++ b/libs/rs/driver/rsdBcc.cpp @@ -269,6 +269,7 @@ static void wc_x(void *usr, uint32_t idx) { void rsdScriptInvokeForEach(const Context *rsc, Script *s, + uint32_t slot, const Allocation * ain, Allocation * aout, const void * usr, diff --git a/libs/rs/driver/rsdBcc.h b/libs/rs/driver/rsdBcc.h index 62b50f47348f..67929bc55a60 100644 --- a/libs/rs/driver/rsdBcc.h +++ b/libs/rs/driver/rsdBcc.h @@ -32,6 +32,7 @@ void rsdScriptInvokeFunction(const android::renderscript::Context *dc, void rsdScriptInvokeForEach(const android::renderscript::Context *rsc, android::renderscript::Script *s, + uint32_t slot, const android::renderscript::Allocation * ain, android::renderscript::Allocation * aout, const void * usr, diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp index 2b58e9eb0e03..b77b18a0b686 100644 --- a/libs/rs/rsElement.cpp +++ b/libs/rs/rsElement.cpp @@ -263,10 +263,10 @@ void Element::incRefs(const void *ptr) const { const uint8_t *p = static_cast<const uint8_t *>(ptr); for (uint32_t i=0; i < mFieldCount; i++) { if (mFields[i].e->mHasReference) { - p = &p[mFields[i].offsetBits >> 3]; + const uint8_t *p2 = &p[mFields[i].offsetBits >> 3]; for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) { - mFields[i].e->incRefs(p); - p += mFields[i].e->getSizeBytes(); + mFields[i].e->incRefs(p2); + p2 += mFields[i].e->getSizeBytes(); } } } @@ -285,10 +285,10 @@ void Element::decRefs(const void *ptr) const { const uint8_t *p = static_cast<const uint8_t *>(ptr); for (uint32_t i=0; i < mFieldCount; i++) { if (mFields[i].e->mHasReference) { - p = &p[mFields[i].offsetBits >> 3]; + const uint8_t *p2 = &p[mFields[i].offsetBits >> 3]; for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) { - mFields[i].e->decRefs(p); - p += mFields[i].e->getSizeBytes(); + mFields[i].e->decRefs(p2); + p2 += mFields[i].e->getSizeBytes(); } } } diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp index b230bb5b3a73..e8b1014f53dd 100644 --- a/libs/rs/rsScriptC.cpp +++ b/libs/rs/rsScriptC.cpp @@ -121,7 +121,7 @@ void ScriptC::runForEach(Context *rsc, setupGLState(rsc); setupScript(rsc); - rsc->mHal.funcs.script.invokeForEach(rsc, this, ain, aout, usr, usrBytes, sc); + rsc->mHal.funcs.script.invokeForEach(rsc, this, 0, ain, aout, usr, usrBytes, sc); } void ScriptC::Invoke(Context *rsc, uint32_t slot, const void *data, size_t len) { diff --git a/libs/rs/rs_hal.h b/libs/rs/rs_hal.h index 928dca5376ed..6a4537b392a2 100644 --- a/libs/rs/rs_hal.h +++ b/libs/rs/rs_hal.h @@ -70,6 +70,7 @@ typedef struct { int (*invokeRoot)(const Context *rsc, Script *s); void (*invokeForEach)(const Context *rsc, Script *s, + uint32_t slot, const Allocation * ain, Allocation * aout, const void * usr, diff --git a/media/java/android/mtp/MtpServer.java b/media/java/android/mtp/MtpServer.java index 0133cf601463..f561cc0bbbad 100644 --- a/media/java/android/mtp/MtpServer.java +++ b/media/java/android/mtp/MtpServer.java @@ -16,18 +16,13 @@ package android.mtp; -import android.util.Log; - /** * Java wrapper for MTP/PTP support as USB responder. * {@hide} */ -public class MtpServer { - - private final Object mLock = new Object(); - private boolean mStarted; +public class MtpServer implements Runnable { - private static final String TAG = "MtpServer"; + private int mNativeContext; // accessed by native methods static { System.loadLibrary("media_jni"); @@ -38,19 +33,14 @@ public class MtpServer { } public void start() { - synchronized (mLock) { - native_start(); - mStarted = true; - } + Thread thread = new Thread(this, "MtpServer"); + thread.start(); } - public void stop() { - synchronized (mLock) { - if (mStarted) { - native_stop(); - mStarted = false; - } - } + @Override + public void run() { + native_run(); + native_cleanup(); } public void sendObjectAdded(int handle) { @@ -70,8 +60,8 @@ public class MtpServer { } private native final void native_setup(MtpDatabase database, boolean usePtp); - private native final void native_start(); - private native final void native_stop(); + private native final void native_run(); + private native final void native_cleanup(); private native final void native_send_object_added(int handle); private native final void native_send_object_removed(int handle); private native final void native_add_storage(MtpStorage storage); diff --git a/media/jni/android_mtp_MtpServer.cpp b/media/jni/android_mtp_MtpServer.cpp index 446b6303da25..107db08d516f 100644 --- a/media/jni/android_mtp_MtpServer.cpp +++ b/media/jni/android_mtp_MtpServer.cpp @@ -22,13 +22,8 @@ #include <limits.h> #include <unistd.h> #include <fcntl.h> -#include <sys/ioctl.h> #include <utils/threads.h> -#ifdef HAVE_ANDROID_OS -#include <linux/usb/f_mtp.h> -#endif - #include "jni.h" #include "JNIHelp.h" #include "android_runtime/AndroidRuntime.h" @@ -39,8 +34,8 @@ using namespace android; -// MtpStorage class -jclass clazz_MtpStorage; +// MtpServer fields +static jfieldID field_MtpServer_nativeContext; // MtpStorage fields static jfieldID field_MtpStorage_storageId; @@ -57,173 +52,78 @@ static Mutex sMutex; // in android_mtp_MtpDatabase.cpp extern MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database); -// ---------------------------------------------------------------------------- - -#ifdef HAVE_ANDROID_OS - -static bool ExceptionCheck(void* env) -{ - return ((JNIEnv *)env)->ExceptionCheck(); +static inline MtpServer* getMtpServer(JNIEnv *env, jobject thiz) { + return (MtpServer*)env->GetIntField(thiz, field_MtpServer_nativeContext); } -class MtpThread : public Thread { -private: - MtpDatabase* mDatabase; - bool mPtp; - MtpServer* mServer; - MtpStorageList mStorageList; - int mFd; - -public: - MtpThread(MtpDatabase* database, bool usePtp) - : mDatabase(database), - mPtp(usePtp), - mServer(NULL), - mFd(-1) - { - } - - virtual ~MtpThread() { - } - - void addStorage(MtpStorage *storage) { - mStorageList.push(storage); - if (mServer) - mServer->addStorage(storage); - } - - void removeStorage(MtpStorageID id) { - MtpStorage* storage = mServer->getStorage(id); - if (storage) { - for (size_t i = 0; i < mStorageList.size(); i++) { - if (mStorageList[i] == storage) { - mStorageList.removeAt(i); - break; - } - } - if (mServer) - mServer->removeStorage(storage); - delete storage; - } - } - - void start() { - run("MtpThread"); - } - - virtual bool threadLoop() { - sMutex.lock(); - - mFd = open("/dev/mtp_usb", O_RDWR); - if (mFd >= 0) { - mServer = new MtpServer(mFd, mDatabase, mPtp, AID_MEDIA_RW, 0664, 0775); - for (size_t i = 0; i < mStorageList.size(); i++) { - mServer->addStorage(mStorageList[i]); - } - } else { - LOGE("could not open MTP driver, errno: %d", errno); - } - - sMutex.unlock(); - mServer->run(); - sMutex.lock(); - - close(mFd); - mFd = -1; - delete mServer; - mServer = NULL; - - sMutex.unlock(); - // delay a bit before retrying to avoid excessive spin - if (!exitPending()) { - sleep(1); - } - - return true; - } - - void sendObjectAdded(MtpObjectHandle handle) { - if (mServer) - mServer->sendObjectAdded(handle); - } - - void sendObjectRemoved(MtpObjectHandle handle) { - if (mServer) - mServer->sendObjectRemoved(handle); - } -}; - -// This smart pointer is necessary for preventing MtpThread from exiting too early -static sp<MtpThread> sThread; - -#endif // HAVE_ANDROID_OS - static void android_mtp_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, jboolean usePtp) { -#ifdef HAVE_ANDROID_OS - // create the thread and assign it to the smart pointer - sThread = new MtpThread(getMtpDatabase(env, javaDatabase), usePtp); -#endif + int fd = open("/dev/mtp_usb", O_RDWR); + if (fd >= 0) { + MtpServer* server = new MtpServer(fd, getMtpDatabase(env, javaDatabase), + usePtp, AID_MEDIA_RW, 0664, 0775); + env->SetIntField(thiz, field_MtpServer_nativeContext, (int)server); + } else { + LOGE("could not open MTP driver, errno: %d", errno); + } } static void -android_mtp_MtpServer_start(JNIEnv *env, jobject thiz) +android_mtp_MtpServer_run(JNIEnv *env, jobject thiz) { -#ifdef HAVE_ANDROID_OS - sMutex.lock(); - MtpThread *thread = sThread.get(); - if (thread) - thread->start(); - sMutex.unlock(); -#endif // HAVE_ANDROID_OS + MtpServer* server = getMtpServer(env, thiz); + if (server) + server->run(); + else + LOGE("server is null in run"); } static void -android_mtp_MtpServer_stop(JNIEnv *env, jobject thiz) +android_mtp_MtpServer_cleanup(JNIEnv *env, jobject thiz) { -#ifdef HAVE_ANDROID_OS - sMutex.lock(); - MtpThread *thread = sThread.get(); - if (thread) { - thread->requestExitAndWait(); - sThread = NULL; + Mutex::Autolock autoLock(sMutex); + + MtpServer* server = getMtpServer(env, thiz); + if (server) { + delete server; + env->SetIntField(thiz, field_MtpServer_nativeContext, 0); + } else { + LOGE("server is null in cleanup"); } - sMutex.unlock(); -#endif } static void android_mtp_MtpServer_send_object_added(JNIEnv *env, jobject thiz, jint handle) { -#ifdef HAVE_ANDROID_OS - sMutex.lock(); - MtpThread *thread = sThread.get(); - if (thread) - thread->sendObjectAdded(handle); - sMutex.unlock(); -#endif + Mutex::Autolock autoLock(sMutex); + + MtpServer* server = getMtpServer(env, thiz); + if (server) + server->sendObjectAdded(handle); + else + LOGE("server is null in send_object_added"); } static void android_mtp_MtpServer_send_object_removed(JNIEnv *env, jobject thiz, jint handle) { -#ifdef HAVE_ANDROID_OS - sMutex.lock(); - MtpThread *thread = sThread.get(); - if (thread) - thread->sendObjectRemoved(handle); - sMutex.unlock(); -#endif + Mutex::Autolock autoLock(sMutex); + + MtpServer* server = getMtpServer(env, thiz); + if (server) + server->sendObjectRemoved(handle); + else + LOGE("server is null in send_object_removed"); } static void android_mtp_MtpServer_add_storage(JNIEnv *env, jobject thiz, jobject jstorage) { -#ifdef HAVE_ANDROID_OS - sMutex.lock(); - MtpThread *thread = sThread.get(); - if (thread) { + Mutex::Autolock autoLock(sMutex); + + MtpServer* server = getMtpServer(env, thiz); + if (server) { jint storageID = env->GetIntField(jstorage, field_MtpStorage_storageId); jstring path = (jstring)env->GetObjectField(jstorage, field_MtpStorage_path); jstring description = (jstring)env->GetObjectField(jstorage, field_MtpStorage_description); @@ -237,7 +137,7 @@ android_mtp_MtpServer_add_storage(JNIEnv *env, jobject thiz, jobject jstorage) if (descriptionStr != NULL) { MtpStorage* storage = new MtpStorage(storageID, pathStr, descriptionStr, reserveSpace, removable, maxFileSize); - thread->addStorage(storage); + server->addStorage(storage); env->ReleaseStringUTFChars(path, pathStr); env->ReleaseStringUTFChars(description, descriptionStr); } else { @@ -245,24 +145,24 @@ android_mtp_MtpServer_add_storage(JNIEnv *env, jobject thiz, jobject jstorage) } } } else { - LOGE("MtpThread is null in add_storage"); + LOGE("server is null in add_storage"); } - sMutex.unlock(); -#endif } static void android_mtp_MtpServer_remove_storage(JNIEnv *env, jobject thiz, jint storageId) { -#ifdef HAVE_ANDROID_OS - sMutex.lock(); - MtpThread *thread = sThread.get(); - if (thread) - thread->removeStorage(storageId); - else - LOGE("MtpThread is null in remove_storage"); - sMutex.unlock(); -#endif + Mutex::Autolock autoLock(sMutex); + + MtpServer* server = getMtpServer(env, thiz); + if (server) { + MtpStorage* storage = server->getStorage(storageId); + if (storage) { + server->removeStorage(storage); + delete storage; + } + } else + LOGE("server is null in remove_storage"); } // ---------------------------------------------------------------------------- @@ -270,8 +170,8 @@ android_mtp_MtpServer_remove_storage(JNIEnv *env, jobject thiz, jint storageId) static JNINativeMethod gMethods[] = { {"native_setup", "(Landroid/mtp/MtpDatabase;Z)V", (void *)android_mtp_MtpServer_setup}, - {"native_start", "()V", (void *)android_mtp_MtpServer_start}, - {"native_stop", "()V", (void *)android_mtp_MtpServer_stop}, + {"native_run", "()V", (void *)android_mtp_MtpServer_run}, + {"native_cleanup", "()V", (void *)android_mtp_MtpServer_cleanup}, {"native_send_object_added", "(I)V", (void *)android_mtp_MtpServer_send_object_added}, {"native_send_object_removed", "(I)V", (void *)android_mtp_MtpServer_send_object_removed}, {"native_add_storage", "(Landroid/mtp/MtpStorage;)V", @@ -320,13 +220,17 @@ int register_android_mtp_MtpServer(JNIEnv *env) LOGE("Can't find MtpStorage.mMaxFileSize"); return -1; } - clazz_MtpStorage = (jclass)env->NewGlobalRef(clazz); clazz = env->FindClass("android/mtp/MtpServer"); if (clazz == NULL) { LOGE("Can't find android/mtp/MtpServer"); return -1; } + field_MtpServer_nativeContext = env->GetFieldID(clazz, "mNativeContext", "I"); + if (field_MtpServer_nativeContext == NULL) { + LOGE("Can't find MtpServer.mNativeContext"); + return -1; + } return AndroidRuntime::registerNativeMethods(env, "android/mtp/MtpServer", gMethods, NELEM(gMethods)); diff --git a/media/libmedia/IStreamSource.cpp b/media/libmedia/IStreamSource.cpp index c14ee828c50a..b311f3522518 100644 --- a/media/libmedia/IStreamSource.cpp +++ b/media/libmedia/IStreamSource.cpp @@ -29,6 +29,9 @@ namespace android { // static const char *const IStreamListener::kKeyResumeAtPTS = "resume-at-PTS"; +// static +const char *const IStreamListener::kKeyFormatChange = "format-change"; + enum { // IStreamSource SET_LISTENER = IBinder::FIRST_CALL_TRANSACTION, diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp index bbc8a6edcbb3..a6a3a1888179 100644 --- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp +++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp @@ -63,8 +63,17 @@ bool NuPlayer::StreamingSource::feedMoreTSData() { mEOS = true; break; } else if (n == INFO_DISCONTINUITY) { - mTSParser->signalDiscontinuity( - ATSParser::DISCONTINUITY_SEEK, extra); + ATSParser::DiscontinuityType type = ATSParser::DISCONTINUITY_SEEK; + + int32_t formatChange; + if (extra != NULL + && extra->findInt32( + IStreamListener::kKeyFormatChange, &formatChange) + && formatChange != 0) { + type = ATSParser::DISCONTINUITY_FORMATCHANGE; + } + + mTSParser->signalDiscontinuity(type, extra); } else if (n < 0) { CHECK_EQ(n, -EWOULDBLOCK); break; diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp index c7e7ced50bb9..1bc2fb9eecd7 100644..100755 --- a/media/libstagefright/CameraSource.cpp +++ b/media/libstagefright/CameraSource.cpp @@ -103,6 +103,10 @@ static int32_t getColorFormat(const char* colorFormat) { return OMX_COLOR_Format16bitRGB565; } + if (!strcmp(colorFormat, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar")) { + return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar; + } + LOGE("Uknown color format (%s), please add it to " "CameraSource::getColorFormat", colorFormat); diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp index eaad2c32a876..8c9ff878e040 100644..100755 --- a/media/libstagefright/MPEG4Writer.cpp +++ b/media/libstagefright/MPEG4Writer.cpp @@ -1715,7 +1715,10 @@ status_t MPEG4Writer::Track::parseAVCCodecSpecificData( return ERROR_MALFORMED; } } - +// FIXME: +// Add chromat_format_idc, bit depth values, etc for AVC/h264 high profile and above +// and remove #if 0 +#if 0 { // Check on the profiles // These profiles requires additional parameter set extensions @@ -1725,7 +1728,7 @@ status_t MPEG4Writer::Track::parseAVCCodecSpecificData( return BAD_VALUE; } } - +#endif return OK; } diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 06363eebd557..3b0575248efc 100644..100755 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -218,18 +218,21 @@ static const CodecInfo kEncoderInfo[] = { { MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBEncoder" }, { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.encode" }, { MEDIA_MIMETYPE_AUDIO_AAC, "AACEncoder" }, + { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.DUCATI1.VIDEO.MPEG4E" }, { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.encoder.mpeg4" }, { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.encoder.mpeg4" }, { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.encoder" }, { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.Nvidia.mp4.encoder" }, { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.SEC.MPEG4.Encoder" }, { MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Encoder" }, + { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.DUCATI1.VIDEO.MPEG4E" }, { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.encoder.h263" }, { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.encoder.h263" }, { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.Video.encoder" }, { MEDIA_MIMETYPE_VIDEO_H263, "OMX.Nvidia.h263.encoder" }, { MEDIA_MIMETYPE_VIDEO_H263, "OMX.SEC.H263.Encoder" }, { MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Encoder" }, + { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.DUCATI1.VIDEO.H264E" }, { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.encoder.avc" }, { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.encoder.avc" }, { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.encoder" }, @@ -393,7 +396,17 @@ uint32_t OMXCodec::getComponentQuirks( if (!strcmp(componentName, "OMX.TI.DUCATI1.VIDEO.DECODER")) { quirks |= kRequiresAllocateBufferOnInputPorts; quirks |= kRequiresAllocateBufferOnOutputPorts; - } else if (!strncmp(componentName, "OMX.TI.", 7)) { + } + + // FIXME: + // Remove the quirks after the work is done. + else if (!strcmp(componentName, "OMX.TI.DUCATI1.VIDEO.MPEG4E") || + !strcmp(componentName, "OMX.TI.DUCATI1.VIDEO.H264E")) { + + quirks |= kRequiresAllocateBufferOnInputPorts; + quirks |= kRequiresAllocateBufferOnOutputPorts; + } + else if (!strncmp(componentName, "OMX.TI.", 7)) { // Apparently I must not use OMX_UseBuffer on either input or // output ports on any of the TI components or quote: // "(I) may have unexpected problem (sic) which can be timing related @@ -887,6 +900,7 @@ static size_t getFrameSize( case OMX_COLOR_FormatYUV420Planar: case OMX_COLOR_FormatYUV420SemiPlanar: + case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar: return (width * height * 3) / 2; default: @@ -910,6 +924,7 @@ status_t OMXCodec::findTargetColorFormat( } } + // Check whether the target color format is supported. return isColorFormatSupported(*colorFormat, kPortIndexInput); } @@ -1032,6 +1047,11 @@ void OMXCodec::setVideoInputFormat( video_def->nFrameWidth = width; video_def->nFrameHeight = height; video_def->xFramerate = 0; // No need for output port + // FIXME: + // Revmoe this workaround after work is done. + if (!strncmp(mComponentName, "OMX.TI.DUCATI1", 14)) { + video_def->xFramerate = (frameRate << 16); + } video_def->nBitrate = bitRate; // Q16 format video_def->eCompressionFormat = compressionFormat; video_def->eColorFormat = OMX_COLOR_FormatUnused; @@ -1304,6 +1324,12 @@ status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) { h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profileLevel.mProfile); h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(profileLevel.mLevel); + // FIXME: + // Remove the workaround after the work in done. + if (!strncmp(mComponentName, "OMX.TI.DUCATI1", 14)) { + h264type.eProfile = OMX_VIDEO_AVCProfileBaseline; + } + if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) { h264type.nSliceHeaderSpacing = 0; h264type.bUseHadamard = OMX_TRUE; diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp index 9085f10e8afb..4047e2e8777e 100644 --- a/media/mtp/MtpServer.cpp +++ b/media/mtp/MtpServer.cpp @@ -237,6 +237,8 @@ void MtpServer::run() { if (mSessionOpen) mDatabase->sessionEnded(); + close(fd); + mFD = -1; } void MtpServer::sendObjectAdded(MtpObjectHandle handle) { diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp index da9b55ccd2a3..10b9083549f2 100644 --- a/services/input/InputDispatcher.cpp +++ b/services/input/InputDispatcher.cpp @@ -3154,9 +3154,11 @@ void InputDispatcher::setInputWindows(const Vector<InputWindow>& inputWindows) { mLastHoverWindow = NULL; } + mWindows.clear(); + // Loop over new windows and rebuild the necessary window pointers for // tracking focus and touch. - mWindows = inputWindows; + mWindows.appendVector(inputWindows); size_t numWindows = mWindows.size(); for (size_t i = 0; i < numWindows; i++) { @@ -4558,7 +4560,8 @@ void InputDispatcher::TouchState::copyFrom(const TouchState& other) { split = other.split; deviceId = other.deviceId; source = other.source; - windows = other.windows; + windows.clear(); + windows.appendVector(other.windows); } void InputDispatcher::TouchState::addOrUpdateWindow(const InputWindow* window, diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index 872438c5e504..54e94db07389 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -313,21 +313,24 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); synchronized (mStatsLock) { + // use system clock to be externally consistent + final long now = System.currentTimeMillis(); + final NetworkStats stats = new NetworkStats(end - start, 1); final NetworkStats.Entry entry = new NetworkStats.Entry(); - long[] total = new long[2]; + NetworkStatsHistory.Entry historyEntry = null; // combine total from all interfaces that match template for (NetworkIdentitySet ident : mNetworkStats.keySet()) { if (templateMatches(template, ident)) { final NetworkStatsHistory history = mNetworkStats.get(ident); - total = history.getTotalData(start, end, total); + historyEntry = history.getValues(start, end, now, historyEntry); entry.iface = IFACE_ALL; entry.uid = UID_ALL; entry.tag = TAG_NONE; - entry.rxBytes = total[0]; - entry.txBytes = total[1]; + entry.rxBytes = historyEntry.rxBytes; + entry.txBytes = historyEntry.txBytes; stats.combineValues(entry); } @@ -345,9 +348,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { synchronized (mStatsLock) { ensureUidStatsLoadedLocked(); + // use system clock to be externally consistent + final long now = System.currentTimeMillis(); + final NetworkStats stats = new NetworkStats(end - start, 24); final NetworkStats.Entry entry = new NetworkStats.Entry(); - long[] total = new long[2]; + NetworkStatsHistory.Entry historyEntry = null; for (NetworkIdentitySet ident : mUidStats.keySet()) { if (templateMatches(template, ident)) { @@ -361,13 +367,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // other tags when requested. if (tag == TAG_NONE || includeTags) { final NetworkStatsHistory history = uidStats.valueAt(i); - total = history.getTotalData(start, end, total); + historyEntry = history.getValues(start, end, now, historyEntry); entry.iface = IFACE_ALL; entry.uid = uid; entry.tag = tag; - entry.rxBytes = total[0]; - entry.txBytes = total[1]; + entry.rxBytes = historyEntry.rxBytes; + entry.txBytes = historyEntry.txBytes; if (entry.rxBytes > 0 || entry.txBytes > 0) { stats.combineValues(entry); @@ -425,6 +431,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // broadcast. final int uid = intent.getIntExtra(EXTRA_UID, 0); synchronized (mStatsLock) { + // TODO: perform one last stats poll for UID removeUidLocked(uid); } } diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java index 86b3d364ab02..313979808ced 100644 --- a/services/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/java/com/android/server/usb/UsbDeviceManager.java @@ -138,12 +138,9 @@ public class UsbDeviceManager { // create a thread for our Handler HandlerThread thread = new HandlerThread("UsbDeviceManager", - Process.THREAD_PRIORITY_BACKGROUND) { - protected void onLooperPrepared() { - mHandler = new UsbHandler(); - } - }; + Process.THREAD_PRIORITY_BACKGROUND); thread.start(); + mHandler = new UsbHandler(thread.getLooper()); } public void systemReady() { @@ -249,7 +246,8 @@ public class UsbDeviceManager { private static final int NOTIFICATION_INSTALLER = 3; private static final int NOTIFICATION_ADB = 4; - public UsbHandler() { + public UsbHandler(Looper looper) { + super(looper); try { // persist.sys.usb.config should never be unset. But if it is, set it to "adb" // so we have a chance of debugging what happened. diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 35e29a6315a8..f3b6c4dd23b3 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -188,22 +188,37 @@ void Layer::setGeometry(hwc_layer_t* hwcl) return; } + /* + * Transformations are applied in this order: + * 1) buffer orientation/flip/mirror + * 2) state transformation (window manager) + * 3) layer orientation (screen orientation) + * (NOTE: the matrices are multiplied in reverse order) + */ + + const Transform bufferOrientation(mCurrentTransform); + const Transform& stateTransform(s.transform); + const Transform layerOrientation(mOrientation); + + const Transform tr(layerOrientation * stateTransform * bufferOrientation); + + // this gives us only the "orientation" component of the transform + const uint32_t finalTransform = tr.getOrientation(); + // we can only handle simple transformation - if (mOrientation & Transform::ROT_INVALID) { + if (finalTransform & Transform::ROT_INVALID) { hwcl->flags = HWC_SKIP_LAYER; return; } - // FIXME: shouldn't we take the state's transform into account here? - - Transform tr(Transform(mOrientation) * Transform(mCurrentTransform)); - hwcl->transform = tr.getOrientation(); + hwcl->transform = finalTransform; if (!isOpaque()) { hwcl->blending = mPremultipliedAlpha ? HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE; } + // scaling is already applied in mTransformedBounds hwcl->displayFrame.left = mTransformedBounds.left; hwcl->displayFrame.top = mTransformedBounds.top; hwcl->displayFrame.right = mTransformedBounds.right; diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp index 0467a14604c9..4cedcbf86cc6 100644 --- a/services/surfaceflinger/Transform.cpp +++ b/services/surfaceflinger/Transform.cpp @@ -308,6 +308,7 @@ uint32_t Transform::type() const scale = true; } } else { + // there is a skew component and/or a non 90 degrees rotation flags = ROT_INVALID; } diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java index 36b3b82a4111..ac740636138e 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java @@ -264,7 +264,6 @@ public class NetworkStatsServiceTest extends AndroidTestCase { public void testStatsBucketResize() throws Exception { long elapsedRealtime = 0; NetworkStatsHistory history = null; - long[] total = null; assertStatsFilesExist(false); @@ -292,9 +291,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { // verify service recorded history history = mService.getHistoryForNetwork(new NetworkTemplate(MATCH_WIFI, null)); - total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null); - assertEquals(512L, total[0]); - assertEquals(512L, total[1]); + assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 512L); assertEquals(HOUR_IN_MILLIS, history.getBucketDuration()); assertEquals(2, history.size()); verifyAndReset(); @@ -311,9 +308,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { // verify identical stats, but spread across 4 buckets now history = mService.getHistoryForNetwork(new NetworkTemplate(MATCH_WIFI, null)); - total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null); - assertEquals(512L, total[0]); - assertEquals(512L, total[1]); + assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 512L); assertEquals(30 * MINUTE_IN_MILLIS, history.getBucketDuration()); assertEquals(4, history.size()); verifyAndReset(); @@ -575,32 +570,28 @@ public class NetworkStatsServiceTest extends AndroidTestCase { NetworkStats stats = mService.getSummaryForAllUid( sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true); assertEquals(3, stats.size()); - assertEntry(stats, 0, IFACE_ALL, UID_RED, TAG_NONE, 50L, 5L, 50L, 5L); - assertEntry(stats, 1, IFACE_ALL, UID_RED, 0xF00D, 10L, 1L, 10L, 1L); - assertEntry(stats, 2, IFACE_ALL, UID_BLUE, TAG_NONE, 2048L, 16L, 1024L, 8L); + assertValues(stats, 0, IFACE_ALL, UID_RED, TAG_NONE, 50L, 5L, 50L, 5L); + assertValues(stats, 1, IFACE_ALL, UID_RED, 0xF00D, 10L, 1L, 10L, 1L); + assertValues(stats, 2, IFACE_ALL, UID_BLUE, TAG_NONE, 2048L, 16L, 1024L, 8L); // now verify that recent history only contains one uid final long currentTime = TEST_START + elapsedRealtime; stats = mService.getSummaryForAllUid( sTemplateWifi, currentTime - HOUR_IN_MILLIS, currentTime, true); assertEquals(1, stats.size()); - assertEntry(stats, 0, IFACE_ALL, UID_BLUE, TAG_NONE, 1024L, 8L, 512L, 4L); + assertValues(stats, 0, IFACE_ALL, UID_BLUE, TAG_NONE, 1024L, 8L, 512L, 4L); verifyAndReset(); } - private void assertNetworkTotal(NetworkTemplate template, long rx, long tx) { + private void assertNetworkTotal(NetworkTemplate template, long rxBytes, long txBytes) { final NetworkStatsHistory history = mService.getHistoryForNetwork(template); - final long[] total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null); - assertEquals(rx, total[0]); - assertEquals(tx, total[1]); + assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, txBytes); } - private void assertUidTotal(NetworkTemplate template, int uid, long rx, long tx) { + private void assertUidTotal(NetworkTemplate template, int uid, long rxBytes, long txBytes) { final NetworkStatsHistory history = mService.getHistoryForUid(template, uid, TAG_NONE); - final long[] total = history.getTotalData(Long.MIN_VALUE, Long.MAX_VALUE, null); - assertEquals(rx, total[0]); - assertEquals(tx, total[1]); + assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, txBytes); } private void expectSystemReady() throws Exception { @@ -660,7 +651,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { } } - private static void assertEntry(NetworkStats stats, int i, String iface, int uid, int tag, + private static void assertValues(NetworkStats stats, int i, String iface, int uid, int tag, long rxBytes, long rxPackets, long txBytes, long txPackets) { final NetworkStats.Entry entry = stats.getValues(i, null); assertEquals(iface, entry.iface); @@ -673,6 +664,13 @@ public class NetworkStatsServiceTest extends AndroidTestCase { // assertEquals(txPackets, entry.txPackets); } + private static void assertValues( + NetworkStatsHistory stats, long start, long end, long rxBytes, long txBytes) { + final NetworkStatsHistory.Entry entry = stats.getValues(start, end, null); + assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); + assertEquals("unexpected txBytes", txBytes, entry.txBytes); + } + private static NetworkState buildWifiState() { final NetworkInfo info = new NetworkInfo(TYPE_WIFI, 0, null, null); info.setDetailedState(DetailedState.CONNECTED, null, null); diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java index 430930965c9a..60cf9b7f362b 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java +++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java @@ -166,4 +166,11 @@ public interface TelephonyProperties * the value of config_sms_capable */ static final String PROPERTY_SMS_SEND = "telephony.sms.send"; + + /** + * Set to true to indicate a test CSIM card is used in the device. + * This property is for testing purpose only. This should not be defined + * in commercial configuration. + */ + static final String PROPERTY_TEST_CSIM = "persist.radio.test-csim"; } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java index 10515f71cfc5..fc6abad48c10 100755 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java @@ -16,6 +16,7 @@ package com.android.internal.telephony.cdma; import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA; +import static com.android.internal.telephony.TelephonyProperties.PROPERTY_TEST_CSIM; import com.android.internal.telephony.GsmAlphabet; import com.android.internal.telephony.IccCardApplication.AppType; import com.android.internal.telephony.IccFileHandler; @@ -447,6 +448,12 @@ public final class CdmaLteUiccRecords extends SIMRecords { // to determine if the SIM is provisioned. Otherwise, // consider the SIM is provisioned. (for case of ordinal // USIM only UICC.) + // If PROPERTY_TEST_CSIM is defined, bypess provision check + // and consider the SIM is provisioned. + if (SystemProperties.getBoolean(PROPERTY_TEST_CSIM, false)) { + return true; + } + if (phone.mIccCard.isApplicationOnIcc(AppType.APPTYPE_CSIM) && ((mMdn == null) || (mMin == null))) { return false; diff --git a/tests/BiDiTests/res/layout/textview_drawables_ltr.xml b/tests/BiDiTests/res/layout/textview_drawables_ltr.xml new file mode 100644 index 000000000000..88b13b7c565a --- /dev/null +++ b/tests/BiDiTests/res/layout/textview_drawables_ltr.xml @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/textview_drawables_ltr" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:layoutDirection="ltr"> + + <LinearLayout android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <TextView android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:textSize="24dip" + android:text="@string/textview_text" + android:drawableLeft="@drawable/start" + android:drawableRight="@drawable/end" + android:drawablePadding="3dip" + /> + + <TextView android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:textSize="24dip" + android:text="@string/textview_text" + android:drawableStart="@drawable/start" + android:drawableEnd="@drawable/end" + android:drawablePadding="3dip" + /> + + <TextView android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:textSize="24dip" + android:text="@string/textview_text" + android:drawableLeft="@drawable/end" + android:drawableStart="@drawable/start" + android:drawableEnd="@drawable/end" + android:drawablePadding="3dip" + /> + + <TextView android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:textSize="24dip" + android:text="@string/textview_text" + android:drawableRight="@drawable/start" + android:drawableStart="@drawable/start" + android:drawableEnd="@drawable/end" + android:drawablePadding="3dip" + /> + + <TextView android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:textSize="24dip" + android:text="@string/textview_text" + android:drawableLeft="@drawable/end" + android:drawableRight="@drawable/start" + android:drawableStart="@drawable/start" + android:drawableEnd="@drawable/end" + android:drawablePadding="3dip" + /> + + <TextView android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:textSize="24dip" + android:text="@string/textview_text" + android:drawableRight="@drawable/end" + android:drawableStart="@drawable/start" + android:drawablePadding="3dip" + /> + + <TextView android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:textSize="24dip" + android:text="@string/textview_text" + android:drawableLeft="@drawable/start" + android:drawableEnd="@drawable/end" + android:drawablePadding="3dip" + /> + + <TextView android:id="@+id/textview_error" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:textSize="24dip" + android:text="@string/textview_text" + android:drawablePadding="3dip" + /> + + </LinearLayout> + +</FrameLayout> diff --git a/tests/BiDiTests/res/layout/textview_drawables_rtl.xml b/tests/BiDiTests/res/layout/textview_drawables_rtl.xml new file mode 100644 index 000000000000..7f47d5de6460 --- /dev/null +++ b/tests/BiDiTests/res/layout/textview_drawables_rtl.xml @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/textview_drawables_rtl" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:layoutDirection="rtl"> + + <LinearLayout android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <TextView android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:textSize="24dip" + android:text="@string/textview_text" + android:drawableLeft="@drawable/end" + android:drawableRight="@drawable/start" + android:drawablePadding="3dip" + /> + + <TextView android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:textSize="24dip" + android:text="@string/textview_text" + android:drawableStart="@drawable/start" + android:drawableEnd="@drawable/end" + android:drawablePadding="3dip" + /> + + <TextView android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:textSize="24dip" + android:text="@string/textview_text" + android:drawableLeft="@drawable/start" + android:drawableStart="@drawable/start" + android:drawableEnd="@drawable/end" + android:drawablePadding="3dip" + /> + + <TextView android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:textSize="24dip" + android:text="@string/textview_text" + android:drawableRight="@drawable/end" + android:drawableStart="@drawable/start" + android:drawableEnd="@drawable/end" + android:drawablePadding="3dip" + /> + + <TextView android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:textSize="24dip" + android:text="@string/textview_text" + android:drawableLeft="@drawable/start" + android:drawableRight="@drawable/end" + android:drawableStart="@drawable/start" + android:drawableEnd="@drawable/end" + android:drawablePadding="3dip" + /> + + <TextView android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:textSize="24dip" + android:text="@string/textview_text" + android:drawableLeft="@drawable/end" + android:drawableStart="@drawable/start" + android:drawablePadding="3dip" + /> + + <TextView android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:textSize="24dip" + android:text="@string/textview_text" + android:drawableRight="@drawable/start" + android:drawableEnd="@drawable/end" + android:drawablePadding="3dip" + /> + + <TextView android:id="@+id/textview_error" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:textSize="24dip" + android:text="@string/textview_text" + android:drawablePadding="3dip" + /> + + </LinearLayout> + +</FrameLayout> diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java index c0338796400e..7002c4148786 100644 --- a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java +++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java @@ -134,6 +134,9 @@ public class BiDiTestActivity extends Activity { addItem(result, "TextDirection LTR", BiDiTestTextViewDirectionLtr.class, R.id.textview_direction_ltr); addItem(result, "TextDirection RTL", BiDiTestTextViewDirectionRtl.class, R.id.textview_direction_rtl); + addItem(result, "TextView Drawables LTR", BiDiTestTextViewDrawablesLtr.class, R.id.textview_drawables_ltr); + addItem(result, "TextView Drawables RTL", BiDiTestTextViewDrawablesRtl.class, R.id.textview_drawables_rtl); + return result; } diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDrawablesLtr.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDrawablesLtr.java new file mode 100644 index 000000000000..a65d92dbd4ee --- /dev/null +++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDrawablesLtr.java @@ -0,0 +1,45 @@ +/* + * 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 com.android.bidi; + +import android.app.Fragment; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +public class BiDiTestTextViewDrawablesLtr extends Fragment { + + private View currentView; + private TextView textViewError; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + currentView = inflater.inflate(R.layout.textview_drawables_ltr, container, false); + return currentView; + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + textViewError = (TextView) currentView.findViewById(R.id.textview_error); + textViewError.setError("Error!!"); + } +} diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDrawablesRtl.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDrawablesRtl.java new file mode 100644 index 000000000000..7b7e8124b146 --- /dev/null +++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewDrawablesRtl.java @@ -0,0 +1,45 @@ +/* + * 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 com.android.bidi; + +import android.app.Fragment; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +public class BiDiTestTextViewDrawablesRtl extends Fragment { + + private View currentView; + private TextView textViewError; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + currentView = inflater.inflate(R.layout.textview_drawables_rtl, container, false); + return currentView; + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + textViewError = (TextView) currentView.findViewById(R.id.textview_error); + textViewError.setError("Error!!"); + } +} |