Merge changes I22d9e018,Ib0701fcc,Ibc637918,I9eb7e002,I4adcec73
* changes:
audioflinger: don't do work in constructor, instead do it in onFirstRef
audioflinger: enumerate all the possible audio interfaces
audio/media: convert to using the audio HAL and new audio defs
libmedia: move AudioParameter out of AudioSystem
audioflinger: move legacy audio hw/policy out to libhardware_legacy
diff --git a/api/current.txt b/api/current.txt
index ebf3893..c76627f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -17115,14 +17115,32 @@
package android.speech.tts {
+ public abstract class SynthesisRequest {
+ ctor public SynthesisRequest(java.lang.String);
+ method public abstract int audioAvailable(byte[], int, int);
+ method public abstract int completeAudioAvailable(int, int, int, byte[], int, int);
+ method public abstract int done();
+ method public abstract void error();
+ method public java.lang.String getCountry();
+ method public java.lang.String getLanguage();
+ method public abstract int getMaxBufferSize();
+ method public int getPitch();
+ method public int getSpeechRate();
+ method public java.lang.String getText();
+ method public java.lang.String getVariant();
+ method public abstract int start(int, int, int);
+ }
+
public class TextToSpeech {
ctor public TextToSpeech(android.content.Context, android.speech.tts.TextToSpeech.OnInitListener);
+ ctor public TextToSpeech(android.content.Context, android.speech.tts.TextToSpeech.OnInitListener, java.lang.String);
method public int addEarcon(java.lang.String, java.lang.String, int);
method public int addEarcon(java.lang.String, java.lang.String);
method public int addSpeech(java.lang.String, java.lang.String, int);
method public int addSpeech(java.lang.String, java.lang.String);
method public boolean areDefaultsEnforced();
method public java.lang.String getDefaultEngine();
+ method public java.util.List<android.speech.tts.TextToSpeech.EngineInfo> getEngines();
method public java.util.Locale getLanguage();
method public int isLanguageAvailable(java.util.Locale);
method public boolean isSpeaking();
@@ -17167,12 +17185,20 @@
field public static final java.lang.String EXTRA_VOICE_DATA_FILES = "dataFiles";
field public static final java.lang.String EXTRA_VOICE_DATA_FILES_INFO = "dataFilesInfo";
field public static final java.lang.String EXTRA_VOICE_DATA_ROOT_DIRECTORY = "dataRoot";
+ field public static final java.lang.String INTENT_ACTION_TTS_SERVICE = "android.intent.action.TTS_SERVICE";
field public static final java.lang.String KEY_PARAM_PAN = "pan";
field public static final java.lang.String KEY_PARAM_STREAM = "streamType";
field public static final java.lang.String KEY_PARAM_UTTERANCE_ID = "utteranceId";
field public static final java.lang.String KEY_PARAM_VOLUME = "volume";
}
+ public static class TextToSpeech.EngineInfo {
+ ctor public TextToSpeech.EngineInfo();
+ field public int icon;
+ field public java.lang.String label;
+ field public java.lang.String name;
+ }
+
public static abstract interface TextToSpeech.OnInitListener {
method public abstract void onInit(int);
}
@@ -17181,6 +17207,16 @@
method public abstract void onUtteranceCompleted(java.lang.String);
}
+ public abstract class TextToSpeechService extends android.app.Service {
+ ctor public TextToSpeechService();
+ method public android.os.IBinder onBind(android.content.Intent);
+ method protected abstract java.lang.String[] onGetLanguage();
+ method protected abstract int onIsLanguageAvailable(java.lang.String, java.lang.String, java.lang.String);
+ method protected abstract int onLoadLanguage(java.lang.String, java.lang.String, java.lang.String);
+ method protected abstract void onStop();
+ method protected abstract void onSynthesizeText(android.speech.tts.SynthesisRequest);
+ }
+
}
package android.telephony {
diff --git a/core/java/android/speech/tts/SynthesisRequest.java b/core/java/android/speech/tts/SynthesisRequest.java
index 515218b..6df9af2 100644
--- a/core/java/android/speech/tts/SynthesisRequest.java
+++ b/core/java/android/speech/tts/SynthesisRequest.java
@@ -24,8 +24,6 @@
*
* Alternatively, the engine can provide all the audio at once, by using
* {@link #completeAudioAvailable}.
- *
- * @hide Pending approval
*/
public abstract class SynthesisRequest {
@@ -92,16 +90,14 @@
}
/**
- * Gets the speech rate to use. {@link TextToSpeech.Engine#DEFAULT_RATE} (100)
- * is the normal rate.
+ * Gets the speech rate to use. The normal rate is 100.
*/
public int getSpeechRate() {
return mSpeechRate;
}
/**
- * Gets the pitch to use. {@link TextToSpeech.Engine#DEFAULT_PITCH} (100)
- * is the normal pitch.
+ * Gets the pitch to use. The normal pitch is 100.
*/
public int getPitch() {
return mPitch;
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index e247df8..1d26c22 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -220,8 +220,6 @@
* extend {@link TextToSpeechService}. Normal applications should not use this intent
* directly, instead they should talk to the TTS service using the the methods in this
* class.
- *
- * @hide Pending API council approval
*/
@SdkConstant(SdkConstantType.SERVICE_ACTION)
public static final String INTENT_ACTION_TTS_SERVICE =
@@ -428,7 +426,7 @@
private final Bundle mParams = new Bundle();
/**
- * The constructor for the TextToSpeech class.
+ * The constructor for the TextToSpeech class, using the default TTS engine.
* This will also initialize the associated TextToSpeech engine if it isn't already running.
*
* @param context
@@ -442,7 +440,15 @@
}
/**
- * @hide pending approval
+ * The constructor for the TextToSpeech class, using the given TTS engine.
+ * This will also initialize the associated TextToSpeech engine if it isn't already running.
+ *
+ * @param context
+ * The context this instance is running in.
+ * @param listener
+ * The {@link TextToSpeech.OnInitListener} that will be called when the
+ * TextToSpeech engine has initialized.
+ * @param engine Package name of the TTS engine to use.
*/
public TextToSpeech(Context context, OnInitListener listener, String engine) {
mContext = context;
@@ -1060,8 +1066,6 @@
* Gets a list of all installed TTS engines.
*
* @return A list of engine info objects. The list can be empty, but will never by {@code null}.
- *
- * @hide Pending approval
*/
public List<EngineInfo> getEngines() {
PackageManager pm = mContext.getPackageManager();
@@ -1144,7 +1148,6 @@
* Information about an installed text-to-speech engine.
*
* @see TextToSpeech#getEngines
- * @hide Pending approval
*/
public static class EngineInfo {
/**
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index da97fb4..590e2ef 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -41,8 +41,6 @@
/**
* Abstract base class for TTS engine implementations.
- *
- * @hide Pending approval
*/
public abstract class TextToSpeechService extends Service {
diff --git a/core/java/android/text/style/TextAppearanceSpan.java b/core/java/android/text/style/TextAppearanceSpan.java
index de929e3..deed713 100644
--- a/core/java/android/text/style/TextAppearanceSpan.java
+++ b/core/java/android/text/style/TextAppearanceSpan.java
@@ -51,10 +51,9 @@
* to determine the color. The <code>appearance</code> should be,
* for example, <code>android.R.style.TextAppearance_Small</code>,
* and the <code>colorList</code> should be, for example,
- * <code>android.R.styleable.Theme_textColorDim</code>.
+ * <code>android.R.styleable.Theme_textColorPrimary</code>.
*/
- public TextAppearanceSpan(Context context, int appearance,
- int colorList) {
+ public TextAppearanceSpan(Context context, int appearance, int colorList) {
ColorStateList textColor;
TypedArray a =
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 7b404b4..1a84175 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2203,10 +2203,10 @@
}
/**
- * Perform dispatching of a {@link #saveHierarchyState freeze()} to only this view,
- * not to its children. For use when overriding
- * {@link #dispatchSaveInstanceState dispatchFreeze()} to allow subclasses to freeze
- * their own state but not the state of their children.
+ * Perform dispatching of a {@link #saveHierarchyState(android.util.SparseArray)} freeze()}
+ * to only this view, not to its children. For use when overriding
+ * {@link #dispatchSaveInstanceState(android.util.SparseArray)} dispatchFreeze()} to allow
+ * subclasses to freeze their own state but not the state of their children.
*
* @param container the container
*/
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index f02daba..20503b7 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1926,6 +1926,7 @@
void dispatchDetachedFromWindow() {
if (mView != null && mView.mAttachInfo != null) {
mView.dispatchDetachedFromWindow();
+ mAttached = false;
}
mView = null;
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index 25f2229..807f6ce 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -60,8 +60,7 @@
mSubtypeLocale = locale != null ? locale : "";
mSubtypeMode = mode != null ? mode : "";
mSubtypeExtraValue = extraValue != null ? extraValue : "";
- mSubtypeHashCode = hashCodeInternal(mSubtypeNameResId, mSubtypeIconResId, mSubtypeLocale,
- mSubtypeMode, mSubtypeExtraValue);
+ mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue);
}
InputMethodSubtype(Parcel source) {
@@ -74,8 +73,7 @@
mSubtypeMode = s != null ? s : "";
s = source.readString();
mSubtypeExtraValue = s != null ? s : "";
- mSubtypeHashCode = hashCodeInternal(mSubtypeNameResId, mSubtypeIconResId, mSubtypeLocale,
- mSubtypeMode, mSubtypeExtraValue);
+ mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue);
}
/**
@@ -195,9 +193,8 @@
}
};
- private static int hashCodeInternal(int nameResId, int iconResId, String locale,
- String mode, String extraValue) {
- return Arrays.hashCode(new Object[] {nameResId, iconResId, locale, mode, extraValue});
+ private static int hashCodeInternal(String locale, String mode, String extraValue) {
+ return Arrays.hashCode(new Object[] {locale, mode, extraValue});
}
/**
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 71d6080..3e11197 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -219,6 +219,7 @@
private boolean mAllowContentAccess = true;
private boolean mLoadWithOverviewMode = false;
private boolean mEnableSmoothTransition = false;
+ private boolean mForceUserScalable = false;
// AutoFill Profile data
/**
@@ -1658,6 +1659,23 @@
}
}
+ /**
+ * Returns whether the viewport metatag can disable zooming
+ * @hide
+ */
+ public boolean forceUserScalable() {
+ return mForceUserScalable;
+ }
+
+ /**
+ * Sets whether viewport metatag can disable zooming.
+ * @param flag Whether or not to forceably enable user scalable.
+ * @hide
+ */
+ public synchronized void setForceUserScalable(boolean flag) {
+ mForceUserScalable = flag;
+ }
+
synchronized void setSyntheticLinksEnabled(boolean flag) {
if (mSyntheticLinksEnabled != flag) {
mSyntheticLinksEnabled = flag;
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 0271695..09205a5 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -2253,6 +2253,27 @@
// set the viewport settings from WebKit
setViewportSettingsFromNative();
+ if (mSettings.forceUserScalable()) {
+ mViewportUserScalable = true;
+ if (mViewportInitialScale > 0) {
+ if (mViewportMinimumScale > 0) {
+ mViewportMinimumScale = Math.min(mViewportMinimumScale,
+ mViewportInitialScale / 2);
+ }
+ if (mViewportMaximumScale > 0) {
+ mViewportMaximumScale = Math.max(mViewportMaximumScale,
+ mViewportInitialScale * 2);
+ }
+ } else {
+ if (mViewportMinimumScale > 0) {
+ mViewportMinimumScale = Math.min(mViewportMinimumScale, 50);
+ }
+ if (mViewportMaximumScale > 0) {
+ mViewportMaximumScale = Math.max(mViewportMaximumScale, 200);
+ }
+ }
+ }
+
// adjust the default scale to match the densityDpi
float adjust = 1.0f;
if (mViewportDensityDpi == -1) {
@@ -2589,11 +2610,11 @@
// called by JNI
private Class<?> getPluginClass(String libName, String clsName) {
-
+
if (mWebView == null) {
return null;
}
-
+
PluginManager pluginManager = PluginManager.getInstance(null);
String pkgName = pluginManager.getPluginsAPKName(libName);
@@ -2601,7 +2622,7 @@
Log.w(LOGTAG, "Unable to resolve " + libName + " to a plugin APK");
return null;
}
-
+
try {
return pluginManager.getPluginClass(pkgName, clsName);
} catch (NameNotFoundException e) {
@@ -2656,7 +2677,7 @@
view.mView = pluginView;
return view;
}
-
+
// called by JNI. PluginWidget functions for creating an embedded View for
// the surface drawing model.
private ViewManager.ChildView addSurface(View pluginView, int x, int y,
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 1fe6f4b..d8068f9 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -218,15 +218,16 @@
/**
* An optional argument to supply a maximum width for this view. Only valid if
- * {@link #setAdjustViewBounds} has been set to true. To set an image to be a maximum of 100 x
- * 100 while preserving the original aspect ratio, do the following: 1) set adjustViewBounds to
- * true 2) set maxWidth and maxHeight to 100 3) set the height and width layout params to
- * WRAP_CONTENT.
+ * {@link #setAdjustViewBounds(boolean)} has been set to true. To set an image to be a maximum
+ * of 100 x 100 while preserving the original aspect ratio, do the following: 1) set
+ * adjustViewBounds to true 2) set maxWidth and maxHeight to 100 3) set the height and width
+ * layout params to WRAP_CONTENT.
*
* <p>
* Note that this view could be still smaller than 100 x 100 using this approach if the original
* image is small. To set an image to a fixed size, specify that size in the layout params and
- * then use {@link #setScaleType} to determine how to fit the image within the bounds.
+ * then use {@link #setScaleType(android.widget.ImageView.ScaleType)} to determine how to fit
+ * the image within the bounds.
* </p>
*
* @param maxWidth maximum width for this view
@@ -240,15 +241,16 @@
/**
* An optional argument to supply a maximum height for this view. Only valid if
- * {@link #setAdjustViewBounds} has been set to true. To set an image to be a maximum of 100 x
- * 100 while preserving the original aspect ratio, do the following: 1) set adjustViewBounds to
- * true 2) set maxWidth and maxHeight to 100 3) set the height and width layout params to
- * WRAP_CONTENT.
+ * {@link #setAdjustViewBounds(boolean)} has been set to true. To set an image to be a
+ * maximum of 100 x 100 while preserving the original aspect ratio, do the following: 1) set
+ * adjustViewBounds to true 2) set maxWidth and maxHeight to 100 3) set the height and width
+ * layout params to WRAP_CONTENT.
*
* <p>
* Note that this view could be still smaller than 100 x 100 using this approach if the original
* image is small. To set an image to a fixed size, specify that size in the layout params and
- * then use {@link #setScaleType} to determine how to fit the image within the bounds.
+ * then use {@link #setScaleType(android.widget.ImageView.ScaleType)} to determine how to fit
+ * the image within the bounds.
* </p>
*
* @param maxHeight maximum height for this view
@@ -272,8 +274,8 @@
*
* <p class="note">This does Bitmap reading and decoding on the UI
* thread, which can cause a latency hiccup. If that's a concern,
- * consider using {@link #setImageDrawable} or
- * {@link #setImageBitmap} and
+ * consider using {@link #setImageDrawable(android.graphics.drawable.Drawable)} or
+ * {@link #setImageBitmap(android.graphics.Bitmap)} and
* {@link android.graphics.BitmapFactory} instead.</p>
*
* @param resId the resource identifier of the the drawable
@@ -297,8 +299,8 @@
*
* <p class="note">This does Bitmap reading and decoding on the UI
* thread, which can cause a latency hiccup. If that's a concern,
- * consider using {@link #setImageDrawable} or
- * {@link #setImageBitmap} and
+ * consider using {@link #setImageDrawable(android.graphics.drawable.Drawable)} or
+ * {@link #setImageBitmap(android.graphics.Bitmap)} and
* {@link android.graphics.BitmapFactory} instead.</p>
*
* @param uri The Uri of an image
@@ -902,12 +904,12 @@
/**
* <p>Set the offset of the widget's text baseline from the widget's top
- * boundary. This value is overridden by the {@link #setBaselineAlignBottom}
+ * boundary. This value is overridden by the {@link #setBaselineAlignBottom(boolean)}
* property.</p>
*
* @param baseline The baseline to use, or -1 if none is to be provided.
*
- * @see #setBaseline
+ * @see #setBaseline(int)
* @attr ref android.R.styleable#ImageView_baseline
*/
public void setBaseline(int baseline) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 4d3aa68..6c5d117 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -60,6 +60,7 @@
import android.text.SpanWatcher;
import android.text.Spannable;
import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.SpannedString;
import android.text.StaticLayout;
@@ -80,10 +81,13 @@
import android.text.method.TextKeyListener;
import android.text.method.TimeKeyListener;
import android.text.method.TransformationMethod;
+import android.text.method.WordIterator;
import android.text.style.ClickableSpan;
import android.text.style.ParagraphStyle;
import android.text.style.SuggestionSpan;
+import android.text.style.TextAppearanceSpan;
import android.text.style.URLSpan;
+import android.text.style.UnderlineSpan;
import android.text.style.UpdateAppearance;
import android.text.util.Linkify;
import android.util.AttributeSet;
@@ -127,6 +131,7 @@
import java.io.IOException;
import java.lang.ref.WeakReference;
+import java.text.BreakIterator;
import java.util.ArrayList;
/**
@@ -314,6 +319,7 @@
private int mTextEditSuggestionsBottomWindowLayout, mTextEditSuggestionsTopWindowLayout;
private int mTextEditSuggestionItemLayout;
private SuggestionsPopupWindow mSuggestionsPopupWindow;
+ private SuggestionRangeSpan mSuggestionRangeSpan;
private int mCursorDrawableRes;
private final Drawable[] mCursorDrawable = new Drawable[2];
@@ -8225,13 +8231,20 @@
return ((minOffset >= selectionStart) && (maxOffset < selectionEnd));
}
+ private static class SuggestionRangeSpan extends UnderlineSpan {
+ // TODO themable, would be nice to make it a child class of TextAppearanceSpan, but
+ // there is no way to have underline and TextAppearanceSpan.
+ }
+
private class SuggestionsPopupWindow implements OnClickListener {
private static final int MAX_NUMBER_SUGGESTIONS = 5;
- private static final long NO_SUGGESTIONS = -1L;
+ private static final int NO_SUGGESTIONS = -1;
private final PopupWindow mContainer;
private final ViewGroup[] mSuggestionViews = new ViewGroup[2];
private final int[] mSuggestionViewLayouts = new int[] {
mTextEditSuggestionsBottomWindowLayout, mTextEditSuggestionsTopWindowLayout};
+ private WordIterator mWordIterator;
+ private TextAppearanceSpan[] mHighlightSpans = new TextAppearanceSpan[0];
public SuggestionsPopupWindow() {
mContainer = new PopupWindow(TextView.this.mContext, null,
@@ -8244,6 +8257,11 @@
mContainer.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
}
+ private class SuggestionInfo {
+ int suggestionStart, suggestionEnd; // range of suggestion item with replacement text
+ int spanStart, spanEnd; // range in TextView where text should be inserted
+ }
+
private ViewGroup getViewGroup(boolean under) {
final int viewIndex = under ? 0 : 1;
ViewGroup viewGroup = mSuggestionViews[viewIndex];
@@ -8277,6 +8295,7 @@
"Inflated TextEdit suggestion item is not a TextView: " + childView);
}
+ childView.setTag(new SuggestionInfo());
viewGroup.addView(childView);
childView.setOnClickListener(this);
}
@@ -8299,21 +8318,28 @@
mContainer.setContentView(viewGroup);
int totalNbSuggestions = 0;
+ int spanUnionStart = mText.length();
+ int spanUnionEnd = 0;
+
for (int spanIndex = 0; spanIndex < nbSpans; spanIndex++) {
SuggestionSpan suggestionSpan = suggestionSpans[spanIndex];
final int spanStart = spannable.getSpanStart(suggestionSpan);
final int spanEnd = spannable.getSpanEnd(suggestionSpan);
- final Long spanRange = packRangeInLong(spanStart, spanEnd);
+ spanUnionStart = Math.min(spanStart, spanUnionStart);
+ spanUnionEnd = Math.max(spanEnd, spanUnionEnd);
String[] suggestions = suggestionSpan.getSuggestions();
int nbSuggestions = suggestions.length;
for (int suggestionIndex = 0; suggestionIndex < nbSuggestions; suggestionIndex++) {
TextView textView = (TextView) viewGroup.getChildAt(totalNbSuggestions);
textView.setText(suggestions[suggestionIndex]);
- textView.setTag(spanRange);
+ SuggestionInfo suggestionInfo = (SuggestionInfo) textView.getTag();
+ suggestionInfo.spanStart = spanStart;
+ suggestionInfo.spanEnd = spanEnd;
totalNbSuggestions++;
- if (totalNbSuggestions == MAX_NUMBER_SUGGESTIONS) {
+ if (totalNbSuggestions > MAX_NUMBER_SUGGESTIONS) {
+ // Also end outer for loop
spanIndex = nbSpans;
break;
}
@@ -8324,8 +8350,18 @@
// TODO Replace by final text, use a dedicated layout, add a fade out timer...
TextView textView = (TextView) viewGroup.getChildAt(0);
textView.setText("No suggestions available");
- textView.setTag(NO_SUGGESTIONS);
+ SuggestionInfo suggestionInfo = (SuggestionInfo) textView.getTag();
+ suggestionInfo.spanStart = NO_SUGGESTIONS;
totalNbSuggestions++;
+ } else {
+ if (mSuggestionRangeSpan == null) mSuggestionRangeSpan = new SuggestionRangeSpan();
+ ((Editable) mText).setSpan(mSuggestionRangeSpan, spanUnionStart, spanUnionEnd,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+ for (int i = 0; i < totalNbSuggestions; i++) {
+ final TextView textView = (TextView) viewGroup.getChildAt(i);
+ highlightTextDifferences(textView, spanUnionStart, spanUnionEnd);
+ }
}
for (int i = 0; i < MAX_NUMBER_SUGGESTIONS; i++) {
@@ -8338,7 +8374,158 @@
positionAtCursor();
}
+ private long[] getWordLimits(CharSequence text) {
+ if (mWordIterator == null) mWordIterator = new WordIterator(); // TODO locale
+ mWordIterator.setCharSequence(text);
+
+ // First pass will simply count the number of words to be able to create an array
+ // Not too expensive since previous break positions are cached by the BreakIterator
+ int nbWords = 0;
+ int position = mWordIterator.following(0);
+ while (position != BreakIterator.DONE) {
+ nbWords++;
+ position = mWordIterator.following(position);
+ }
+
+ int index = 0;
+ long[] result = new long[nbWords];
+
+ position = mWordIterator.following(0);
+ while (position != BreakIterator.DONE) {
+ int wordStart = mWordIterator.getBeginning(position);
+ result[index++] = packRangeInLong(wordStart, position);
+ position = mWordIterator.following(position);
+ }
+
+ return result;
+ }
+
+ private TextAppearanceSpan highlightSpan(int index) {
+ final int length = mHighlightSpans.length;
+ if (index < length) {
+ return mHighlightSpans[index];
+ }
+
+ // Assumes indexes are requested in sequence: simply append one more item
+ TextAppearanceSpan[] newArray = new TextAppearanceSpan[length + 1];
+ System.arraycopy(mHighlightSpans, 0, newArray, 0, length);
+ TextAppearanceSpan highlightSpan = new TextAppearanceSpan(mContext,
+ android.R.style.TextAppearance_SuggestionHighlight);
+ newArray[length] = highlightSpan;
+ mHighlightSpans = newArray;
+ return highlightSpan;
+ }
+
+ private void highlightTextDifferences(TextView textView, int unionStart, int unionEnd) {
+ SuggestionInfo suggestionInfo = (SuggestionInfo) textView.getTag();
+ final int spanStart = suggestionInfo.spanStart;
+ final int spanEnd = suggestionInfo.spanEnd;
+
+ // Remove all text formating by converting to Strings
+ final String text = textView.getText().toString();
+ final String sourceText = mText.subSequence(spanStart, spanEnd).toString();
+
+ long[] sourceWordLimits = getWordLimits(sourceText);
+ long[] wordLimits = getWordLimits(text);
+
+ SpannableStringBuilder ssb = new SpannableStringBuilder();
+ // span [spanStart, spanEnd] is included in union [spanUnionStart, int spanUnionEnd]
+ // The final result is made of 3 parts: the text before, between and after the span
+ // This is the text before, provided for context
+ ssb.append(mText.subSequence(unionStart, spanStart).toString());
+
+ // shift is used to offset spans positions wrt span's beginning
+ final int shift = spanStart - unionStart;
+ suggestionInfo.suggestionStart = shift;
+ suggestionInfo.suggestionEnd = shift + text.length();
+
+ // This is the actual suggestion text, which will be highlighted by the following code
+ ssb.append(text);
+
+ String[] words = new String[wordLimits.length];
+ for (int i = 0; i < wordLimits.length; i++) {
+ int wordStart = extractRangeStartFromLong(wordLimits[i]);
+ int wordEnd = extractRangeEndFromLong(wordLimits[i]);
+ words[i] = text.substring(wordStart, wordEnd);
+ }
+
+ // Highlighted word algorithm is bases on word matching between source and text
+ // Matching words are found from left to right. TODO: change for RTL languages
+ // Characters between matching words are highlighted
+ int previousCommonWordIndex = -1;
+ int nbHighlightSpans = 0;
+ for (int i = 0; i < sourceWordLimits.length; i++) {
+ int wordStart = extractRangeStartFromLong(sourceWordLimits[i]);
+ int wordEnd = extractRangeEndFromLong(sourceWordLimits[i]);
+ String sourceWord = sourceText.substring(wordStart, wordEnd);
+
+ for (int j = previousCommonWordIndex + 1; j < words.length; j++) {
+ if (sourceWord.equals(words[j])) {
+ if (j != previousCommonWordIndex + 1) {
+ int firstDifferentPosition = previousCommonWordIndex < 0 ? 0 :
+ extractRangeEndFromLong(wordLimits[previousCommonWordIndex]);
+ int lastDifferentPosition = extractRangeStartFromLong(wordLimits[j]);
+ ssb.setSpan(highlightSpan(nbHighlightSpans++),
+ shift + firstDifferentPosition, shift + lastDifferentPosition,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ } else {
+ // Compare characters between words
+ int previousSourceWordEnd = i == 0 ? 0 :
+ extractRangeEndFromLong(sourceWordLimits[i - 1]);
+ int sourceWordStart = extractRangeStartFromLong(sourceWordLimits[i]);
+ String sourceSpaces = sourceText.substring(previousSourceWordEnd,
+ sourceWordStart);
+
+ int previousWordEnd = j == 0 ? 0 :
+ extractRangeEndFromLong(wordLimits[j - 1]);
+ int currentWordStart = extractRangeStartFromLong(wordLimits[j]);
+ String textSpaces = text.substring(previousWordEnd, currentWordStart);
+
+ if (!sourceSpaces.equals(textSpaces)) {
+ ssb.setSpan(highlightSpan(nbHighlightSpans++),
+ shift + previousWordEnd, shift + currentWordStart,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ }
+ previousCommonWordIndex = j;
+ break;
+ }
+ }
+ }
+
+ // Finally, compare ends of Strings
+ if (previousCommonWordIndex < words.length - 1) {
+ int firstDifferentPosition = previousCommonWordIndex < 0 ? 0 :
+ extractRangeEndFromLong(wordLimits[previousCommonWordIndex]);
+ int lastDifferentPosition = textView.length();
+ ssb.setSpan(highlightSpan(nbHighlightSpans++),
+ shift + firstDifferentPosition, shift + lastDifferentPosition,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ } else {
+ int lastSourceWordEnd = sourceWordLimits.length == 0 ? 0 :
+ extractRangeEndFromLong(sourceWordLimits[sourceWordLimits.length - 1]);
+ String sourceSpaces = sourceText.substring(lastSourceWordEnd, sourceText.length());
+
+ int lastCommonTextWordEnd = previousCommonWordIndex < 0 ? 0 :
+ extractRangeEndFromLong(wordLimits[previousCommonWordIndex]);
+ String textSpaces = text.substring(lastCommonTextWordEnd, textView.length());
+
+ if (!sourceSpaces.equals(textSpaces) && textSpaces.length() > 0) {
+ ssb.setSpan(highlightSpan(nbHighlightSpans++),
+ shift + lastCommonTextWordEnd, shift + textView.length(),
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ }
+
+ // Final part, text after the current suggestion range.
+ ssb.append(mText.subSequence(spanEnd, unionEnd).toString());
+ textView.setText(ssb);
+ }
+
public void hide() {
+ if ((mText instanceof Editable) && mSuggestionRangeSpan != null) {
+ ((Editable) mText).removeSpan(mSuggestionRangeSpan);
+ }
mContainer.dismiss();
}
@@ -8346,11 +8533,15 @@
public void onClick(View view) {
if (view instanceof TextView) {
TextView textView = (TextView) view;
- Long range = ((Long) view.getTag());
- if (range != NO_SUGGESTIONS) {
- final int spanStart = extractRangeStartFromLong(range);
- final int spanEnd = extractRangeEndFromLong(range);
- ((Editable) mText).replace(spanStart, spanEnd, textView.getText());
+ SuggestionInfo suggestionInfo = (SuggestionInfo) textView.getTag();
+ final int spanStart = suggestionInfo.spanStart;
+ final int spanEnd = suggestionInfo.spanEnd;
+ if (spanStart != NO_SUGGESTIONS) {
+ final int suggestionStart = suggestionInfo.suggestionStart;
+ final int suggestionEnd = suggestionInfo.suggestionEnd;
+ final String suggestion = textView.getText().subSequence(
+ suggestionStart, suggestionEnd).toString();
+ ((Editable) mText).replace(spanStart, spanEnd, suggestion);
}
}
hide();
diff --git a/core/res/res/drawable-hdpi/text_edit_suggestions_bottom_window.9.png b/core/res/res/drawable-hdpi/text_edit_suggestions_bottom_window.9.png
new file mode 100644
index 0000000..c97514f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/text_edit_suggestions_bottom_window.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_edit_suggestions_top_window.9.png b/core/res/res/drawable-hdpi/text_edit_suggestions_top_window.9.png
new file mode 100644
index 0000000..ff6b34a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/text_edit_suggestions_top_window.9.png
Binary files differ
diff --git a/core/res/res/layout/text_edit_suggestion_item.xml b/core/res/res/layout/text_edit_suggestion_item.xml
index a54cad2..ef537d9 100644
--- a/core/res/res/layout/text_edit_suggestion_item.xml
+++ b/core/res/res/layout/text_edit_suggestion_item.xml
@@ -21,7 +21,7 @@
android:paddingRight="16dip"
android:paddingTop="8dip"
android:paddingBottom="8dip"
- android:layout_gravity="center"
+ android:layout_gravity="left|center_vertical"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@android:color/black" />
+ android:textColor="@android:color/dim_foreground_light" />
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 9c59cb6..39d2329 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -60,6 +60,7 @@
<color name="highlighted_text_light">#9983CC39</color>
<color name="link_text_dark">#5c5cff</color>
<color name="link_text_light">#0000ee</color>
+ <color name="suggestion_highlight_text">#177bbd</color>
<drawable name="stat_notify_sync_noanim">@drawable/stat_notify_sync_anim0</drawable>
<drawable name="stat_sys_download_done">@drawable/stat_sys_download_anim0</drawable>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 778d934..501d478 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1659,6 +1659,7 @@
<public type="attr" name="stopWithTask" />
<public type="style" name="Theme.Holo.Light.NoActionBar" />
+ <public type="style" name="TextAppearance.SuggestionHighlight" />
<public type="attr" name="textSuggestionsWindowStyle" />
<public type="attr" name="textEditSuggestionsBottomWindowLayout" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 8ce35f8..e666698 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -876,6 +876,13 @@
<item name="android:textSize">30sp</item>
</style>
+ <!-- @hide -->
+ <style name="TextAppearance.SuggestionHighlight">
+ <item name="android:textSize">18sp</item>
+ <item name="android:textColor">@android:color/suggestion_highlight_text</item>
+ <item name="android:textStyle">bold</item>
+ </style>
+
<!-- Preference Styles -->
<style name="Preference">
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 4be6995..010e3c3 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -100,6 +100,12 @@
<application android:theme="@style/Theme">
<uses-library android:name="android.test.runner" />
+ <activity android:name="android.view.ViewAttachTestActivity" android:label="View Attach Test">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
<activity android:name="StubTestBrowserActivity" android:label="Stubbed Test Browser">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
diff --git a/core/tests/coretests/res/layout/attach_view_test.xml b/core/tests/coretests/res/layout/attach_view_test.xml
new file mode 100644
index 0000000..42841cb
--- /dev/null
+++ b/core/tests/coretests/res/layout/attach_view_test.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+ <android.view.ViewAttachView
+ android:id="@+id/view_attach_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:keepScreenOn="true"/>
+</LinearLayout>
diff --git a/core/tests/coretests/src/android/view/ViewAttachTest.java b/core/tests/coretests/src/android/view/ViewAttachTest.java
new file mode 100644
index 0000000..cff66e4
--- /dev/null
+++ b/core/tests/coretests/src/android/view/ViewAttachTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.view;
+
+import android.content.pm.ActivityInfo;
+import android.os.SystemClock;
+import android.test.ActivityInstrumentationTestCase2;
+
+public class ViewAttachTest extends
+ ActivityInstrumentationTestCase2<ViewAttachTestActivity> {
+
+ public ViewAttachTest() {
+ super(ViewAttachTestActivity.class);
+ }
+
+ /**
+ * Make sure that onAttachedToWindow and onDetachedToWindow is called in the
+ * correct order The ViewAttachTestActivity contains a view that will throw
+ * an RuntimeException if onDetachedToWindow and onAttachedToWindow is
+ * called in the wrong order.
+ *
+ * 1. Initiate the activity 2. Perform a series of orientation changes to
+ * the activity (this will force the View hierarchy to be rebuild,
+ * generating onAttachedToWindow and onDetachedToWindow)
+ *
+ * Expected result: No RuntimeException is thrown from the TestView in
+ * ViewFlipperTestActivity.
+ *
+ * @throws Throwable
+ */
+ public void testAttached() throws Throwable {
+ final ViewAttachTestActivity activity = getActivity();
+ for (int i = 0; i < 20; i++) {
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ SystemClock.sleep(250);
+ activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ SystemClock.sleep(250);
+ }
+ }
+}
diff --git a/core/tests/coretests/src/android/view/ViewAttachTestActivity.java b/core/tests/coretests/src/android/view/ViewAttachTestActivity.java
new file mode 100644
index 0000000..59e25ae
--- /dev/null
+++ b/core/tests/coretests/src/android/view/ViewAttachTestActivity.java
@@ -0,0 +1,31 @@
+/*
+ * 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.view;
+
+import com.android.frameworks.coretests.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class ViewAttachTestActivity extends Activity {
+ public static final String TAG = "OnAttachedTest";
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.attach_view_test);
+ }
+}
diff --git a/core/tests/coretests/src/android/view/ViewAttachView.java b/core/tests/coretests/src/android/view/ViewAttachView.java
new file mode 100644
index 0000000..5af2d8f
--- /dev/null
+++ b/core/tests/coretests/src/android/view/ViewAttachView.java
@@ -0,0 +1,80 @@
+/*
+ * 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.view;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.os.SystemClock;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+
+/**
+ * A View that will throw a RuntimeException if onAttachedToWindow and
+ * onDetachedFromWindow is called in the wrong order for ViewAttachTest
+ */
+public class ViewAttachView extends View {
+ public static final String TAG = "OnAttachedTest";
+ private boolean attached;
+
+ public ViewAttachView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init(attrs, defStyle);
+ }
+
+ public ViewAttachView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(attrs, 0);
+ }
+
+ public ViewAttachView(Context context) {
+ super(context);
+ init(null, 0);
+ }
+
+ private void init(AttributeSet attrs, int defStyle) {
+ SystemClock.sleep(2000);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ Log.d(TAG, "onAttachedToWindow");
+ super.onAttachedToWindow();
+ if (attached) {
+ throw new RuntimeException("OnAttachedToWindow called more than once in a row");
+ }
+ attached = true;
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ Log.d(TAG, "onDetachedFromWindow");
+ super.onDetachedFromWindow();
+ if (!attached) {
+ throw new RuntimeException(
+ "onDetachedFromWindowcalled without prior call to OnAttachedToWindow");
+ }
+ attached = false;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ canvas.drawColor(Color.BLUE);
+ }
+}
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index b752850..c3f2360 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -237,7 +237,11 @@
size_t receiveLen;
uint32_t subID;
- int id = rsContextGetMessage(con, buf, &receiveLen, &subID, sizeof(buf), true);
+ int id = rsContextGetMessage(con,
+ buf, sizeof(buf),
+ &receiveLen, sizeof(receiveLen),
+ &subID, sizeof(subID),
+ true);
if (!id && receiveLen) {
LOGV("message receive buffer too small. %i", receiveLen);
}
@@ -252,7 +256,11 @@
jint *ptr = _env->GetIntArrayElements(data, NULL);
size_t receiveLen;
uint32_t subID;
- int id = rsContextGetMessage(con, ptr, &receiveLen, &subID, len * 4, true);
+ int id = rsContextGetMessage(con,
+ ptr, len * 4,
+ &receiveLen, sizeof(receiveLen),
+ &subID, sizeof(subID),
+ true);
if (!id && receiveLen) {
LOGV("message receive buffer too small. %i", receiveLen);
}
@@ -266,7 +274,8 @@
jint *auxDataPtr = _env->GetIntArrayElements(auxData, NULL);
size_t receiveLen;
uint32_t subID;
- int id = rsContextPeekMessage(con, &receiveLen, &subID, wait);
+ int id = rsContextPeekMessage(con, &receiveLen, sizeof(receiveLen),
+ &subID, sizeof(subID), wait);
auxDataPtr[0] = (jint)subID;
auxDataPtr[1] = (jint)receiveLen;
_env->ReleaseIntArrayElements(auxData, auxDataPtr, 0);
@@ -426,7 +435,9 @@
bitmap.lockPixels();
const void* ptr = bitmap.getPixels();
- jint id = (jint)rsaAllocationCreateFromBitmap(con, (RsType)type, (RsAllocationMipmapControl)mip, ptr, usage);
+ jint id = (jint)rsaAllocationCreateFromBitmap(con,
+ (RsType)type, (RsAllocationMipmapControl)mip,
+ ptr, bitmap.getSize(), usage);
bitmap.unlockPixels();
return id;
}
@@ -440,7 +451,9 @@
bitmap.lockPixels();
const void* ptr = bitmap.getPixels();
- jint id = (jint)rsaAllocationCubeCreateFromBitmap(con, (RsType)type, (RsAllocationMipmapControl)mip, ptr, usage);
+ jint id = (jint)rsaAllocationCubeCreateFromBitmap(con,
+ (RsType)type, (RsAllocationMipmapControl)mip,
+ ptr, bitmap.getSize(), usage);
bitmap.unlockPixels();
return id;
}
diff --git a/include/media/stagefright/MediaErrors.h b/include/media/stagefright/MediaErrors.h
index 6df4d86..1a6d548 100644
--- a/include/media/stagefright/MediaErrors.h
+++ b/include/media/stagefright/MediaErrors.h
@@ -42,6 +42,17 @@
INFO_DISCONTINUITY = MEDIA_ERROR_BASE - 13,
ERROR_NO_LICENSE = MEDIA_ERROR_BASE - 14,
+
+ // Heartbeat Error Codes
+ HEARTBEAT_ERROR_BASE = -3000,
+
+ ERROR_HEARTBEAT_AUTHENTICATION_FAILURE = HEARTBEAT_ERROR_BASE,
+ ERROR_HEARTBEAT_NO_ACTIVE_PURCHASE_AGREEMENT = HEARTBEAT_ERROR_BASE - 1,
+ ERROR_HEARTBEAT_CONCURRENT_PLAYBACK = HEARTBEAT_ERROR_BASE - 2,
+ ERROR_HEARTBEAT_UNUSUAL_ACTIVITY = HEARTBEAT_ERROR_BASE - 3,
+ ERROR_HEARTBEAT_STREAMING_UNAVAILABLE = HEARTBEAT_ERROR_BASE - 4,
+ ERROR_HEARTBEAT_CANNOT_ACTIVATE_RENTAL = HEARTBEAT_ERROR_BASE - 5,
+ ERROR_HEARTBEAT_TERMINATE_REQUESTED = HEARTBEAT_ERROR_BASE - 6,
};
} // namespace android
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 26e240f..6c4a2a9 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -53,6 +53,23 @@
}
/**
+ * Sets this layer's region to a rectangle. Computes the appropriate
+ * texture coordinates.
+ */
+ void setRegionAsRect() {
+ const android::Rect& bounds = region.getBounds();
+ regionRect.set(bounds.leftTop().x, bounds.leftTop().y,
+ bounds.rightBottom().x, bounds.rightBottom().y);
+
+ const float texX = 1.0f / float(width);
+ const float texY = 1.0f / float(height);
+ const float height = layer.getHeight();
+ texCoords.set(
+ regionRect.left * texX, (height - regionRect.top) * texY,
+ regionRect.right * texX, (height - regionRect.bottom) * texY);
+ }
+
+ /**
* Bounds of the layer.
*/
Rect layer;
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index ba110ec..ca1e7ae 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -102,19 +102,7 @@
mLayer->meshElementCount = 0;
}
- const android::Rect& bounds = mLayer->region.getBounds();
- mLayer->regionRect.set(bounds.leftTop().x, bounds.leftTop().y,
- bounds.rightBottom().x, bounds.rightBottom().y);
-
- const float texX = 1.0f / float(mLayer->width);
- const float texY = 1.0f / float(mLayer->height);
- const float height = mLayer->layer.getHeight();
- mLayer->texCoords.set(
- mLayer->regionRect.left * texX,
- (height - mLayer->regionRect.top) * texY,
- mLayer->regionRect.right * texX,
- (height - mLayer->regionRect.bottom) * texY);
-
+ mLayer->setRegionAsRect();
return;
}
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index dd0cca22..ea42838 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -647,10 +647,10 @@
void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
#if RENDER_LAYERS_AS_REGIONS
if (layer->region.isRect()) {
- const android::Rect& bounds = layer->region.getBounds();
- layer->regionRect.set(bounds.leftTop().x, bounds.leftTop().y,
- bounds.rightBottom().x, bounds.rightBottom().y);
+ layer->setRegionAsRect();
+
composeLayerRect(layer, layer->regionRect);
+
layer->region.clear();
return;
}
@@ -979,8 +979,8 @@
}
}
-void OpenGLRenderer::setupDrawModelViewIdentity() {
- mCaches.currentProgram->set(mOrthoMatrix, mIdentity, *mSnapshot->transform);
+void OpenGLRenderer::setupDrawModelViewIdentity(bool offset) {
+ mCaches.currentProgram->set(mOrthoMatrix, mIdentity, *mSnapshot->transform, offset);
}
void OpenGLRenderer::setupDrawModelView(float left, float top, float right, float bottom,
@@ -1389,13 +1389,46 @@
}
}
-void OpenGLRenderer::drawLinesAsQuads(float *points, int count, bool isAA, bool isHairline,
- float strokeWidth) {
+void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
+ if (mSnapshot->isIgnored()) return;
+
+ const bool isAA = paint->isAntiAlias();
+ float strokeWidth = paint->getStrokeWidth() * 0.5f;
+ // A stroke width of 0 has a special meaning in Skia:
+ // it draws a line 1 px wide regardless of current transform
+ bool isHairLine = paint->getStrokeWidth() == 0.0f;
+ int alpha;
+ SkXfermode::Mode mode;
+ int generatedVerticesCount = 0;
int verticesCount = count;
if (count > 4) {
// Polyline: account for extra vertices needed for continous tri-strip
verticesCount += (count -4);
}
+
+ getAlphaAndMode(paint, &alpha, &mode);
+ setupDraw();
+ if (isAA) {
+ setupDrawAALine();
+ }
+ setupDrawColor(paint->getColor(), alpha);
+ setupDrawColorFilter();
+ setupDrawShader();
+ if (isAA) {
+ setupDrawBlending(true, mode);
+ } else {
+ setupDrawBlending(mode);
+ }
+ setupDrawProgram();
+ setupDrawModelViewIdentity(true);
+ setupDrawColorUniforms();
+ setupDrawColorFilterUniforms();
+ setupDrawShaderIdentityUniforms();
+
+ if (isHairLine) {
+ // Set a real stroke width to be used in quad construction
+ strokeWidth = .5;
+ }
if (isAA) {
// Expand boundary to enable AA calculations on the quad border
strokeWidth += .5f;
@@ -1407,25 +1440,22 @@
if (!isAA) {
setupDrawVertices(vertices);
} else {
- AlphaVertex* alphaCoords = aaVertices + gVertexAlphaOffset;
+ void* alphaCoords = ((GLbyte*) aaVertices) + gVertexAlphaOffset;
// innerProportion is the ratio of the inner (non-AA) port of the line to the total
// AA stroke width (the base stroke width expanded by a half pixel on either side).
// This value is used in the fragment shader to determine how to fill fragments.
float innerProportion = fmax(strokeWidth - 1.0f, 0) / (strokeWidth + .5f);
- setupDrawAALine((void*) aaVertices, (void*) alphaCoords, innerProportion);
+ setupDrawAALine((void*) aaVertices, alphaCoords, innerProportion);
}
- int generatedVerticesCount = 0;
AlphaVertex *prevAAVertex = NULL;
Vertex *prevVertex = NULL;
float inverseScaleX = 1.0f;
float inverseScaleY = 1.0f;
- if (isHairline) {
+ if (isHairLine) {
// The quad that we use for AA hairlines needs to account for scaling because the line
// should always be one pixel wide regardless of scale.
- inverseScaleX = 1.0f;
- inverseScaleY = 1.0f;
if (!mSnapshot->transform->isPureTranslate()) {
Matrix4 *mat = mSnapshot->transform;
float m00 = mat->data[Matrix4::kScaleX];
@@ -1446,22 +1476,19 @@
vec2 a(points[i], points[i + 1]);
vec2 b(points[i + 2], points[i + 3]);
- // Bias to snap to the same pixels as Skia
- a += 0.375;
- b += 0.375;
-
// Find the normal to the line
vec2 n = (b - a).copyNormalized() * strokeWidth;
- if (isHairline) {
- float wideningFactor;
- if (fabs(n.x) >= fabs(n.y)) {
- wideningFactor = fabs(1.0f / n.x);
- } else {
- wideningFactor = fabs(1.0f / n.y);
+ if (isHairLine) {
+ n *= inverseScaleX;
+ if (isAA) {
+ float wideningFactor;
+ if (fabs(n.x) >= fabs(n.y)) {
+ wideningFactor = fabs(1.0f / n.x);
+ } else {
+ wideningFactor = fabs(1.0f / n.y);
+ }
+ n *= wideningFactor;
}
- n.x *= inverseScaleX;
- n.y *= inverseScaleY;
- n *= wideningFactor;
}
float x = n.x;
n.x = -n.y;
@@ -1525,69 +1552,6 @@
}
}
-void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
- if (mSnapshot->isIgnored()) return;
-
- const bool isAA = paint->isAntiAlias();
- const float strokeWidth = paint->getStrokeWidth() * 0.5f;
- // A stroke width of 0 has a special meaning in Skia:
- // it draws a line 1 px wide regardless of current transform
- bool isHairLine = paint->getStrokeWidth() == 0.0f;
-
- int alpha;
- SkXfermode::Mode mode;
- getAlphaAndMode(paint, &alpha, &mode);
- int generatedVerticesCount = 0;
-
- setupDraw();
- if (isAA) {
- setupDrawAALine();
- }
- setupDrawColor(paint->getColor(), alpha);
- setupDrawColorFilter();
- setupDrawShader();
- if (isAA) {
- setupDrawBlending(true, mode);
- } else {
- setupDrawBlending(mode);
- }
- setupDrawProgram();
- setupDrawModelViewIdentity();
- setupDrawColorUniforms();
- setupDrawColorFilterUniforms();
- setupDrawShaderIdentityUniforms();
-
- if (!isHairLine) {
- drawLinesAsQuads(points, count, isAA, isHairLine, strokeWidth);
- } else {
- if (isAA) {
- drawLinesAsQuads(points, count, isAA, isHairLine, .5f);
- } else {
- int verticesCount = count >> 1;
- Vertex lines[verticesCount];
- Vertex* vertices = &lines[0];
- setupDrawVertices(vertices);
- for (int i = 0; i < count; i += 4) {
-
- const float left = fmin(points[i], points[i + 2]);
- const float right = fmax(points[i], points[i + 2]);
- const float top = fmin(points[i + 1], points[i + 3]);
- const float bottom = fmax(points[i + 1], points[i + 3]);
-
- Vertex::set(vertices++, points[i], points[i + 1]);
- Vertex::set(vertices++, points[i + 2], points[i + 3]);
- generatedVerticesCount += 2;
- dirtyLayer(left, top,
- right == left ? left + 1 : right, bottom == top ? top + 1 : bottom,
- *mSnapshot->transform);
- }
-
- glLineWidth(1.0f);
- glDrawArrays(GL_LINES, 0, generatedVerticesCount);
- }
- }
-}
-
void OpenGLRenderer::drawPoints(float* points, int count, SkPaint* paint) {
if (mSnapshot->isIgnored()) return;
@@ -1596,8 +1560,13 @@
// A stroke width of 0 has a special meaning in Skia:
// it draws an unscaled 1px point
+ float strokeWidth = paint->getStrokeWidth();
const bool isHairLine = paint->getStrokeWidth() == 0.0f;
-
+ if (isHairLine) {
+ // Now that we know it's hairline, we can set the effective width, to be used later
+ strokeWidth = 1.0f;
+ }
+ const float halfWidth = strokeWidth / 2;
int alpha;
SkXfermode::Mode mode;
getAlphaAndMode(paint, &alpha, &mode);
@@ -1609,13 +1578,13 @@
TextureVertex* vertex = &pointsData[0];
setupDraw();
- setupDrawPoint(isHairLine ? 1.0f : paint->getStrokeWidth());
+ setupDrawPoint(strokeWidth);
setupDrawColor(paint->getColor(), alpha);
setupDrawColorFilter();
setupDrawShader();
setupDrawBlending(mode);
setupDrawProgram();
- setupDrawModelViewIdentity();
+ setupDrawModelViewIdentity(true);
setupDrawColorUniforms();
setupDrawColorFilterUniforms();
setupDrawPointUniforms();
@@ -1625,6 +1594,11 @@
for (int i = 0; i < count; i += 2) {
TextureVertex::set(vertex++, points[i], points[i + 1], 0.0f, 0.0f);
generatedVerticesCount++;
+ float left = points[i] - halfWidth;
+ float right = points[i] + halfWidth;
+ float top = points[i + 1] - halfWidth;
+ float bottom = points [i + 1] + halfWidth;
+ dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
}
glDrawArrays(GL_POINTS, 0, generatedVerticesCount);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 0276095..918e1fb 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -283,19 +283,6 @@
void drawAlphaBitmap(Texture* texture, float left, float top, SkPaint* paint);
/**
- * Draws a line as a quad. Called by drawLines() for all cases except hairline without AA.
- *
- * @param points The vertices of the lines. Every four entries specifies the x/y points
- * of a single line segment.
- * @param count The number of entries in the points array.
- * @param isAA Whether the line is anti-aliased
- * @param isHairline Whether the line has strokeWidth==0, which results in the line being
- * one pixel wide on the display regardless of scale.
- */
- void drawLinesAsQuads(float *points, int count, bool isAA, bool isHairline,
- float strokeWidth);
-
- /**
* Draws a textured rectangle with the specified texture. The specified coordinates
* are transformed by the current snapshot's transform matrix.
*
@@ -453,7 +440,7 @@
bool swapSrcDst = false);
void setupDrawProgram();
void setupDrawDirtyRegionsDisabled();
- void setupDrawModelViewIdentity();
+ void setupDrawModelViewIdentity(bool offset = false);
void setupDrawModelView(float left, float top, float right, float bottom,
bool ignoreTransform = false, bool ignoreModelView = false);
void setupDrawModelViewTranslate(float left, float top, float right, float bottom,
diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp
index 2187f24..972dd87 100644
--- a/libs/hwui/Program.cpp
+++ b/libs/hwui/Program.cpp
@@ -124,8 +124,15 @@
}
void Program::set(const mat4& projectionMatrix, const mat4& modelViewMatrix,
- const mat4& transformMatrix) {
+ const mat4& transformMatrix, bool offset) {
mat4 t(projectionMatrix);
+ if (offset) {
+ // offset screenspace xy by an amount that compensates for typical precision issues
+ // in GPU hardware that tends to paint hor/vert lines in pixels shifted up and to the left.
+ // This offset value is based on an assumption that some hardware may use as little
+ // as 12.4 precision, so we offset by slightly more than 1/16.
+ t.translate(.375, .375, 0);
+ }
t.multiply(transformMatrix);
t.multiply(modelViewMatrix);
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index afc6f3d..764cb05 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -81,7 +81,7 @@
* transform matrices.
*/
void set(const mat4& projectionMatrix, const mat4& modelViewMatrix,
- const mat4& transformMatrix);
+ const mat4& transformMatrix, bool offset = false);
/**
* Sets the color associated with this shader.
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index cb6d7e0..f4e3f57 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -26,20 +26,6 @@
#include "RenderScriptDefines.h"
-RsDevice rsDeviceCreate();
-void rsDeviceDestroy(RsDevice);
-void rsDeviceSetConfig(RsDevice, RsDeviceParam, int32_t value);
-
-RsContext rsContextCreate(RsDevice, uint32_t version);
-RsContext rsContextCreateGL(RsDevice, uint32_t version,
- RsSurfaceConfig sc, uint32_t dpi);
-void rsContextDestroy(RsContext);
-
-RsMessageToClientType rsContextGetMessage(RsContext vrsc, void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen, bool wait);
-RsMessageToClientType rsContextPeekMessage(RsContext vrsc, size_t *receiveLen, uint32_t *subID, bool wait);
-void rsContextInitToClient(RsContext);
-void rsContextDeinitToClient(RsContext);
-
//
// A3D loading and object update code.
// Should only be called at object creation, not thread safe
@@ -63,18 +49,8 @@
void rsaElementGetNativeData(RsContext, RsElement, uint32_t *elemData, uint32_t elemDataSize);
void rsaElementGetSubElements(RsContext, RsElement, uint32_t *ids, const char **names, uint32_t dataSize);
-// Async commands for returning new IDS
-RsType rsaTypeCreate(RsContext, RsElement, uint32_t dimX, uint32_t dimY,
- uint32_t dimZ, bool mips, bool faces);
-RsAllocation rsaAllocationCreateTyped(RsContext rsc, RsType vtype,
- RsAllocationMipmapControl mips,
- uint32_t usages);
-RsAllocation rsaAllocationCreateFromBitmap(RsContext con, RsType vtype,
- RsAllocationMipmapControl mips,
- const void *data, uint32_t usages);
-RsAllocation rsaAllocationCubeCreateFromBitmap(RsContext con, RsType vtype,
- RsAllocationMipmapControl mips,
- const void *data, uint32_t usages);
+
+
#ifdef ANDROID_RS_SERIALIZE
#define NO_RS_FUNCS
#endif
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index dac5cec..998296b 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -1,4 +1,110 @@
+DeviceCreate {
+ direct
+ nocontext
+ ret RsDevice
+}
+
+DeviceDestroy {
+ direct
+ nocontext
+ param RsDevice dev
+}
+
+DeviceSetConfig {
+ direct
+ nocontext
+ param RsDevice dev
+ param RsDeviceParam p
+ param int32_t value
+}
+
+ContextCreate {
+ direct
+ nocontext
+ param RsDevice dev
+ param uint32_t version
+ ret RsContext
+}
+
+ContextCreateGL {
+ direct
+ nocontext
+ param RsDevice dev
+ param uint32_t version
+ param RsSurfaceConfig sc
+ param uint32_t dpi
+ ret RsContext
+}
+
+ContextDestroy {
+ direct
+}
+
+ContextGetMessage {
+ direct
+ param void *data
+ param size_t *receiveLen
+ param uint32_t *subID
+ param bool wait
+ ret RsMessageToClientType
+}
+
+ContextPeekMessage {
+ direct
+ param size_t *receiveLen
+ param uint32_t *subID
+ param bool wait
+ ret RsMessageToClientType
+}
+
+ContextInitToClient {
+ direct
+}
+
+ContextDeinitToClient {
+ direct
+}
+
+aTypeCreate {
+ direct
+ param RsElement e
+ param uint32_t dimX
+ param uint32_t dimY
+ param uint32_t dimZ
+ param bool mips
+ param bool faces
+ ret RsType
+}
+
+aAllocationCreateTyped {
+ direct
+ param RsType vtype
+ param RsAllocationMipmapControl mips
+ param uint32_t usages
+ ret RsAllocation
+}
+
+aAllocationCreateFromBitmap {
+ direct
+ param RsType vtype
+ param RsAllocationMipmapControl mips
+ param const void *data
+ param uint32_t usages
+ ret RsAllocation
+}
+
+aAllocationCubeCreateFromBitmap {
+ direct
+ param RsType vtype
+ param RsAllocationMipmapControl mips
+ param const void *data
+ param uint32_t usages
+ ret RsAllocation
+}
+
+
+
ContextFinish {
handcodeApi
}
@@ -82,23 +188,21 @@
Allocation1DData {
+ handcodeApi
param RsAllocation va
param uint32_t xoff
param uint32_t lod
param uint32_t count
param const void *data
- handcodeApi
- togglePlay
}
Allocation1DElementData {
+ handcodeApi
param RsAllocation va
param uint32_t x
param uint32_t lod
param const void *data
param uint32_t comp_offset
- handcodeApi
- togglePlay
}
Allocation2DData {
@@ -186,11 +290,10 @@
}
ScriptInvokeV {
+ handcodeApi
param RsScript s
param uint32_t slot
param const void * data
- handcodeApi
- togglePlay
}
ScriptSetVarI {
@@ -224,11 +327,10 @@
}
ScriptSetVarV {
+ handcodeApi
param RsScript s
param uint32_t slot
param const void * data
- handcodeApi
- togglePlay
}
@@ -330,3 +432,4 @@
MeshInitVertexAttribs {
param RsMesh mesh
}
+
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index a759004..743b2c4 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -833,7 +833,7 @@
RsAllocation rsaAllocationCreateFromBitmap(RsContext con, RsType vtype,
RsAllocationMipmapControl mips,
- const void *data, uint32_t usages) {
+ const void *data, size_t data_length, uint32_t usages) {
Context *rsc = static_cast<Context *>(con);
Type *t = static_cast<Type *>(vtype);
@@ -855,7 +855,7 @@
RsAllocation rsaAllocationCubeCreateFromBitmap(RsContext con, RsType vtype,
RsAllocationMipmapControl mips,
- const void *data, uint32_t usages) {
+ const void *data, size_t data_length, uint32_t usages) {
Context *rsc = static_cast<Context *>(con);
Type *t = static_cast<Type *>(vtype);
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 0ca892d..50f5f55 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -768,14 +768,20 @@
return rsc;
}
-RsMessageToClientType rsContextPeekMessage(RsContext vrsc, size_t *receiveLen, uint32_t *subID, bool wait) {
+RsMessageToClientType rsContextPeekMessage(RsContext vrsc,
+ size_t * receiveLen, size_t receiveLen_length,
+ uint32_t * subID, size_t subID_length, bool wait) {
Context * rsc = static_cast<Context *>(vrsc);
return rsc->peekMessageToClient(receiveLen, subID, wait);
}
-RsMessageToClientType rsContextGetMessage(RsContext vrsc, void *data, size_t *receiveLen, uint32_t *subID, size_t bufferLen, bool wait) {
+RsMessageToClientType rsContextGetMessage(RsContext vrsc, void * data, size_t data_length,
+ size_t * receiveLen, size_t receiveLen_length,
+ uint32_t * subID, size_t subID_length, bool wait) {
Context * rsc = static_cast<Context *>(vrsc);
- return rsc->getMessageToClient(data, receiveLen, subID, bufferLen, wait);
+ rsAssert(subID_length == sizeof(uint32_t));
+ rsAssert(receiveLen_length == sizeof(size_t));
+ return rsc->getMessageToClient(data, receiveLen, subID, data_length, wait);
}
void rsContextInitToClient(RsContext vrsc) {
diff --git a/libs/rs/rsg_generator.c b/libs/rs/rsg_generator.c
index 4ac5b7f..14b380a 100644
--- a/libs/rs/rsg_generator.c
+++ b/libs/rs/rsg_generator.c
@@ -4,7 +4,7 @@
void printFileHeader(FILE *f) {
fprintf(f, "/*\n");
- fprintf(f, " * Copyright (C) 2010 The Android Open Source Project\n");
+ fprintf(f, " * Copyright (C) 2011 The Android Open Source Project\n");
fprintf(f, " *\n");
fprintf(f, " * Licensed under the Apache License, Version 2.0 (the \"License\");\n");
fprintf(f, " * you may not use this file except in compliance with the License.\n");
@@ -96,12 +96,14 @@
void printFuncDecl(FILE *f, const ApiEntry *api, const char *prefix, int addContext) {
printVarType(f, &api->ret);
fprintf(f, " %s%s (", prefix, api->name);
- if (addContext) {
- fprintf(f, "Context *");
- } else {
- fprintf(f, "RsContext rsc");
+ if (!api->nocontext) {
+ if (addContext) {
+ fprintf(f, "Context *");
+ } else {
+ fprintf(f, "RsContext rsc");
+ }
}
- printArgList(f, api, 1);
+ printArgList(f, api, !api->nocontext);
fprintf(f, ")");
}
@@ -117,6 +119,10 @@
void printPlaybackFuncs(FILE *f, const char *prefix) {
int ct;
for (ct=0; ct < apiCount; ct++) {
+ if (apis[ct].direct) {
+ continue;
+ }
+
fprintf(f, "void %s%s (Context *, const void *);\n", prefix, apis[ct].name);
}
}
@@ -140,6 +146,10 @@
int needFlush = 0;
const ApiEntry * api = &apis[ct];
+ if (api->direct) {
+ continue;
+ }
+
printFuncDecl(f, api, "rs", 0);
fprintf(f, "\n{\n");
if (api->handcodeApi) {
@@ -198,31 +208,37 @@
for (ct=0; ct < apiCount; ct++) {
const ApiEntry * api = &apis[ct];
+ if (api->direct) {
+ continue;
+ }
+
fprintf(f, "void rsp_%s(Context *con, const void *vp)\n", api->name);
fprintf(f, "{\n");
- if (api->handcodePlay) {
- fprintf(f, " rsHCPLAY_%s(con, vp);\n", api->name);
- } else {
- //fprintf(f, " LOGE(\"play command %s\\n\");\n", api->name);
- fprintf(f, " const RS_CMD_%s *cmd = static_cast<const RS_CMD_%s *>(vp);\n", api->name, api->name);
- fprintf(f, " ");
- if (api->ret.typeName[0]) {
- fprintf(f, "con->mIO.mToCoreRet = (intptr_t)");
- }
- fprintf(f, "rsi_%s(con", api->name);
- for (ct2=0; ct2 < api->paramCount; ct2++) {
- const VarType *vt = &api->params[ct2];
- fprintf(f, ",\n cmd->%s", vt->name);
- }
- fprintf(f, ");\n");
+
+ //fprintf(f, " LOGE(\"play command %s\\n\");\n", api->name);
+ fprintf(f, " const RS_CMD_%s *cmd = static_cast<const RS_CMD_%s *>(vp);\n", api->name, api->name);
+ fprintf(f, " ");
+ if (api->ret.typeName[0]) {
+ fprintf(f, "con->mIO.mToCoreRet = (intptr_t)");
}
+ fprintf(f, "rsi_%s(con", api->name);
+ for (ct2=0; ct2 < api->paramCount; ct2++) {
+ const VarType *vt = &api->params[ct2];
+ fprintf(f, ",\n cmd->%s", vt->name);
+ }
+ fprintf(f, ");\n");
+
fprintf(f, "};\n\n");
}
fprintf(f, "RsPlaybackFunc gPlaybackFuncs[%i] = {\n", apiCount + 1);
fprintf(f, " NULL,\n");
for (ct=0; ct < apiCount; ct++) {
- fprintf(f, " %s%s,\n", "rsp_", apis[ct].name);
+ if (apis[ct].direct) {
+ fprintf(f, " NULL,\n");
+ } else {
+ fprintf(f, " %s%s,\n", "rsp_", apis[ct].name);
+ }
}
fprintf(f, "};\n");
diff --git a/libs/rs/spec.h b/libs/rs/spec.h
index 82650a7..ecc5cc7 100644
--- a/libs/rs/spec.h
+++ b/libs/rs/spec.h
@@ -25,7 +25,8 @@
char name[256];
int sync;
int handcodeApi;
- int handcodePlay;
+ int direct;
+ int nocontext;
int paramCount;
VarType ret;
VarType params[16];
diff --git a/libs/rs/spec.l b/libs/rs/spec.l
index c8af891..dcd4435 100644
--- a/libs/rs/spec.l
+++ b/libs/rs/spec.l
@@ -44,6 +44,7 @@
<comment>"*"+"/" BEGIN(INITIAL);
<*>" " //printf("found ' '\n");
+<*>"\t" //printf("found ' '\n");
<*>"\n" ++num_lines; //printf("found lf \n");
{ID} {
@@ -64,8 +65,12 @@
apis[apiCount].handcodeApi = 1;
}
-<api_entry2>"handcodePlay" {
- apis[apiCount].handcodePlay = 1;
+<api_entry2>"direct" {
+ apis[apiCount].direct = 1;
+ }
+
+<api_entry2>"nocontext" {
+ apis[apiCount].nocontext = 1;
}
<api_entry2>"ret" {
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index 08db902..ef4d3d0 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -453,6 +453,10 @@
}
if (left == mNumSampleSizes) {
+ if (flags == kFlagAfter) {
+ return ERROR_OUT_OF_RANGE;
+ }
+
--left;
}
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 4f28855..54c0d77 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -487,14 +487,12 @@
{ "audio/3gpp",
"file:///sdcard/media_api/video/H263_500_AMRNB_12.3gp" },
{ "audio/amr-wb",
- "file:///sdcard/media_api/music_perf/AMRWB/"
- "NIN_AMR-WB_15.85kbps_16kbps.amr" },
+ "file:///sdcard/media_api/music/"
+ "AI_AMR-WB_12.65kbps(13kbps)_16khz_mono_NMC.awb" },
{ "audio/mp4a-latm",
- "file:///sdcard/media_api/music_perf/AAC/"
- "WC_AAC_80kbps_32khz_Stereo_1pCBR_SSE.mp4" },
+ "file:///sdcard/media_api/video/H264_AAC.3gp" },
{ "audio/mpeg",
- "file:///sdcard/media_api/music_perf/MP3/"
- "WC_256kbps_44.1khz_mono_CBR_DPA.mp3" }
+ "file:///sdcard/media_api/music/MP3CBR.mp3" }
};
for (size_t i = 0; i < sizeof(kMimeToURL) / sizeof(kMimeToURL[0]); ++i) {
@@ -626,8 +624,10 @@
requestedSeekTimeUs, requestedSeekTimeUs / 1E6);
}
- MediaBuffer *buffer;
- options.setSeekTo(requestedSeekTimeUs);
+ MediaBuffer *buffer = NULL;
+ options.setSeekTo(
+ requestedSeekTimeUs, MediaSource::ReadOptions::SEEK_NEXT_SYNC);
+
if (seekSource->read(&buffer, &options) != OK) {
CHECK_EQ(buffer, NULL);
actualSeekTimeUs = -1;
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 1ad8047..d96369b 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -642,14 +642,16 @@
}
/**
- * Installs or removes the accessibility input filter when accessibility is enabled
- * or disabled.
+ * Sets the input filter state. If the filter is in enabled it is registered
+ * in the window manager, otherwise the filter is removed from the latter.
+ *
+ * @param enabled Whether the input filter is enabled.
*/
- private void updateInputFilterLocked() {
+ private void setInputFilterEnabledLocked(boolean enabled) {
WindowManagerService wm = (WindowManagerService)ServiceManager.getService(
Context.WINDOW_SERVICE);
if (wm != null) {
- if (mIsEnabled) {
+ if (enabled) {
if (mInputFilter == null) {
mInputFilter = new AccessibilityInputFilter(mContext);
}
@@ -681,7 +683,7 @@
if (enabledServices.size() > 0
&& service.mFeedbackType == AccessibilityServiceInfo.FEEDBACK_SPOKEN) {
updateClientsLocked();
- updateInputFilterLocked();
+ setInputFilterEnabledLocked(true);
}
}
@@ -697,7 +699,7 @@
if (enabledServices.isEmpty()
&& service.mFeedbackType == AccessibilityServiceInfo.FEEDBACK_SPOKEN) {
updateClientsLocked();
- updateInputFilterLocked();
+ setInputFilterEnabledLocked(false);
}
}
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index c4027e0..b2f95cd 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -986,8 +986,16 @@
ssize_t index = mActiveBufferIndex;
if (index >= 0) {
if (!mFailover) {
- Image& texture(mBufferData[index].texture);
- err = mTextureManager.initEglImage(&texture, dpy, buffer);
+ {
+ // Without that lock, there is a chance of race condition
+ // where while composing a specific index, requestBuf
+ // with the same index can be executed and touch the same data
+ // that is being used in initEglImage.
+ // (e.g. dirty flag in texture)
+ Mutex::Autolock _l(mLock);
+ Image& texture(mBufferData[index].texture);
+ err = mTextureManager.initEglImage(&texture, dpy, buffer);
+ }
// if EGLImage fails, we switch to regular texture mode, and we
// free all resources associated with using EGLImages.
if (err == NO_ERROR) {
diff --git a/tests/DumpRenderTree/assets/run_page_cycler.py b/tests/DumpRenderTree/assets/run_page_cycler.py
index 692f32e..f995086 100755
--- a/tests/DumpRenderTree/assets/run_page_cycler.py
+++ b/tests/DumpRenderTree/assets/run_page_cycler.py
@@ -33,10 +33,16 @@
# Include all tests if none are specified.
if not args:
print "need a URL, e.g. file:///sdcard/webkit/page_cycler/moz/start.html\?auto=1\&iterations=10"
+ print " or remote:android-browser-test:80/page_cycler/"
sys.exit(1)
else:
path = ' '.join(args);
+ if path[:7] == "remote:":
+ remote_path = path[7:]
+ else:
+ remote_path = None
+
adb_cmd = "adb ";
if options.adb_options:
adb_cmd += options.adb_options
@@ -56,7 +62,20 @@
run_load_test_cmd_postfix = " -w com.android.dumprendertree/.LayoutTestsAutoRunner"
# Call LoadTestsAutoTest::runTest.
- run_load_test_cmd = run_load_test_cmd_prefix + " -e class com.android.dumprendertree.LoadTestsAutoTest#runPageCyclerTest -e path \"" + path + "\" -e timeout " + timeout_ms
+ run_load_test_cmd = run_load_test_cmd_prefix + " -e class com.android.dumprendertree.LoadTestsAutoTest#runPageCyclerTest -e timeout " + timeout_ms
+
+ if remote_path:
+ if options.suite:
+ run_load_test_cmd += " -e suite %s -e forward %s " % (options.suite,
+ remote_path)
+ else:
+ print "for network mode, need to specify --suite as well."
+ sys.exit(1)
+ if options.iteration:
+ run_load_test_cmd += " -e iteration %s" % options.iteration
+ else:
+ run_load_test_cmd += " -e path \"%s\" " % path
+
if options.drawtime:
run_load_test_cmd += " -e drawtime true "
@@ -130,5 +149,15 @@
default=None,
help="stores rendered page to a location on device.")
+ option_parser.add_option("-u", "--suite",
+ default=None,
+ help="(for network mode) specify the suite to"
+ " run by name")
+
+ option_parser.add_option("-i", "--iteration",
+ default="5",
+ help="(for network mode) specify how many iterations"
+ " to run")
+
options, args = option_parser.parse_args();
main(options, args)
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java
index e058f32..3ba3488 100755
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java
@@ -25,7 +25,7 @@
/**
* Instrumentation Test Runner for all DumpRenderTree tests.
- *
+ *
* Running all tests:
*
* adb shell am instrument \
@@ -57,7 +57,7 @@
e.printStackTrace();
}
}
-
+
String delay_str = (String) icicle.get("delay");
if(delay_str != null) {
try {
@@ -66,30 +66,37 @@
}
}
- String r = (String)icicle.get("rebaseline");
+ String r = icicle.getString("rebaseline");
this.mRebaseline = (r != null && r.toLowerCase().equals("true"));
- String logtime = (String) icicle.get("logtime");
+ String logtime = icicle.getString("logtime");
this.mLogtime = (logtime != null
&& logtime.toLowerCase().equals("true"));
- String drawTime = (String) icicle.get("drawtime");
+ String drawTime = icicle.getString("drawtime");
this.mGetDrawTime = (drawTime != null
&& drawTime.toLowerCase().equals("true"));
- mSaveImagePath = (String) icicle.get("saveimage");
+ mSaveImagePath = icicle.getString("saveimage");
- mJsEngine = (String) icicle.get("jsengine");
+ mJsEngine = icicle.getString("jsengine");
+
+ mPageCyclerSuite = icicle.getString("suite");
+ mPageCyclerForwardHost = icicle.getString("forward");
+ mPageCyclerIteration = icicle.getString("iteration", "5");
super.onCreate(icicle);
}
-
- public String mTestPath;
- public String mSaveImagePath;
- public int mTimeoutInMillis;
- public int mDelay;
- public boolean mRebaseline;
- public boolean mLogtime;
- public boolean mGetDrawTime;
- public String mJsEngine;
+
+ String mPageCyclerSuite;
+ String mPageCyclerForwardHost;
+ String mPageCyclerIteration;
+ String mTestPath;
+ String mSaveImagePath;
+ int mTimeoutInMillis;
+ int mDelay;
+ boolean mRebaseline;
+ boolean mLogtime;
+ boolean mGetDrawTime;
+ String mJsEngine;
}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
index 050b779..7ac0665 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
@@ -401,15 +401,6 @@
activity.setDefaultDumpDataType(DumpDataType.EXT_REPR);
// Run tests.
- int addr = -1;
- try{
- addr = AdbUtils.resolve("android-browser-test.mtv.corp.google.com");
- } catch (IOException ioe) {
- Log.w(LOGTAG, "error while resolving test host name", ioe);
- }
- if(addr == -1) {
- Log.w(LOGTAG, "failed to resolve test host. http tests will fail.");
- }
for (int i = 0; i < mTestList.size(); i++) {
String s = mTestList.elementAt(i);
boolean ignoreResult = mTestListIgnoreResult.elementAt(i);
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
index 622fb0e..ee5bb5d 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
@@ -16,6 +16,9 @@
package com.android.dumprendertree;
+import com.android.dumprendertree.forwarder.AdbUtils;
+import com.android.dumprendertree.forwarder.ForwardServer;
+
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
@@ -34,6 +37,8 @@
import java.io.PrintStream;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
public class LoadTestsAutoTest extends ActivityInstrumentationTestCase2<TestShellActivity> {
@@ -41,13 +46,15 @@
private final static String LOAD_TEST_RESULT =
Environment.getExternalStorageDirectory() + "/load_test_result.txt";
private final static int MAX_GC_WAIT_SEC = 10;
+ private final static int LOCAL_PORT = 17171;
private boolean mFinished;
static final String LOAD_TEST_RUNNER_FILES[] = {
"run_page_cycler.py"
};
+ private ForwardServer mForwardServer;
public LoadTestsAutoTest() {
- super("com.android.dumprendertree", TestShellActivity.class);
+ super(TestShellActivity.class);
}
// This function writes the result of the layout test to
@@ -59,14 +66,38 @@
inst.sendStatus(0, bundle);
}
+ private String setUpForwarding(String forwardInfo, String suite, String iteration) throws IOException {
+ // read forwarding information first
+ Pattern forwardPattern = Pattern.compile("(.*):(\\d+)/(.*)/");
+ Matcher matcher = forwardPattern.matcher(forwardInfo);
+ if (!matcher.matches()) {
+ throw new RuntimeException("Invalid forward information");
+ }
+ String host = matcher.group(1);
+ int port = Integer.parseInt(matcher.group(2));
+ mForwardServer = new ForwardServer(LOCAL_PORT, AdbUtils.resolve(host), port);
+ mForwardServer.start();
+ return String.format("http://127.0.0.1:%d/%s/%s/start.html?auto=1&iterations=%s",
+ LOCAL_PORT, matcher.group(3), suite, iteration);
+ }
+
// Invokes running of layout tests
// and waits till it has finished running.
- public void runPageCyclerTest() {
+ public void runPageCyclerTest() throws IOException {
LayoutTestsAutoRunner runner = (LayoutTestsAutoRunner) getInstrumentation();
+ if (runner.mPageCyclerSuite != null) {
+ // start forwarder to use page cycler suites hosted on external web server
+ if (runner.mPageCyclerForwardHost == null) {
+ throw new RuntimeException("no forwarder information provided");
+ }
+ runner.mTestPath = setUpForwarding(runner.mPageCyclerForwardHost,
+ runner.mPageCyclerSuite, runner.mPageCyclerIteration);
+ Log.d(LOGTAG, "using path: " + runner.mTestPath);
+ }
+
if (runner.mTestPath == null) {
- Log.e(LOGTAG, "No test specified");
- return;
+ throw new RuntimeException("No test specified");
}
TestShellActivity activity = (TestShellActivity) getActivity();
@@ -79,6 +110,10 @@
runner.mGetDrawTime, runner.mSaveImagePath);
activity.clearCache();
+ if (mForwardServer != null) {
+ mForwardServer.stop();
+ mForwardServer = null;
+ }
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
@@ -92,7 +127,9 @@
private void freeMem() {
Log.v(LOGTAG, "freeMem: calling gc...");
final CountDownLatch latch = new CountDownLatch(1);
+ @SuppressWarnings("unused")
Object dummy = new Object() {
+ // this object instance is used to track gc
@Override
protected void finalize() throws Throwable {
latch.countDown();
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java
index a1f3cdf..a971e7b 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java
@@ -36,6 +36,7 @@
private Socket from, to;
private static final String LOGTAG = "Forwarder";
+ private static final int BUFFER_SIZE = 16384;
public Forwarder (Socket from, Socket to, ForwardServer server) {
this.server = server;
@@ -90,7 +91,7 @@
int length;
InputStream is = in.getInputStream();
OutputStream os = out.getOutputStream();
- byte[] buffer = new byte[4096];
+ byte[] buffer = new byte[BUFFER_SIZE];
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index c763b1d..31b2ddd 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -406,6 +406,15 @@
</activity>
<activity
+ android:name="PointsActivity"
+ android:label="_Points">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity
android:name="Transform3dActivity"
android:label="_3d">
<intent-filter>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java
index ccf0631..55fab3f 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java
@@ -42,8 +42,9 @@
swView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
frame.addView(swView);
final LinesView hwBothView = new LinesView(this, 850, Color.GREEN);
- // BUG: some lines not drawn or drawn with alpha when enabling hw layers
-// hwBothView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ // Don't actually need to render to a hw layer, but it's a good sanity-check that
+ // we're rendering to/from layers correctly
+ hwBothView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
frame.addView(hwBothView);
final LinesView swBothView = new LinesView(this, 854, Color.RED);
swBothView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PointsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PointsActivity.java
new file mode 100644
index 0000000..b3fb7a1
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PointsActivity.java
@@ -0,0 +1,128 @@
+/*
+ * 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.test.hwui;
+
+import android.animation.ObjectAnimator;
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.drawable.ColorDrawable;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+import android.widget.SeekBar;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class PointsActivity extends Activity {
+
+ float mSeekValue = .5f;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getWindow().setBackgroundDrawable(new ColorDrawable(0xff000000));
+ SeekBar slider = new SeekBar(this);
+ LinearLayout container = new LinearLayout(this);
+ container.setOrientation(LinearLayout.VERTICAL);
+ setContentView(container);
+
+ container.addView(slider);
+ slider.setMax(100);
+ slider.setProgress(50);
+ FrameLayout frame = new FrameLayout(this);
+ final RenderingView gpuView = new RenderingView(this, Color.GREEN);
+ frame.addView(gpuView);
+ final RenderingView swView = new RenderingView(this, Color.RED);
+ swView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+ frame.addView(swView);
+ container.addView(frame);
+
+ slider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ mSeekValue = (float)progress / 100.0f;
+ float gpuAlpha = Math.min(2.0f * mSeekValue, 1f);
+ gpuView.setAlpha(gpuAlpha);
+ float swAlpha = Math.min((1 - mSeekValue) * 2.0f, 1f);
+ System.out.println("(gpuAlpha, swAlpha = " + gpuAlpha + ", " + swAlpha);
+ swView.setAlpha(swAlpha);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+ });
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ }
+
+ public static class RenderingView extends View {
+
+ private int mColor;
+
+ public RenderingView(Context c, int color) {
+ super(c);
+ mColor = color;
+ }
+
+ private void drawPoints(Canvas canvas, Paint p, float xOffset, float yOffset) {
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ Paint p = new Paint();
+ p.setColor(mColor);
+
+ float yOffset = 0;
+ for (int i = 0; i < 2; ++i) {
+ float xOffset = 0;
+
+ p.setStrokeWidth(0f);
+ p.setStrokeCap(Paint.Cap.SQUARE);
+ canvas.drawPoint(100 + xOffset, 100 + yOffset, p);
+ xOffset += 5;
+
+ p.setStrokeWidth(1f);
+ canvas.drawPoint(100 + xOffset, 100 + yOffset, p);
+ xOffset += 15;
+
+ p.setStrokeWidth(20);
+ canvas.drawPoint(100 + xOffset, 100 + yOffset, p);
+ xOffset += 30;
+
+ p.setStrokeCap(Paint.Cap.ROUND);
+ canvas.drawPoint(100 + xOffset, 100 + yOffset, p);
+
+ p.setAntiAlias(true);
+ yOffset += 30;
+ }
+
+ }
+ }
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
index 7462701..e776463 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
@@ -88,9 +88,8 @@
}
// This is a hack to work around an invalidation bug
- mBitmapOut = Bitmap.createBitmap(mBitmapOut);
+ mBitmapOut.setPixel(0, 0, 0);
mOutPixelsAllocation.copyTo(mBitmapOut);
- mDisplayView.setImageBitmap(mBitmapOut);
mDisplayView.invalidate();
}
};