diff options
75 files changed, 915 insertions, 134 deletions
diff --git a/api/current.xml b/api/current.xml index 3f8b5fe..7eef62f 100644 --- a/api/current.xml +++ b/api/current.xml @@ -94481,6 +94481,17 @@ visibility="public" > </method> +<method name="getSerial" + return="java.lang.String" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="getUri" return="java.lang.String" abstract="false" @@ -267064,7 +267075,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="arg0" type="T"> +<parameter name="t" type="T"> </parameter> </method> </interface> diff --git a/core/java/android/hardware/usb/UsbAccessory.java b/core/java/android/hardware/usb/UsbAccessory.java index cc174d4..5e9ead0 100644 --- a/core/java/android/hardware/usb/UsbAccessory.java +++ b/core/java/android/hardware/usb/UsbAccessory.java @@ -33,18 +33,20 @@ public class UsbAccessory implements Parcelable { private final String mDescription; private final String mVersion; private final String mUri; + private final String mSerial; /** * UsbAccessory should only be instantiated by UsbService implementation * @hide */ public UsbAccessory(String manufacturer, String model, String description, - String version, String uri) { + String version, String uri, String serial) { mManufacturer = manufacturer; mModel = model; mDescription = description; mVersion = version; mUri = uri; + mSerial = serial; } /** @@ -57,6 +59,7 @@ public class UsbAccessory implements Parcelable { mDescription = strings[2]; mVersion = strings[3]; mUri = strings[4]; + mSerial = strings[5]; } /** @@ -106,6 +109,17 @@ public class UsbAccessory implements Parcelable { return mUri; } + /** + * Returns the unique serial number for the accessory. + * This is an optional serial number that can be used to differentiate + * between individual accessories of the same model and manufacturer + * + * @return the unique serial number + */ + public String getSerial() { + return mSerial; + } + private static boolean compare(String s1, String s2) { if (s1 == null) return (s2 == null); return s1.equals(s2); @@ -119,7 +133,8 @@ public class UsbAccessory implements Parcelable { compare(mModel, accessory.getModel()) && compare(mDescription, accessory.getDescription()) && compare(mVersion, accessory.getVersion()) && - compare(mUri, accessory.getUri())); + compare(mUri, accessory.getUri()) && + compare(mSerial, accessory.getSerial())); } return false; } @@ -130,7 +145,8 @@ public class UsbAccessory implements Parcelable { (mModel == null ? 0 : mModel.hashCode()) ^ (mDescription == null ? 0 : mDescription.hashCode()) ^ (mVersion == null ? 0 : mVersion.hashCode()) ^ - (mUri == null ? 0 : mUri.hashCode())); + (mUri == null ? 0 : mUri.hashCode()) ^ + (mSerial == null ? 0 : mSerial.hashCode())); } @Override @@ -139,7 +155,8 @@ public class UsbAccessory implements Parcelable { ", mModel=" + mModel + ", mDescription=" + mDescription + ", mVersion=" + mVersion + - ", mUri=" + mUri + "]"; + ", mUri=" + mUri + + ", mSerial=" + mSerial + "]"; } public static final Parcelable.Creator<UsbAccessory> CREATOR = @@ -150,7 +167,8 @@ public class UsbAccessory implements Parcelable { String description = in.readString(); String version = in.readString(); String uri = in.readString(); - return new UsbAccessory(manufacturer, model, description, version, uri); + String serial = in.readString(); + return new UsbAccessory(manufacturer, model, description, version, uri, serial); } public UsbAccessory[] newArray(int size) { @@ -168,5 +186,6 @@ public class UsbAccessory implements Parcelable { parcel.writeString(mDescription); parcel.writeString(mVersion); parcel.writeString(mUri); + parcel.writeString(mSerial); } } diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index fa5479b..14f2e9d 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -245,12 +245,13 @@ class GLES20Canvas extends HardwareCanvas { private static native void nDestroyDisplayList(int displayList); @Override - public boolean drawDisplayList(DisplayList displayList, Rect dirty) { + public boolean drawDisplayList(DisplayList displayList, int width, int height, Rect dirty) { return nDrawDisplayList(mRenderer, - ((GLES20DisplayList) displayList).mNativeDisplayList, dirty); + ((GLES20DisplayList) displayList).mNativeDisplayList, width, height, dirty); } - private static native boolean nDrawDisplayList(int renderer, int displayList, Rect dirty); + private static native boolean nDrawDisplayList(int renderer, int displayList, + int width, int height, Rect dirty); /////////////////////////////////////////////////////////////////////////// // Hardware layer diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java index cb1003a..caa7b74 100644 --- a/core/java/android/view/HardwareCanvas.java +++ b/core/java/android/view/HardwareCanvas.java @@ -53,13 +53,15 @@ public abstract class HardwareCanvas extends Canvas { * Draws the specified display list onto this canvas. * * @param displayList The display list to replay. + * @param width The width of the display list. + * @param height The height of the display list. * @param dirty The dirty region to redraw in the next pass, matters only * if this method returns true, can be null. * * @return True if the content of the display list requires another * drawing pass (invalidate()), false otherwise */ - abstract boolean drawDisplayList(DisplayList displayList, Rect dirty); + abstract boolean drawDisplayList(DisplayList displayList, int width, int height, Rect dirty); /** * Draws the specified layer onto this canvas. diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 0cf7ae6..8584bf2 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -608,7 +608,8 @@ public abstract class HardwareRenderer { DisplayList displayList = view.getDisplayList(); if (displayList != null) { - if (canvas.drawDisplayList(displayList, mRedrawClip)) { + if (canvas.drawDisplayList(displayList, view.getWidth(), + view.getHeight(), mRedrawClip)) { if (mRedrawClip.isEmpty() || view.getParent() == null) { view.invalidate(); } else { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 32c9e27..5a96efd 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -59,7 +59,6 @@ import android.util.Pools; import android.util.SparseArray; import android.util.TypedValue; import android.view.ContextMenu.ContextMenuInfo; -import android.view.View.MeasureSpec; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityEventSource; import android.view.accessibility.AccessibilityManager; @@ -4651,6 +4650,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility * @return True if the event was handled by the view, false otherwise. */ public boolean dispatchGenericMotionEvent(MotionEvent event) { + //noinspection SimplifiableIfStatement if (mOnGenericMotionListener != null && (mViewFlags & ENABLED_MASK) == ENABLED && mOnGenericMotionListener.onGenericMotion(this, event)) { return true; @@ -9326,7 +9326,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility } final ScrollabilityCache scrollabilityCache = mScrollCache; - int length = scrollabilityCache.fadingEdgeLength; + final float fadeHeight = scrollabilityCache.fadingEdgeLength; + int length = (int) fadeHeight; // clip the fade length if top and bottom fades overlap // overlapping fades produce odd-looking artifacts @@ -9341,16 +9342,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility if (verticalEdges) { topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength())); - drawTop = topFadeStrength > 0.0f; + drawTop = topFadeStrength * fadeHeight > 1.0f; bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength())); - drawBottom = bottomFadeStrength > 0.0f; + drawBottom = bottomFadeStrength * fadeHeight > 1.0f; } if (horizontalEdges) { leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength())); - drawLeft = leftFadeStrength > 0.0f; + drawLeft = leftFadeStrength * fadeHeight > 1.0f; rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength())); - drawRight = rightFadeStrength > 0.0f; + drawRight = rightFadeStrength * fadeHeight > 1.0f; } saveCount = canvas.getSaveCount(); @@ -9388,7 +9389,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility final Paint p = scrollabilityCache.paint; final Matrix matrix = scrollabilityCache.matrix; final Shader fade = scrollabilityCache.shader; - final float fadeHeight = scrollabilityCache.fadingEdgeLength; if (drawTop) { matrix.setScale(1, fadeHeight * topFadeStrength); @@ -9438,6 +9438,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility * * @return The known solid color background for this view, or 0 if the color may vary */ + @ViewDebug.ExportedProperty(category = "drawing") public int getSolidColor() { return 0; } @@ -11644,6 +11645,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility * @return true if scrolling was clamped to an over-scroll boundary along either * axis, false otherwise. */ + @SuppressWarnings({"UnusedParameters"}) protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index f9692da..8dc86ac 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -2585,7 +2585,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } } else { child.mPrivateFlags &= ~DIRTY_MASK; - ((HardwareCanvas) canvas).drawDisplayList(displayList, null); + ((HardwareCanvas) canvas).drawDisplayList(displayList, cr - cl, cb - ct, null); } } } else if (cache != null) { diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 4aa1f5e..1a574d5 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -5384,7 +5384,8 @@ public class WebView extends AbsoluteLayout private boolean shouldForwardTouchEvent() { return mFullScreenHolder != null || (mForwardTouchEvents && !mSelectingText - && mPreventDefault != PREVENT_DEFAULT_IGNORE); + && mPreventDefault != PREVENT_DEFAULT_IGNORE + && mPreventDefault != PREVENT_DEFAULT_NO); } private boolean inFullScreenMode() { diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index eca39fc..d39271e 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -5226,6 +5226,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * * @return The cache color hint */ + @ViewDebug.ExportedProperty(category = "drawing") public int getCacheColorHint() { return mCacheColorHint; } diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp index 0ea8225..7fdad10 100644 --- a/core/jni/android/graphics/Shader.cpp +++ b/core/jni/android/graphics/Shader.cpp @@ -119,7 +119,7 @@ static SkShader* LinearGradient_create1(JNIEnv* env, jobject o, const jint* colorValues = env->GetIntArrayElements(colorArray, NULL); SkAutoSTMalloc<8, SkScalar> storage(posArray ? count : 0); - SkScalar* pos = NULL; + SkScalar* pos = NULL; if (posArray) { AutoJavaFloatArray autoPos(env, posArray, count); @@ -164,7 +164,11 @@ static SkiaShader* LinearGradient_postCreate1(JNIEnv* env, jobject o, SkShader* } } else { storedPositions[0] = 0.0f; - storedPositions[1] = 1.0f; + const jfloat step = 1.0f / (count - 1); + for (size_t i = 1; i < count - 1; i++) { + storedPositions[i] = step * i; + } + storedPositions[count - 1] = 1.0f; } SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors, @@ -289,7 +293,11 @@ static SkiaShader* RadialGradient_postCreate1(JNIEnv* env, jobject o, SkShader* } } else { storedPositions[0] = 0.0f; - storedPositions[1] = 1.0f; + const jfloat step = 1.0f / (count - 1); + for (size_t i = 1; i < count - 1; i++) { + storedPositions[i] = step * i; + } + storedPositions[count - 1] = 1.0f; } SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors, @@ -384,7 +392,11 @@ static SkiaShader* SweepGradient_postCreate1(JNIEnv* env, jobject o, SkShader* s } } else { storedPositions[0] = 0.0f; - storedPositions[1] = 1.0f; + const jfloat step = 1.0f / (count - 1); + for (size_t i = 1; i < count - 1; i++) { + storedPositions[i] = step * i; + } + storedPositions[count - 1] = 1.0f; } SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, count, diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index a78f660..5116f09 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -498,9 +498,10 @@ static void android_view_GLES20Canvas_destroyDisplayList(JNIEnv* env, } static bool android_view_GLES20Canvas_drawDisplayList(JNIEnv* env, - jobject clazz, OpenGLRenderer* renderer, DisplayList* displayList, jobject dirty) { + jobject clazz, OpenGLRenderer* renderer, DisplayList* displayList, + jint width, jint height, jobject dirty) { android::uirenderer::Rect bounds; - bool redraw = renderer->drawDisplayList(displayList, bounds); + bool redraw = renderer->drawDisplayList(displayList, width, height, bounds); if (redraw && dirty != NULL) { env->CallVoidMethod(dirty, gRectClassInfo.set, int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom)); @@ -664,7 +665,7 @@ static JNINativeMethod gMethods[] = { { "nGetDisplayList", "(I)I", (void*) android_view_GLES20Canvas_getDisplayList }, { "nDestroyDisplayList", "(I)V", (void*) android_view_GLES20Canvas_destroyDisplayList }, { "nGetDisplayListRenderer", "(I)I", (void*) android_view_GLES20Canvas_getDisplayListRenderer }, - { "nDrawDisplayList", "(IILandroid/graphics/Rect;)Z", + { "nDrawDisplayList", "(IIIILandroid/graphics/Rect;)Z", (void*) android_view_GLES20Canvas_drawDisplayList }, { "nInterrupt", "(I)V", (void*) android_view_GLES20Canvas_interrupt }, diff --git a/core/res/res/drawable-hdpi/ic_media_embed_play.png b/core/res/res/drawable-hdpi/ic_media_embed_play.png Binary files differindex e67ec80..23ac7e4 100644 --- a/core/res/res/drawable-hdpi/ic_media_embed_play.png +++ b/core/res/res/drawable-hdpi/ic_media_embed_play.png diff --git a/core/res/res/drawable-hdpi/ic_media_ff.png b/core/res/res/drawable-hdpi/ic_media_ff.png Binary files differindex b0dc05b..a892ba2 100644 --- a/core/res/res/drawable-hdpi/ic_media_ff.png +++ b/core/res/res/drawable-hdpi/ic_media_ff.png diff --git a/core/res/res/drawable-hdpi/ic_media_fullscreen.png b/core/res/res/drawable-hdpi/ic_media_fullscreen.png Binary files differindex 3f26e45..0cdbf77 100644 --- a/core/res/res/drawable-hdpi/ic_media_fullscreen.png +++ b/core/res/res/drawable-hdpi/ic_media_fullscreen.png diff --git a/core/res/res/drawable-hdpi/ic_media_next.png b/core/res/res/drawable-hdpi/ic_media_next.png Binary files differindex 2552f4e..2285670 100644 --- a/core/res/res/drawable-hdpi/ic_media_next.png +++ b/core/res/res/drawable-hdpi/ic_media_next.png diff --git a/core/res/res/drawable-hdpi/ic_media_pause.png b/core/res/res/drawable-hdpi/ic_media_pause.png Binary files differindex d4670c2..ffb55cd 100644 --- a/core/res/res/drawable-hdpi/ic_media_pause.png +++ b/core/res/res/drawable-hdpi/ic_media_pause.png diff --git a/core/res/res/drawable-hdpi/ic_media_play.png b/core/res/res/drawable-hdpi/ic_media_play.png Binary files differindex e67ec80..e525bd2 100644 --- a/core/res/res/drawable-hdpi/ic_media_play.png +++ b/core/res/res/drawable-hdpi/ic_media_play.png diff --git a/core/res/res/drawable-hdpi/ic_media_previous.png b/core/res/res/drawable-hdpi/ic_media_previous.png Binary files differindex 05eba71..3333711 100644 --- a/core/res/res/drawable-hdpi/ic_media_previous.png +++ b/core/res/res/drawable-hdpi/ic_media_previous.png diff --git a/core/res/res/drawable-hdpi/ic_media_rew.png b/core/res/res/drawable-hdpi/ic_media_rew.png Binary files differindex 88eed2e..b14e9b9 100644 --- a/core/res/res/drawable-hdpi/ic_media_rew.png +++ b/core/res/res/drawable-hdpi/ic_media_rew.png diff --git a/core/res/res/drawable-hdpi/ic_paste_bubble_disabled_holo.png b/core/res/res/drawable-hdpi/ic_paste_bubble_disabled_holo.png Binary files differnew file mode 100644 index 0000000..42ac16b --- /dev/null +++ b/core/res/res/drawable-hdpi/ic_paste_bubble_disabled_holo.png diff --git a/core/res/res/drawable-hdpi/ic_paste_bubble_holo_disabled.png b/core/res/res/drawable-hdpi/ic_paste_bubble_holo_disabled.png Binary files differdeleted file mode 100644 index 15bd8b2..0000000 --- a/core/res/res/drawable-hdpi/ic_paste_bubble_holo_disabled.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/ic_media_embed_play.png b/core/res/res/drawable-mdpi/ic_media_embed_play.png Binary files differindex 41cd65f..fc5d8c6 100644 --- a/core/res/res/drawable-mdpi/ic_media_embed_play.png +++ b/core/res/res/drawable-mdpi/ic_media_embed_play.png diff --git a/core/res/res/drawable-mdpi/ic_media_ff.png b/core/res/res/drawable-mdpi/ic_media_ff.png Binary files differindex d99779d..892772e 100644 --- a/core/res/res/drawable-mdpi/ic_media_ff.png +++ b/core/res/res/drawable-mdpi/ic_media_ff.png diff --git a/core/res/res/drawable-mdpi/ic_media_fullscreen.png b/core/res/res/drawable-mdpi/ic_media_fullscreen.png Binary files differindex 24fb6d6..1c60e15 100644 --- a/core/res/res/drawable-mdpi/ic_media_fullscreen.png +++ b/core/res/res/drawable-mdpi/ic_media_fullscreen.png diff --git a/core/res/res/drawable-mdpi/ic_media_next.png b/core/res/res/drawable-mdpi/ic_media_next.png Binary files differindex cee4930..bbe311b 100644 --- a/core/res/res/drawable-mdpi/ic_media_next.png +++ b/core/res/res/drawable-mdpi/ic_media_next.png diff --git a/core/res/res/drawable-mdpi/ic_media_pause.png b/core/res/res/drawable-mdpi/ic_media_pause.png Binary files differindex 9e8b675..e4e8d86 100644 --- a/core/res/res/drawable-mdpi/ic_media_pause.png +++ b/core/res/res/drawable-mdpi/ic_media_pause.png diff --git a/core/res/res/drawable-mdpi/ic_media_play.png b/core/res/res/drawable-mdpi/ic_media_play.png Binary files differindex 41cd65f..8eaf962 100644 --- a/core/res/res/drawable-mdpi/ic_media_play.png +++ b/core/res/res/drawable-mdpi/ic_media_play.png diff --git a/core/res/res/drawable-mdpi/ic_media_previous.png b/core/res/res/drawable-mdpi/ic_media_previous.png Binary files differindex 1be95b4..e9abc7f 100644 --- a/core/res/res/drawable-mdpi/ic_media_previous.png +++ b/core/res/res/drawable-mdpi/ic_media_previous.png diff --git a/core/res/res/drawable-mdpi/ic_media_rew.png b/core/res/res/drawable-mdpi/ic_media_rew.png Binary files differindex 8311508..a5eb94a 100644 --- a/core/res/res/drawable-mdpi/ic_media_rew.png +++ b/core/res/res/drawable-mdpi/ic_media_rew.png diff --git a/core/res/res/drawable-mdpi/ic_paste_bubble_disabled_holo.png b/core/res/res/drawable-mdpi/ic_paste_bubble_disabled_holo.png Binary files differnew file mode 100644 index 0000000..ce6bd86 --- /dev/null +++ b/core/res/res/drawable-mdpi/ic_paste_bubble_disabled_holo.png diff --git a/core/res/res/drawable-mdpi/ic_paste_bubble_holo_disabled.png b/core/res/res/drawable-mdpi/ic_paste_bubble_holo_disabled.png Binary files differdeleted file mode 100644 index e483e84..0000000 --- a/core/res/res/drawable-mdpi/ic_paste_bubble_holo_disabled.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png Binary files differindex b7413b3..62e3274 100644 --- a/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png Binary files differindex 82e7a03..b7512fa 100644 --- a/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png +++ b/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/textfield_search_right_default_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_search_right_default_holo_dark.9.png Binary files differindex 4b0ea21..bfc6f83 100644 --- a/core/res/res/drawable-mdpi/textfield_search_right_default_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/textfield_search_right_default_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/textfield_search_right_default_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_search_right_default_holo_light.9.png Binary files differindex e87591c..708ba90 100644 --- a/core/res/res/drawable-mdpi/textfield_search_right_default_holo_light.9.png +++ b/core/res/res/drawable-mdpi/textfield_search_right_default_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_dark.9.png Binary files differindex 14f69b1..0da1e9c 100644 --- a/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_light.9.png Binary files differindex 85329ca..2e93557 100644 --- a/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_light.9.png +++ b/core/res/res/drawable-mdpi/textfield_search_right_selected_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/textfield_search_selected_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_search_selected_holo_dark.9.png Binary files differindex 7e130d9..7aeaad6 100644 --- a/core/res/res/drawable-mdpi/textfield_search_selected_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/textfield_search_selected_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/textfield_search_selected_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_search_selected_holo_light.9.png Binary files differindex 050d1c0..cf46f32 100644 --- a/core/res/res/drawable-mdpi/textfield_search_selected_holo_light.9.png +++ b/core/res/res/drawable-mdpi/textfield_search_selected_holo_light.9.png diff --git a/core/res/res/layout/text_edit_no_paste_window.xml b/core/res/res/layout/text_edit_no_paste_window.xml index f804986..98b16e2 100644 --- a/core/res/res/layout/text_edit_no_paste_window.xml +++ b/core/res/res/layout/text_edit_no_paste_window.xml @@ -25,7 +25,7 @@ android:paddingRight="16dip" android:paddingTop="8dip" android:paddingBottom="8dip" - android:drawableLeft="@android:drawable/ic_paste_bubble_holo_disabled" + android:drawableLeft="@android:drawable/ic_paste_bubble_disabled_holo" android:drawablePadding="8dip" android:gravity="center" android:textAppearance="?android:attr/textAppearanceMediumInverse" diff --git a/core/res/res/layout/text_edit_side_no_paste_window.xml b/core/res/res/layout/text_edit_side_no_paste_window.xml index 903bcb6..3eb41fb 100644 --- a/core/res/res/layout/text_edit_side_no_paste_window.xml +++ b/core/res/res/layout/text_edit_side_no_paste_window.xml @@ -25,7 +25,7 @@ android:paddingRight="16dip" android:paddingTop="8dip" android:paddingBottom="8dip" - android:drawableLeft="@android:drawable/ic_paste_bubble_holo_disabled" + android:drawableLeft="@android:drawable/ic_paste_bubble_disabled_holo" android:drawablePadding="8dip" android:gravity="center" android:textAppearance="?android:attr/textAppearanceMediumInverse" diff --git a/data/fonts/DroidSans-Bold.ttf b/data/fonts/DroidSans-Bold.ttf Binary files differindex 7ac04b6..d065b64 100644 --- a/data/fonts/DroidSans-Bold.ttf +++ b/data/fonts/DroidSans-Bold.ttf diff --git a/data/fonts/DroidSans.ttf b/data/fonts/DroidSans.ttf Binary files differindex 767c63a..ad1efca 100644 --- a/data/fonts/DroidSans.ttf +++ b/data/fonts/DroidSans.ttf diff --git a/data/fonts/DroidSansArabic.ttf b/data/fonts/DroidSansArabic.ttf Binary files differindex 660e2a9..bdefaac 100644 --- a/data/fonts/DroidSansArabic.ttf +++ b/data/fonts/DroidSansArabic.ttf diff --git a/data/fonts/DroidSansFallback.ttf b/data/fonts/DroidSansFallback.ttf Binary files differindex 8c6fabe..ba9d76f 100644 --- a/data/fonts/DroidSansFallback.ttf +++ b/data/fonts/DroidSansFallback.ttf diff --git a/data/fonts/DroidSansMono.ttf b/data/fonts/DroidSansMono.ttf Binary files differindex 6e79dad..a007071 100644 --- a/data/fonts/DroidSansMono.ttf +++ b/data/fonts/DroidSansMono.ttf diff --git a/data/fonts/DroidSerif-Bold.ttf b/data/fonts/DroidSerif-Bold.ttf Binary files differindex 85d6c6b..838d255 100644 --- a/data/fonts/DroidSerif-Bold.ttf +++ b/data/fonts/DroidSerif-Bold.ttf diff --git a/data/fonts/DroidSerif-BoldItalic.ttf b/data/fonts/DroidSerif-BoldItalic.ttf Binary files differindex 9d8e798..0b1601f 100644 --- a/data/fonts/DroidSerif-BoldItalic.ttf +++ b/data/fonts/DroidSerif-BoldItalic.ttf diff --git a/data/fonts/DroidSerif-Italic.ttf b/data/fonts/DroidSerif-Italic.ttf Binary files differindex 6acc86d..2972809 100644 --- a/data/fonts/DroidSerif-Italic.ttf +++ b/data/fonts/DroidSerif-Italic.ttf diff --git a/data/fonts/DroidSerif-Regular.ttf b/data/fonts/DroidSerif-Regular.ttf Binary files differindex 8c1c2c4..5b4fe81 100644 --- a/data/fonts/DroidSerif-Regular.ttf +++ b/data/fonts/DroidSerif-Regular.ttf diff --git a/docs/html/index.jd b/docs/html/index.jd index f1bb59f..7fcd7b6 100644 --- a/docs/html/index.jd +++ b/docs/html/index.jd @@ -13,7 +13,7 @@ home=true <!-- total max width is 520px --> <img src="{@docRoot}assets/images/home/GDC2011.png" alt="Android at GDC 2011" width="203px" style="padding-left:22px;padding-bottom:28px;padding-top:22px;"/> <div id="announcement" style="width:275px"> - <p>Android will be at the <a href="http://www.gdconf.com/">2011 Game Developers Conference</a> in San Francisco, from March 1st to 4th. We're looking forward to seeing you there!</p> + <p>Thanks to everyone who visited us at the <a href="http://www.gdconf.com/">Game Developers Conference</a> in San Francisco. We're looking forward to seeing your games running on Android!</p> <p><a href="http://android-developers.blogspot.com/2011/02/heading-for-gdc.html">Learn more »</a></p> </div> <!-- end annoucement --> </div> <!-- end annoucement-block --> diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp index 3bed959..5c6d71b 100644 --- a/libs/gui/SurfaceTexture.cpp +++ b/libs/gui/SurfaceTexture.cpp @@ -283,11 +283,42 @@ void SurfaceTexture::getTransformMatrix(float mtx[16]) { sp<GraphicBuffer>& buf(mSlots[mCurrentTexture].mGraphicBuffer); float tx, ty, sx, sy; if (!mCurrentCrop.isEmpty()) { - tx = float(mCurrentCrop.left) / float(buf->getWidth()); - ty = float(buf->getHeight() - mCurrentCrop.bottom) / - float(buf->getHeight()); - sx = float(mCurrentCrop.width()) / float(buf->getWidth()); - sy = float(mCurrentCrop.height()) / float(buf->getHeight()); + // In order to prevent bilinear sampling at the of the crop rectangle we + // may need to shrink it by 2 texels in each direction. Normally this + // would just need to take 1/2 a texel off each end, but because the + // chroma channels will likely be subsampled we need to chop off a whole + // texel. This will cause artifacts if someone does nearest sampling + // with 1:1 pixel:texel ratio, but it's impossible to simultaneously + // accomodate the bilinear and nearest sampling uses. + // + // If nearest sampling turns out to be a desirable usage of these + // textures then we could add the ability to switch a SurfaceTexture to + // nearest-mode. Preferably, however, the image producers (video + // decoder, camera, etc.) would simply not use a crop rectangle (or at + // least not tell the framework about it) so that the GPU can do the + // correct edge behavior. + int xshrink = 0, yshrink = 0; + if (mCurrentCrop.left > 0) { + tx = float(mCurrentCrop.left + 1) / float(buf->getWidth()); + xshrink++; + } else { + tx = 0.0f; + } + if (mCurrentCrop.right < buf->getWidth()) { + xshrink++; + } + if (mCurrentCrop.bottom < buf->getHeight()) { + ty = (float(buf->getHeight() - mCurrentCrop.bottom) + 1.0f) / + float(buf->getHeight()); + yshrink++; + } else { + ty = 0.0f; + } + if (mCurrentCrop.top > 0) { + yshrink++; + } + sx = float(mCurrentCrop.width() - xshrink) / float(buf->getWidth()); + sy = float(mCurrentCrop.height() - yshrink) / float(buf->getHeight()); } else { tx = 0.0f; ty = 0.0f; @@ -298,7 +329,7 @@ void SurfaceTexture::getTransformMatrix(float mtx[16]) { sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, 1, 0, - sx*tx, sy*ty, 0, 1, + tx, ty, 0, 1, }; float mtxBeforeFlipV[16]; diff --git a/libs/gui/tests/Android.mk b/libs/gui/tests/Android.mk index 1dd8885..7516299 100644 --- a/libs/gui/tests/Android.mk +++ b/libs/gui/tests/Android.mk @@ -4,39 +4,37 @@ include $(CLEAR_VARS) ifneq ($(TARGET_SIMULATOR),true) -# Build the unit tests. -test_src_files := \ +LOCAL_MODULE := SurfaceTexture_test + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := \ SurfaceTextureClient_test.cpp \ + SurfaceTexture_test.cpp \ -shared_libraries := \ - libcutils \ - libutils \ +LOCAL_SHARED_LIBRARIES := \ + libEGL \ + libGLESv2 \ + libandroid \ libbinder \ + libcutils \ libgui \ libstlport \ + libsurfaceflinger_client \ + libui \ + libutils \ -static_libraries := \ +LOCAL_STATIC_LIBRARIES := \ libgtest \ libgtest_main \ -c_includes := \ +LOCAL_C_INCLUDES := \ bionic \ bionic/libstdc++/include \ external/gtest/include \ external/stlport/stlport \ -module_tags := tests - -$(foreach file,$(test_src_files), \ - $(eval include $(CLEAR_VARS)) \ - $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \ - $(eval LOCAL_STATIC_LIBRARIES := $(static_libraries)) \ - $(eval LOCAL_C_INCLUDES := $(c_includes)) \ - $(eval LOCAL_SRC_FILES := $(file)) \ - $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \ - $(eval LOCAL_MODULE_TAGS := $(module_tags)) \ - $(eval include $(BUILD_EXECUTABLE)) \ -) +include $(BUILD_EXECUTABLE) # Build the manual test programs. include $(call all-subdir-makefiles) diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp new file mode 100644 index 0000000..4184463 --- /dev/null +++ b/libs/gui/tests/SurfaceTexture_test.cpp @@ -0,0 +1,621 @@ +/* + * 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. + */ + +#include <gtest/gtest.h> +#include <gui/SurfaceTexture.h> +#include <gui/SurfaceTextureClient.h> +#include <ui/GraphicBuffer.h> +#include <utils/String8.h> + +#include <surfaceflinger/ISurfaceComposer.h> +#include <surfaceflinger/Surface.h> +#include <surfaceflinger/SurfaceComposerClient.h> + +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +#include <ui/FramebufferNativeWindow.h> + +namespace android { + +class GLTest : public ::testing::Test { +protected: + + GLTest(): + mEglDisplay(EGL_NO_DISPLAY), + mEglSurface(EGL_NO_SURFACE), + mEglContext(EGL_NO_CONTEXT) { + } + + virtual void SetUp() { + EGLBoolean returnValue; + + mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay); + + EGLint majorVersion; + EGLint minorVersion; + EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion)); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + RecordProperty("EglVersionMajor", majorVersion); + RecordProperty("EglVersionMajor", minorVersion); + + EGLConfig myConfig = {0}; + EGLint numConfigs = 0; + EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &myConfig, + 1, &numConfigs)); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + + char* displaySecsEnv = getenv("GLTEST_DISPLAY_SECS"); + if (displaySecsEnv != NULL) { + mDisplaySecs = atoi(displaySecsEnv); + if (mDisplaySecs < 0) { + mDisplaySecs = 0; + } + } else { + mDisplaySecs = 0; + } + + if (mDisplaySecs > 0) { + mComposerClient = new SurfaceComposerClient; + ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); + + mSurfaceControl = mComposerClient->createSurface(getpid(), + String8("Test Surface"), 0, + getSurfaceWidth(), getSurfaceHeight(), + PIXEL_FORMAT_RGB_888, 0); + + ASSERT_TRUE(mSurfaceControl != NULL); + ASSERT_TRUE(mSurfaceControl->isValid()); + + ASSERT_EQ(NO_ERROR, mComposerClient->openTransaction()); + ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(30000)); + ASSERT_EQ(NO_ERROR, mSurfaceControl->show()); + ASSERT_EQ(NO_ERROR, mComposerClient->closeTransaction()); + + sp<ANativeWindow> window = mSurfaceControl->getSurface(); + mEglSurface = eglCreateWindowSurface(mEglDisplay, myConfig, + window.get(), NULL); + } else { + EGLint pbufferAttribs[] = { + EGL_WIDTH, getSurfaceWidth(), + EGL_HEIGHT, getSurfaceHeight(), + EGL_NONE }; + + mEglSurface = eglCreatePbufferSurface(mEglDisplay, myConfig, + pbufferAttribs); + } + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + ASSERT_NE(EGL_NO_SURFACE, mEglSurface); + + mEglContext = eglCreateContext(mEglDisplay, myConfig, EGL_NO_CONTEXT, + getContextAttribs()); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + ASSERT_NE(EGL_NO_CONTEXT, mEglContext); + + EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, + mEglContext)); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + + EGLint w, h; + EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &w)); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &h)); + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + RecordProperty("EglSurfaceWidth", w); + RecordProperty("EglSurfaceHeight", h); + + glViewport(0, 0, w, h); + ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); + } + + virtual void TearDown() { + // Display the result + if (mDisplaySecs > 0 && mEglSurface != EGL_NO_SURFACE) { + eglSwapBuffers(mEglDisplay, mEglSurface); + sleep(mDisplaySecs); + } + + if (mComposerClient != NULL) { + mComposerClient->dispose(); + } + if (mEglContext != EGL_NO_CONTEXT) { + eglDestroyContext(mEglDisplay, mEglContext); + } + if (mEglSurface != EGL_NO_SURFACE) { + eglDestroySurface(mEglDisplay, mEglSurface); + } + if (mEglDisplay != EGL_NO_DISPLAY) { + eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + eglTerminate(mEglDisplay); + } + ASSERT_EQ(EGL_SUCCESS, eglGetError()); + } + + virtual EGLint const* getConfigAttribs() { + static EGLint sDefaultConfigAttribs[] = { + EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_DEPTH_SIZE, 16, + EGL_STENCIL_SIZE, 8, + EGL_NONE }; + + return sDefaultConfigAttribs; + } + + virtual EGLint const* getContextAttribs() { + static EGLint sDefaultContextAttribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE }; + + return sDefaultContextAttribs; + } + + virtual EGLint getSurfaceWidth() { + return 64; + } + + virtual EGLint getSurfaceHeight() { + return 64; + } + + void loadShader(GLenum shaderType, const char* pSource, GLuint* outShader) { + GLuint shader = glCreateShader(shaderType); + ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); + if (shader) { + glShaderSource(shader, 1, &pSource, NULL); + ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); + glCompileShader(shader); + ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); + GLint compiled = 0; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); + if (!compiled) { + GLint infoLen = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); + ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); + if (infoLen) { + char* buf = (char*) malloc(infoLen); + if (buf) { + glGetShaderInfoLog(shader, infoLen, NULL, buf); + printf("Shader compile log:\n%s\n", buf); + free(buf); + FAIL(); + } + } else { + char* buf = (char*) malloc(0x1000); + if (buf) { + glGetShaderInfoLog(shader, 0x1000, NULL, buf); + printf("Shader compile log:\n%s\n", buf); + free(buf); + FAIL(); + } + } + glDeleteShader(shader); + shader = 0; + } + } + ASSERT_TRUE(shader != 0); + *outShader = shader; + } + + void createProgram(const char* pVertexSource, const char* pFragmentSource, + GLuint* outPgm) { + GLuint vertexShader, fragmentShader; + { + SCOPED_TRACE("compiling vertex shader"); + loadShader(GL_VERTEX_SHADER, pVertexSource, &vertexShader); + if (HasFatalFailure()) { + return; + } + } + { + SCOPED_TRACE("compiling fragment shader"); + loadShader(GL_FRAGMENT_SHADER, pFragmentSource, &fragmentShader); + if (HasFatalFailure()) { + return; + } + } + + GLuint program = glCreateProgram(); + ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); + if (program) { + glAttachShader(program, vertexShader); + ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); + glAttachShader(program, fragmentShader); + ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); + glLinkProgram(program); + GLint linkStatus = GL_FALSE; + glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); + if (linkStatus != GL_TRUE) { + GLint bufLength = 0; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); + if (bufLength) { + char* buf = (char*) malloc(bufLength); + if (buf) { + glGetProgramInfoLog(program, bufLength, NULL, buf); + printf("Program link log:\n%s\n", buf); + free(buf); + FAIL(); + } + } + glDeleteProgram(program); + program = 0; + } + } + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); + ASSERT_TRUE(program != 0); + *outPgm = program; + } + + ::testing::AssertionResult checkPixel(int x, int y, int r, + int g, int b, int a) { + GLubyte pixel[4]; + String8 msg; + glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); + GLenum err = glGetError(); + if (err != GL_NO_ERROR) { + msg += String8::format("error reading pixel: %#x", err); + while ((err = glGetError()) != GL_NO_ERROR) { + msg += String8::format(", %#x", err); + } + fprintf(stderr, "pixel check failure: %s\n", msg.string()); + return ::testing::AssertionFailure( + ::testing::Message(msg.string())); + } + if (r >= 0 && GLubyte(r) != pixel[0]) { + msg += String8::format("r(%d isn't %d)", pixel[0], r); + } + if (g >= 0 && GLubyte(g) != pixel[1]) { + if (!msg.isEmpty()) { + msg += " "; + } + msg += String8::format("g(%d isn't %d)", pixel[1], g); + } + if (b >= 0 && GLubyte(b) != pixel[2]) { + if (!msg.isEmpty()) { + msg += " "; + } + msg += String8::format("b(%d isn't %d)", pixel[2], b); + } + if (a >= 0 && GLubyte(a) != pixel[3]) { + if (!msg.isEmpty()) { + msg += " "; + } + msg += String8::format("a(%d isn't %d)", pixel[3], a); + } + if (!msg.isEmpty()) { + fprintf(stderr, "pixel check failure: %s\n", msg.string()); + return ::testing::AssertionFailure( + ::testing::Message(msg.string())); + } else { + return ::testing::AssertionSuccess(); + } + } + + int mDisplaySecs; + sp<SurfaceComposerClient> mComposerClient; + sp<SurfaceControl> mSurfaceControl; + + EGLDisplay mEglDisplay; + EGLSurface mEglSurface; + EGLContext mEglContext; +}; + +// XXX: Code above this point should live elsewhere + +class SurfaceTextureGLTest : public GLTest { +protected: + static const GLint TEX_ID = 123; + + virtual void SetUp() { + GLTest::SetUp(); + mST = new SurfaceTexture(TEX_ID); + mSTC = new SurfaceTextureClient(mST); + mANW = mSTC; + + const char vsrc[] = + "attribute vec4 vPosition;\n" + "varying vec2 texCoords;\n" + "uniform mat4 texMatrix;\n" + "void main() {\n" + " vec2 vTexCoords = 0.5 * (vPosition.xy + vec2(1.0, 1.0));\n" + " texCoords = (texMatrix * vec4(vTexCoords, 0.0, 1.0)).xy;\n" + " gl_Position = vPosition;\n" + "}\n"; + + const char fsrc[] = + "#extension GL_OES_EGL_image_external : require\n" + "precision mediump float;\n" + "uniform samplerExternalOES texSampler;\n" + "varying vec2 texCoords;\n" + "void main() {\n" + " gl_FragColor = texture2D(texSampler, texCoords);\n" + "}\n"; + + { + SCOPED_TRACE("creating shader program"); + createProgram(vsrc, fsrc, &mPgm); + if (HasFatalFailure()) { + return; + } + } + + mPositionHandle = glGetAttribLocation(mPgm, "vPosition"); + ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); + ASSERT_NE(-1, mPositionHandle); + mTexSamplerHandle = glGetUniformLocation(mPgm, "texSampler"); + ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); + ASSERT_NE(-1, mTexSamplerHandle); + mTexMatrixHandle = glGetUniformLocation(mPgm, "texMatrix"); + ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); + ASSERT_NE(-1, mTexMatrixHandle); + } + + // drawTexture draws the SurfaceTexture over the entire GL viewport. + void drawTexture() { + const GLfloat triangleVertices[] = { + -1.0f, 1.0f, + -1.0f, -1.0f, + 1.0f, -1.0f, + 1.0f, 1.0f, + }; + + glVertexAttribPointer(mPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, triangleVertices); + ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); + glEnableVertexAttribArray(mPositionHandle); + ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); + + glUseProgram(mPgm); + glUniform1i(mTexSamplerHandle, 0); + ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); + glBindTexture(GL_TEXTURE_EXTERNAL_OES, TEX_ID); + ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); + + GLfloat texMatrix[16]; + mST->getTransformMatrix(texMatrix); + glUniformMatrix4fv(mTexMatrixHandle, 1, GL_FALSE, texMatrix); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); + } + + sp<SurfaceTexture> mST; + sp<SurfaceTextureClient> mSTC; + sp<ANativeWindow> mANW; + + GLuint mPgm; + GLint mPositionHandle; + GLint mTexSamplerHandle; + GLint mTexMatrixHandle; +}; + +// Fill a YV12 buffer with a multi-colored checkerboard pattern +void fillYV12Buffer(uint8_t* buf, int w, int h, int stride) { + const int blockWidth = w > 16 ? w / 16 : 1; + const int blockHeight = h > 16 ? h / 16 : 1; + const int yuvTexOffsetY = 0; + int yuvTexStrideY = stride; + int yuvTexOffsetV = yuvTexStrideY * h; + int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf; + int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2; + int yuvTexStrideU = yuvTexStrideV; + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + int parityX = (x / blockWidth) & 1; + int parityY = (y / blockHeight) & 1; + unsigned char intensity = (parityX ^ parityY) ? 63 : 191; + buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = intensity; + if (x < w / 2 && y < h / 2) { + buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = intensity; + if (x * 2 < w / 2 && y * 2 < h / 2) { + buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 0] = + buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 1] = + buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 0] = + buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 1] = + intensity; + } + } + } + } +} + +// Fill a YV12 buffer with red outside a given rectangle and green inside it. +void fillYV12BufferRect(uint8_t* buf, int w, int h, int stride, + const android_native_rect_t& rect) { + const int yuvTexOffsetY = 0; + int yuvTexStrideY = stride; + int yuvTexOffsetV = yuvTexStrideY * h; + int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf; + int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2; + int yuvTexStrideU = yuvTexStrideV; + for (int x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + bool inside = rect.left <= x && x < rect.right && + rect.top <= y && y < rect.bottom; + buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = inside ? 240 : 64; + if (x < w / 2 && y < h / 2) { + bool inside = rect.left <= 2*x && 2*x < rect.right && + rect.top <= 2*y && 2*y < rect.bottom; + buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = 16; + buf[yuvTexOffsetV + (y * yuvTexStrideV) + x] = + inside ? 16 : 255; + } + } + } +} + +TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferNpot) { + const int yuvTexWidth = 64; + const int yuvTexHeight = 66; + + ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), + yuvTexWidth, yuvTexHeight, HAL_PIXEL_FORMAT_YV12)); + ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); + + android_native_buffer_t* anb; + ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb)); + ASSERT_TRUE(anb != NULL); + + sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); + ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer())); + + // Fill the buffer with the a checkerboard pattern + uint8_t* img = NULL; + buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); + fillYV12Buffer(img, yuvTexWidth, yuvTexHeight, buf->getStride()); + buf->unlock(); + ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer())); + + mST->updateTexImage(); + + glClearColor(0.2, 0.2, 0.2, 0.2); + glClear(GL_COLOR_BUFFER_BIT); + + drawTexture(); + + EXPECT_TRUE(checkPixel( 0, 0, 255, 127, 255, 255)); + EXPECT_TRUE(checkPixel(63, 0, 0, 133, 0, 255)); + EXPECT_TRUE(checkPixel(63, 63, 0, 133, 0, 255)); + EXPECT_TRUE(checkPixel( 0, 63, 255, 127, 255, 255)); + + EXPECT_TRUE(checkPixel(22, 44, 247, 70, 255, 255)); + EXPECT_TRUE(checkPixel(45, 52, 209, 32, 235, 255)); + EXPECT_TRUE(checkPixel(52, 51, 100, 255, 73, 255)); + EXPECT_TRUE(checkPixel( 7, 31, 155, 0, 118, 255)); + EXPECT_TRUE(checkPixel(31, 9, 148, 71, 110, 255)); + EXPECT_TRUE(checkPixel(29, 35, 255, 127, 255, 255)); + EXPECT_TRUE(checkPixel(36, 22, 155, 29, 0, 255)); +} + +// XXX: This test is disabled because it it currently broken on all devices to +// which I have access. Some of the checkPixel calls are not correct because +// I just copied them from the npot test above and haven't bothered to figure +// out the correct values. +TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledYV12BufferPow2) { + const int yuvTexWidth = 64; + const int yuvTexHeight = 64; + + ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), + yuvTexWidth, yuvTexHeight, HAL_PIXEL_FORMAT_YV12)); + ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); + + android_native_buffer_t* anb; + ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb)); + ASSERT_TRUE(anb != NULL); + + sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); + ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer())); + + // Fill the buffer with the a checkerboard pattern + uint8_t* img = NULL; + buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); + fillYV12Buffer(img, yuvTexWidth, yuvTexHeight, buf->getStride()); + buf->unlock(); + ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer())); + + mST->updateTexImage(); + + glClearColor(0.2, 0.2, 0.2, 0.2); + glClear(GL_COLOR_BUFFER_BIT); + + drawTexture(); + + EXPECT_TRUE(checkPixel( 0, 0, 255, 127, 255, 255)); + EXPECT_TRUE(checkPixel(63, 0, 0, 133, 0, 255)); + EXPECT_TRUE(checkPixel(63, 63, 0, 133, 0, 255)); + EXPECT_TRUE(checkPixel( 0, 63, 255, 127, 255, 255)); + + EXPECT_TRUE(checkPixel(22, 19, 247, 70, 255, 255)); + EXPECT_TRUE(checkPixel(45, 11, 209, 32, 235, 255)); + EXPECT_TRUE(checkPixel(52, 12, 100, 255, 73, 255)); + EXPECT_TRUE(checkPixel( 7, 32, 155, 0, 118, 255)); + EXPECT_TRUE(checkPixel(31, 54, 148, 71, 110, 255)); + EXPECT_TRUE(checkPixel(29, 28, 255, 127, 255, 255)); + EXPECT_TRUE(checkPixel(36, 41, 155, 29, 0, 255)); +} + +TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) { + const int yuvTexWidth = 64; + const int yuvTexHeight = 66; + + ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), + yuvTexWidth, yuvTexHeight, HAL_PIXEL_FORMAT_YV12)); + ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); + + android_native_rect_t crops[] = { + {4, 6, 22, 36}, + {0, 6, 22, 36}, + {4, 0, 22, 36}, + {4, 6, yuvTexWidth, 36}, + {4, 6, 22, yuvTexHeight}, + }; + + for (int i = 0; i < 5; i++) { + const android_native_rect_t& crop(crops[i]); + SCOPED_TRACE(String8::format("rect{ l: %d t: %d r: %d b: %d }", crop.left, + crop.top, crop.right, crop.bottom).string()); + + ASSERT_EQ(NO_ERROR, native_window_set_crop(mANW.get(), &crop)); + + android_native_buffer_t* anb; + ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb)); + ASSERT_TRUE(anb != NULL); + + sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); + ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer())); + + uint8_t* img = NULL; + buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); + fillYV12BufferRect(img, yuvTexWidth, yuvTexHeight, buf->getStride(), crop); + buf->unlock(); + ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer())); + + mST->updateTexImage(); + + glClearColor(0.2, 0.2, 0.2, 0.2); + glClear(GL_COLOR_BUFFER_BIT); + + drawTexture(); + + EXPECT_TRUE(checkPixel( 0, 0, 82, 255, 35, 255)); + EXPECT_TRUE(checkPixel(63, 0, 82, 255, 35, 255)); + EXPECT_TRUE(checkPixel(63, 63, 82, 255, 35, 255)); + EXPECT_TRUE(checkPixel( 0, 63, 82, 255, 35, 255)); + + EXPECT_TRUE(checkPixel(25, 14, 82, 255, 35, 255)); + EXPECT_TRUE(checkPixel(35, 31, 82, 255, 35, 255)); + EXPECT_TRUE(checkPixel(57, 6, 82, 255, 35, 255)); + EXPECT_TRUE(checkPixel( 5, 42, 82, 255, 35, 255)); + EXPECT_TRUE(checkPixel(32, 33, 82, 255, 35, 255)); + EXPECT_TRUE(checkPixel(16, 26, 82, 255, 35, 255)); + EXPECT_TRUE(checkPixel(46, 51, 82, 255, 35, 255)); + } +} + +} diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 737fa02..868290b 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -285,9 +285,12 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) break; case DrawDisplayList: { DisplayList* displayList = getDisplayList(); - DISPLAY_LIST_LOGD("%s%s %p, %d", (char*) indent, OP_NAMES[op], - displayList, level + 1); - needsInvalidate |= renderer.drawDisplayList(displayList, dirty, level + 1); + uint32_t width = getUInt(); + uint32_t height = getUInt(); + DISPLAY_LIST_LOGD("%s%s %p, %dx%d, %d", (char*) indent, OP_NAMES[op], + displayList, width, height, level + 1); + needsInvalidate |= renderer.drawDisplayList(displayList, width, height, + dirty, level + 1); } break; case DrawLayer: { @@ -674,11 +677,13 @@ bool DisplayListRenderer::clipRect(float left, float top, float right, float bot return OpenGLRenderer::clipRect(left, top, right, bottom, op); } -bool DisplayListRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level) { +bool DisplayListRenderer::drawDisplayList(DisplayList* displayList, + uint32_t width, uint32_t height, Rect& dirty, uint32_t level) { // dirty is an out parameter and should not be recorded, // it matters only when replaying the display list addOp(DisplayList::DrawDisplayList); addDisplayList(displayList); + addSize(width, height); return false; } diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index f24545d..6fc315c 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -144,6 +144,10 @@ private: return mReader.readInt(); } + inline uint32_t getUInt() { + return mReader.readU32(); + } + SkMatrix* getMatrix() { return (SkMatrix*) getInt(); } @@ -238,7 +242,8 @@ public: bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op); - bool drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level = 0); + bool drawDisplayList(DisplayList* displayList, uint32_t width, uint32_t height, + Rect& dirty, uint32_t level = 0); void drawLayer(Layer* layer, float x, float y, SkPaint* paint); void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint); void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint); @@ -323,6 +328,11 @@ private: mWriter.writeInt(value); } + inline void addSize(uint32_t w, uint32_t h) { + mWriter.writeInt(w); + mWriter.writeInt(h); + } + void addInts(const int32_t* values, uint32_t count) { mWriter.writeInt(count); for (uint32_t i = 0; i < count; i++) { diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 1f65201..5d9522e 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -403,10 +403,7 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top, // Window coordinates of the layer Rect bounds(left, top, right, bottom); - if (fboLayer) { - // Clear the previous layer regions before we change the viewport - clearLayerRegions(); - } else { + if (!fboLayer) { mSnapshot->transform->mapRect(bounds); // Layers only make sense if they are in the framebuffer's bounds @@ -464,8 +461,14 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top, glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bounds.left, snapshot->height - bounds.bottom, bounds.getWidth(), bounds.getHeight()); } - // Enqueue the buffer coordinates to clear the corresponding region later - mLayers.push(new Rect(bounds)); + + // Clear the framebuffer where the layer will draw + glScissor(bounds.left, mSnapshot->height - bounds.bottom, + bounds.getWidth(), bounds.getHeight()); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + + dirtyClip(); } } @@ -760,31 +763,6 @@ void OpenGLRenderer::dirtyLayerUnchecked(Rect& bounds, Region* region) { #endif } -void OpenGLRenderer::clearLayerRegions() { - if (mLayers.size() == 0 || mSnapshot->isIgnored()) return; - - Rect clipRect(*mSnapshot->clipRect); - clipRect.snapToPixelBoundaries(); - - for (uint32_t i = 0; i < mLayers.size(); i++) { - Rect* bounds = mLayers.itemAt(i); - if (clipRect.intersects(*bounds)) { - // Clear the framebuffer where the layer will draw - glScissor(bounds->left, mSnapshot->height - bounds->bottom, - bounds->getWidth(), bounds->getHeight()); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClear(GL_COLOR_BUFFER_BIT); - - // Restore the clip - dirtyClip(); - } - - delete bounds; - } - - mLayers.clear(); -} - /////////////////////////////////////////////////////////////////////////////// // Transforms /////////////////////////////////////////////////////////////////////////////// @@ -870,7 +848,6 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, /////////////////////////////////////////////////////////////////////////////// void OpenGLRenderer::setupDraw() { - clearLayerRegions(); if (mDirtyClip) { setScissorFromClip(); } @@ -1064,12 +1041,18 @@ void OpenGLRenderer::finishDrawTexture() { // Drawing /////////////////////////////////////////////////////////////////////////////// -bool OpenGLRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level) { +bool OpenGLRenderer::drawDisplayList(DisplayList* displayList, uint32_t width, uint32_t height, + Rect& dirty, uint32_t level) { + if (quickReject(0.0f, 0.0f, width, height)) { + return false; + } + // All the usual checks and setup operations (quickReject, setupDraw, etc.) // will be performed by the display list itself if (displayList) { return displayList->replay(*this, dirty, level); } + return false; } diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 9d86388..7362473 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -96,7 +96,8 @@ public: bool quickReject(float left, float top, float right, float bottom); virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op); - virtual bool drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level = 0); + virtual bool drawDisplayList(DisplayList* displayList, uint32_t width, uint32_t height, + Rect& dirty, uint32_t level = 0); virtual void drawLayer(Layer* layer, float x, float y, SkPaint* paint); virtual void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint); virtual void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint); @@ -247,12 +248,6 @@ private: void composeLayerRect(Layer* layer, const Rect& rect, bool swap = false); /** - * Clears all the regions corresponding to the current list of layers. - * This method MUST be invoked before any drawing operation. - */ - void clearLayerRegions(); - - /** * Mark the layer as dirty at the specified coordinates. The coordinates * are transformed with the supplied matrix. */ @@ -499,9 +494,6 @@ private: // Various caches Caches& mCaches; - // List of rectangles to clear due to calls to saveLayer() - Vector<Rect*> mLayers; - // Indentity matrix const mat4 mIdentity; diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h index 3acd18a..ead5b92 100644 --- a/libs/hwui/ProgramCache.h +++ b/libs/hwui/ProgramCache.h @@ -231,9 +231,11 @@ struct ProgramDescription { * Logs the specified message followed by the key identifying this program. */ void log(const char* message) const { +#if DEBUG_PROGRAMS programid k = key(); PROGRAM_LOGD("%s (key = 0x%.8x%.8x)", message, uint32_t(k >> 32), uint32_t(k & 0xffffffff)); +#endif } private: diff --git a/libs/usb/src/com/android/future/usb/UsbAccessory.java b/libs/usb/src/com/android/future/usb/UsbAccessory.java index 3d0707f..0f965d7 100644 --- a/libs/usb/src/com/android/future/usb/UsbAccessory.java +++ b/libs/usb/src/com/android/future/usb/UsbAccessory.java @@ -19,13 +19,14 @@ package com.android.future.usb; /** * A class representing a USB accessory. */ -public final class UsbAccessory { +public class UsbAccessory { private final String mManufacturer; private final String mModel; private final String mDescription; private final String mVersion; private final String mUri; + private final String mSerial; /* package */ UsbAccessory(android.hardware.usb.UsbAccessory accessory) { mManufacturer = accessory.getManufacturer(); @@ -33,6 +34,7 @@ public final class UsbAccessory { mDescription = accessory.getDescription(); mVersion = accessory.getVersion(); mUri = accessory.getUri(); + mSerial = accessory.getSerial(); } /** @@ -82,6 +84,17 @@ public final class UsbAccessory { return mUri; } + /** + * Returns the unique serial number for the accessory. + * This is an optional serial number that can be used to differentiate + * between individual accessories of the same model and manufacturer + * + * @return the unique serial number + */ + public String getSerial() { + return mSerial; + } + private static boolean compare(String s1, String s2) { if (s1 == null) return (s2 == null); return s1.equals(s2); @@ -95,7 +108,8 @@ public final class UsbAccessory { compare(mModel, accessory.getModel()) && compare(mDescription, accessory.getDescription()) && compare(mVersion, accessory.getVersion()) && - compare(mUri, accessory.getUri())); + compare(mUri, accessory.getUri()) && + compare(mSerial, accessory.getSerial())); } return false; } @@ -106,7 +120,8 @@ public final class UsbAccessory { (mModel == null ? 0 : mModel.hashCode()) ^ (mDescription == null ? 0 : mDescription.hashCode()) ^ (mVersion == null ? 0 : mVersion.hashCode()) ^ - (mUri == null ? 0 : mUri.hashCode())); + (mUri == null ? 0 : mUri.hashCode()) ^ + (mSerial == null ? 0 : mSerial.hashCode())); } @Override @@ -115,6 +130,7 @@ public final class UsbAccessory { ", mModel=" + mModel + ", mDescription=" + mDescription + ", mVersion=" + mVersion + - ", mUri=" + mUri + "]"; + ", mUri=" + mUri + + ", mSerial=" + mSerial + "]"; } } diff --git a/libs/usb/src/com/android/future/usb/UsbManager.java b/libs/usb/src/com/android/future/usb/UsbManager.java index 840e1e3..d424b63 100644 --- a/libs/usb/src/com/android/future/usb/UsbManager.java +++ b/libs/usb/src/com/android/future/usb/UsbManager.java @@ -130,7 +130,8 @@ public class UsbManager { try { return mService.openAccessory(new android.hardware.usb.UsbAccessory( accessory.getManufacturer(),accessory.getModel(), - accessory.getDescription(), accessory.getVersion(), accessory.getUri())); + accessory.getDescription(), accessory.getVersion(), + accessory.getUri(), accessory.getSerial())); } catch (RemoteException e) { Log.e(TAG, "RemoteException in openAccessory" , e); return null; @@ -150,7 +151,8 @@ public class UsbManager { try { return mService.hasAccessoryPermission(new android.hardware.usb.UsbAccessory( accessory.getManufacturer(),accessory.getModel(), - accessory.getDescription(), accessory.getVersion(), accessory.getUri())); + accessory.getDescription(), accessory.getVersion(), + accessory.getUri(), accessory.getSerial())); } catch (RemoteException e) { Log.e(TAG, "RemoteException in hasPermission", e); return false; @@ -174,7 +176,8 @@ public class UsbManager { try { mService.requestAccessoryPermission(new android.hardware.usb.UsbAccessory( accessory.getManufacturer(),accessory.getModel(), - accessory.getDescription(), accessory.getVersion(), accessory.getUri()), + accessory.getDescription(), accessory.getVersion(), + accessory.getUri(), accessory.getSerial()), mContext.getPackageName(), pi); } catch (RemoteException e) { Log.e(TAG, "RemoteException in requestPermission", e); diff --git a/libs/usb/tests/AccessoryChat/Android.mk b/libs/usb/tests/AccessoryChat/Android.mk index d555961..77b8424 100644 --- a/libs/usb/tests/AccessoryChat/Android.mk +++ b/libs/usb/tests/AccessoryChat/Android.mk @@ -21,7 +21,7 @@ LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := $(call all-subdir-java-files) -LOCAL_PACKAGE_NAME := AccessoryChatGB +LOCAL_PACKAGE_NAME := AccessoryChat LOCAL_JAVA_LIBRARIES := com.android.future.usb.accessory diff --git a/libs/usb/tests/AccessoryChat/AndroidManifest.xml b/libs/usb/tests/AccessoryChat/AndroidManifest.xml index d6093ae..37ab29f 100644 --- a/libs/usb/tests/AccessoryChat/AndroidManifest.xml +++ b/libs/usb/tests/AccessoryChat/AndroidManifest.xml @@ -20,7 +20,7 @@ <application> <uses-library android:name="com.android.future.usb.accessory" /> - <activity android:name="AccessoryChat" android:label="Accessory Chat GB"> + <activity android:name="AccessoryChat" android:label="Accessory Chat"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.DEFAULT" /> diff --git a/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c b/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c index 3c0de69..c80b7c4 100644 --- a/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c +++ b/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c @@ -24,6 +24,7 @@ #include <fcntl.h> #include <errno.h> #include <pthread.h> +#include <time.h> #include <usbhost/usbhost.h> #include <linux/usb/f_accessory.h> @@ -65,9 +66,20 @@ static void* write_thread(void* arg) { return NULL; } +static void milli_sleep(int millis) { + struct timespec tm; + + tm.tv_sec = 0; + tm.tv_nsec = millis * 1000000; + nanosleep(&tm, NULL); +} + static void send_string(struct usb_device *device, int index, const char* string) { int ret = usb_device_control_transfer(device, USB_DIR_OUT | USB_TYPE_VENDOR, ACCESSORY_SEND_STRING, 0, index, (void *)string, strlen(string) + 1, 0); + + // some devices can't handle back-to-back requests, so delay a bit + milli_sleep(10); } static int usb_device_added(const char *devname, void* client_data) { @@ -146,6 +158,7 @@ static int usb_device_added(const char *devname, void* client_data) { send_string(device, ACCESSORY_STRING_DESCRIPTION, "Sample Program"); send_string(device, ACCESSORY_STRING_VERSION, "1.0"); send_string(device, ACCESSORY_STRING_URI, "http://www.android.com"); + send_string(device, ACCESSORY_STRING_SERIAL, "1234567890"); ret = usb_device_control_transfer(device, USB_DIR_OUT | USB_TYPE_VENDOR, ACCESSORY_START, 0, 0, 0, 0, 0); diff --git a/libs/usb/tests/AccessoryChat/src/com/android/accessorychat/AccessoryChat.java b/libs/usb/tests/AccessoryChat/src/com/android/accessorychat/AccessoryChat.java index f9a5bf4..c3f4fa3 100644 --- a/libs/usb/tests/AccessoryChat/src/com/android/accessorychat/AccessoryChat.java +++ b/libs/usb/tests/AccessoryChat/src/com/android/accessorychat/AccessoryChat.java @@ -135,7 +135,8 @@ public class AccessoryChat extends Activity implements Runnable, TextView.OnEdit } private void openAccessory(UsbAccessory accessory) { - mFileDescriptor = mUsbManager.openAccessory(accessory); + Log.d(TAG, "openAccessory: " + accessory); + mFileDescriptor = mUsbManager.openAccessory(accessory); if (mFileDescriptor != null) { FileDescriptor fd = mFileDescriptor.getFileDescriptor(); mInputStream = new FileInputStream(fd); diff --git a/media/java/android/media/videoeditor/AudioTrack.java b/media/java/android/media/videoeditor/AudioTrack.java index 7069b23..2de82f2 100755 --- a/media/java/android/media/videoeditor/AudioTrack.java +++ b/media/java/android/media/videoeditor/AudioTrack.java @@ -49,7 +49,6 @@ public class AudioTrack { private final int mAudioType; private final int mAudioBitrate; private final int mAudioSamplingFrequency; - /** * Ducking variables */ @@ -127,11 +126,17 @@ public class AudioTrack { int duckThreshold, int duckedTrackVolume, String audioWaveformFilename) throws IOException { Properties properties = null; + File file = new File(filename); if (!file.exists()) { throw new IOException(filename + " not found ! "); } + /*Compare file_size with 2GB*/ + if (VideoEditor.MAX_SUPPORTED_FILE_SIZE <= file.length()) { + throw new IllegalArgumentException("File size is more than 2GB"); + } + if (editor instanceof VideoEditorImpl) { mMANativeHelper = ((VideoEditorImpl)editor).getNativeContext(); } else { diff --git a/media/java/android/media/videoeditor/MediaItem.java b/media/java/android/media/videoeditor/MediaItem.java index dfe0bae..8c4841f 100755 --- a/media/java/android/media/videoeditor/MediaItem.java +++ b/media/java/android/media/videoeditor/MediaItem.java @@ -131,6 +131,15 @@ public abstract class MediaItem { if (filename == null) { throw new IllegalArgumentException("MediaItem : filename is null"); } + File file = new File(filename); + if (!file.exists()) { + throw new IOException(filename + " not found ! "); + } + + /*Compare file_size with 2GB*/ + if (VideoEditor.MAX_SUPPORTED_FILE_SIZE <= file.length()) { + throw new IllegalArgumentException("File size is more than 2GB"); + } mUniqueId = mediaItemId; mFilename = filename; mRenderingMode = renderingMode; diff --git a/media/java/android/media/videoeditor/VideoEditor.java b/media/java/android/media/videoeditor/VideoEditor.java index 122dc8d..59e4540 100755 --- a/media/java/android/media/videoeditor/VideoEditor.java +++ b/media/java/android/media/videoeditor/VideoEditor.java @@ -68,6 +68,11 @@ public interface VideoEditor { public final static int DURATION_OF_STORYBOARD = -1; /** + * Maximum supported file size + */ + public static final long MAX_SUPPORTED_FILE_SIZE = 2147483648L; + + /** * This listener interface is used by the VideoEditor to emit preview * progress notifications. This callback should be invoked after the number * of frames specified by diff --git a/media/java/android/media/videoeditor/VideoEditorImpl.java b/media/java/android/media/videoeditor/VideoEditorImpl.java index 7e1f73a..78557ee 100755 --- a/media/java/android/media/videoeditor/VideoEditorImpl.java +++ b/media/java/android/media/videoeditor/VideoEditorImpl.java @@ -119,7 +119,6 @@ public class VideoEditorImpl implements VideoEditor { private static final String ATTR_OVERLAY_FRAME_HEIGHT = "overlay_frame_height"; private static final String ATTR_OVERLAY_RESIZED_RGB_FRAME_WIDTH = "resized_RGBframe_width"; private static final String ATTR_OVERLAY_RESIZED_RGB_FRAME_HEIGHT = "resized_RGBframe_height"; - private static final int ENGINE_ACCESS_MAX_TIMEOUT_MS = 500; /* * Instance variables @@ -437,6 +436,12 @@ public class VideoEditorImpl implements VideoEditor { throw new IllegalArgumentException(message); } } + computeTimelineDuration(); + final long audioBitrate = MediaArtistNativeHelper.Bitrate.BR_96_KBPS; + final long fileSize = (mDurationMs * (bitrate + audioBitrate)) / 8000; + if (MAX_SUPPORTED_FILE_SIZE <= fileSize) { + throw new IllegalStateException("Export Size is more than 2GB"); + } boolean semAcquireDone = false; try { diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java index 4e6f81f..2781246 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java @@ -100,6 +100,14 @@ public class UsbConfirmActivity extends AlertActivity } + @Override + protected void onDestroy() { + if (mDisconnectedReceiver != null) { + unregisterReceiver(mDisconnectedReceiver); + } + super.onDestroy(); + } + public void onClick(DialogInterface dialog, int which) { if (which == AlertDialog.BUTTON_POSITIVE) { try { diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 9c9d406..1455764 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -60,7 +60,6 @@ import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.SystemClock; -import android.os.SystemProperties; import android.provider.Settings; import android.provider.Settings.Secure; import android.provider.Settings.SettingNotFoundException; @@ -315,7 +314,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub int mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT; int mImeWindowVis; - long mOldSystemSettingsVersion; AlertDialog.Builder mDialogBuilder; AlertDialog mSwitchingDialog; @@ -490,8 +488,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub handleMessage(msg); } }); - // Initialize the system settings version to undefined. - mOldSystemSettingsVersion = -1; (new MyPackageMonitor()).register(mContext, true); @@ -1012,15 +1008,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } - // TODO: Investigate and fix why are settings changes getting processed before the settings seq - // number is updated? - // TODO: Change this stuff to not rely on modifying settings for normal user interactions. void updateFromSettingsLocked() { - long newSystemSettingsVersion = getSystemSettingsVersion(); - // This is a workaround to avoid a situation that old cached value in Settings.Secure - // will be handled. - if (newSystemSettingsVersion == mOldSystemSettingsVersion) return; - // We are assuming that whoever is changing DEFAULT_INPUT_METHOD and // ENABLED_INPUT_METHODS is taking care of keeping them correctly in // sync, so we will never have a DEFAULT_INPUT_METHOD that is not @@ -1989,7 +1977,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private void setSelectedInputMethodAndSubtypeLocked(InputMethodInfo imi, int subtypeId, boolean setSubtypeOnly) { - mOldSystemSettingsVersion = getSystemSettingsVersion(); // Update the history of InputMethod and Subtype saveCurrentInputMethodAndSubtypeToHistory(); @@ -2239,10 +2226,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } - private static long getSystemSettingsVersion() { - return SystemProperties.getLong(Settings.Secure.SYS_PROP_SETTING_VERSION, 0); - } - /** * @return Return the current subtype of this input method. */ diff --git a/services/jni/com_android_server_UsbService.cpp b/services/jni/com_android_server_UsbService.cpp index c66f181..816f76f 100644 --- a/services/jni/com_android_server_UsbService.cpp +++ b/services/jni/com_android_server_UsbService.cpp @@ -193,13 +193,14 @@ static jobjectArray android_server_UsbService_getAccessoryStrings(JNIEnv *env, j return NULL; } jclass stringClass = env->FindClass("java/lang/String"); - jobjectArray strArray = env->NewObjectArray(5, stringClass, NULL); + jobjectArray strArray = env->NewObjectArray(6, stringClass, NULL); if (!strArray) goto out; set_accessory_string(env, fd, ACCESSORY_GET_STRING_MANUFACTURER, strArray, 0); set_accessory_string(env, fd, ACCESSORY_GET_STRING_MODEL, strArray, 1); set_accessory_string(env, fd, ACCESSORY_GET_STRING_DESCRIPTION, strArray, 2); set_accessory_string(env, fd, ACCESSORY_GET_STRING_VERSION, strArray, 3); set_accessory_string(env, fd, ACCESSORY_GET_STRING_URI, strArray, 4); + set_accessory_string(env, fd, ACCESSORY_GET_STRING_SERIAL, strArray, 5); out: close(fd); diff --git a/tests/HwAccelerationTest/res/drawable/gradient.xml b/tests/HwAccelerationTest/res/drawable/gradient.xml new file mode 100644 index 0000000..756db0b --- /dev/null +++ b/tests/HwAccelerationTest/res/drawable/gradient.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2010 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. +--> + +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <gradient + android:startColor="#FF707070" + android:endColor="#FF0C0C0C" + android:angle="270" /> +</shape> diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java index f8422f4..90db818 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GradientsActivity.java @@ -193,6 +193,7 @@ public class GradientsActivity extends Activity { private final float mDrawWidth; private final float mDrawHeight; private final LinearGradient mGradient; + private final LinearGradient mGradientStops; private final Matrix mMatrix; ShadersView(Context c) { @@ -202,6 +203,9 @@ public class GradientsActivity extends Activity { mDrawHeight = 200; mGradient = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP); + mGradientStops = new LinearGradient(0, 0, 0, 1, + new int[] { 0xFFFF0000, 0xFF00FF00, 0xFF0000FF }, null, Shader.TileMode.CLAMP); + mMatrix = new Matrix(); mPaint = new Paint(); @@ -255,6 +259,19 @@ public class GradientsActivity extends Activity { mGradient.setLocalMatrix(mMatrix); canvas.drawRect(left, top, left + mDrawWidth, bottom, mPaint); + right = left + mDrawWidth; + left = 40.0f; + top = bottom + 20.0f; + bottom = top + 50.0f; + + mPaint.setShader(mGradientStops); + + mMatrix.setScale(1, mDrawWidth); + mMatrix.postRotate(90); + mMatrix.postTranslate(right, top); + mGradientStops.setLocalMatrix(mMatrix); + canvas.drawRect(left, top, right, bottom, mPaint); + canvas.restore(); } } diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java index 763169a..535f865 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TransparentListActivity.java @@ -79,7 +79,7 @@ public class TransparentListActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - getWindow().setBackgroundDrawable(getResources().getDrawable(R.drawable.default_wallpaper)); + getWindow().setBackgroundDrawable(getResources().getDrawable(R.drawable.gradient)); setContentView(R.layout.list_activity); ListAdapter adapter = new SimpleListAdapter(this); |