Merge "Add more check before using the DRM manager client."
diff --git a/api/current.xml b/api/current.xml
index bd86302..ea86e3b 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -76419,6 +76419,17 @@
visibility="public"
>
</method>
+<method name="getGenerationId"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getHeight"
return="int"
abstract="false"
@@ -76636,6 +76647,19 @@
visibility="public"
>
</method>
+<method name="sameAs"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="other" type="android.graphics.Bitmap">
+</parameter>
+</method>
<method name="setDensity"
return="void"
abstract="false"
@@ -76649,6 +76673,19 @@
<parameter name="density" type="int">
</parameter>
</method>
+<method name="setHasAlpha"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="hasAlpha" type="boolean">
+</parameter>
+</method>
<method name="setPixel"
return="void"
abstract="false"
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 71d55f7..d46dacc 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -42,10 +42,23 @@
/**
* Turn on to only refresh the parts of the screen that need updating.
+ * When turned on the property defined by {@link #RENDER_DIRTY_REGIONS_PROPERTY}
+ * must also have the value "true".
*/
public static final boolean RENDER_DIRTY_REGIONS = true;
/**
+ * System property used to enable or disable dirty regions invalidation.
+ * This property is only queried if {@link #RENDER_DIRTY_REGIONS} is true.
+ * The default value of this property is assumed to be true.
+ *
+ * Possible values:
+ * "true", to enable partial invalidates
+ * "false", to disable partial invalidates
+ */
+ static final String RENDER_DIRTY_REGIONS_PROPERTY = "hwui.render_dirty_regions";
+
+ /**
* Turn on to draw dirty regions every other frame.
*/
private static final boolean DEBUG_DIRTY_REGION = false;
@@ -113,8 +126,23 @@
*/
abstract void setup(int width, int height);
+ /**
+ * Interface used to receive callbacks whenever a view is drawn by
+ * a hardware renderer instance.
+ */
interface HardwareDrawCallbacks {
+ /**
+ * Invoked before a view is drawn by a hardware renderer.
+ *
+ * @param canvas The Canvas used to render the view.
+ */
void onHardwarePreDraw(Canvas canvas);
+
+ /**
+ * Invoked after a view is drawn by a hardware renderer.
+ *
+ * @param canvas The Canvas used to render the view.
+ */
void onHardwarePostDraw(Canvas canvas);
}
@@ -250,6 +278,7 @@
int mFrameCount;
Paint mDebugPaint;
+ boolean mDirtyRegions;
final int mGlVersion;
final boolean mTranslucent;
@@ -259,6 +288,9 @@
GlRenderer(int glVersion, boolean translucent) {
mGlVersion = glVersion;
mTranslucent = translucent;
+ final String dirtyProperty = System.getProperty(RENDER_DIRTY_REGIONS_PROPERTY, "true");
+ //noinspection PointlessBooleanExpression,ConstantConditions
+ mDirtyRegions = RENDER_DIRTY_REGIONS && "true".equalsIgnoreCase(dirtyProperty);
}
/**
@@ -388,10 +420,24 @@
// We can now initialize EGL for that display
int[] version = new int[2];
if (!sEgl.eglInitialize(sEglDisplay, version)) {
- throw new RuntimeException("eglInitialize failed "
- + getEGLErrorString(sEgl.eglGetError()));
+ throw new RuntimeException("eglInitialize failed " +
+ getEGLErrorString(sEgl.eglGetError()));
}
+
sEglConfig = getConfigChooser(mGlVersion).chooseConfig(sEgl, sEglDisplay);
+ if (sEglConfig == null) {
+ // We tried to use EGL_SWAP_BEHAVIOR_PRESERVED_BIT, try again without
+ if (mDirtyRegions) {
+ mDirtyRegions = false;
+
+ sEglConfig = getConfigChooser(mGlVersion).chooseConfig(sEgl, sEglDisplay);
+ if (sEglConfig == null) {
+ throw new RuntimeException("eglConfig not initialized");
+ }
+ } else {
+ throw new RuntimeException("eglConfig not initialized");
+ }
+ }
/*
* Create an EGL context. We want to do this as rarely as we can, because an
@@ -409,7 +455,7 @@
throw new RuntimeException("eglDisplay not initialized");
}
if (sEglConfig == null) {
- throw new RuntimeException("mEglConfig not initialized");
+ throw new RuntimeException("eglConfig not initialized");
}
if (Thread.currentThread() != sEglThread) {
throw new IllegalStateException("HardwareRenderer cannot be used "
@@ -452,7 +498,7 @@
+ getEGLErrorString(sEgl.eglGetError()));
}
- if (RENDER_DIRTY_REGIONS) {
+ if (mDirtyRegions) {
if (!GLES20Canvas.preserveBackBuffer()) {
Log.w(LOG_TAG, "Backbuffer cannot be preserved");
}
@@ -518,15 +564,14 @@
* @return An {@link android.view.HardwareRenderer.GlRenderer.EglConfigChooser}.
*/
EglConfigChooser getConfigChooser(int glVersion) {
- return new ComponentSizeChooser(glVersion, 8, 8, 8, 8, 0, 0);
+ return new ComponentSizeChooser(glVersion, 8, 8, 8, 8, 0, 0, mDirtyRegions);
}
@Override
void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks,
Rect dirty) {
if (canDraw()) {
- //noinspection PointlessBooleanExpression,ConstantConditions
- if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
+ if (!mDirtyRegions) {
dirty = null;
}
@@ -676,16 +721,16 @@
static class ComponentSizeChooser extends EglConfigChooser {
private int[] mValue;
- private int mRedSize;
- private int mGreenSize;
- private int mBlueSize;
- private int mAlphaSize;
- private int mDepthSize;
- private int mStencilSize;
+ private final int mRedSize;
+ private final int mGreenSize;
+ private final int mBlueSize;
+ private final int mAlphaSize;
+ private final int mDepthSize;
+ private final int mStencilSize;
+ private final boolean mDirtyRegions;
ComponentSizeChooser(int glVersion, int redSize, int greenSize, int blueSize,
- int alphaSize, int depthSize, int stencilSize) {
- //noinspection PointlessBitwiseExpression
+ int alphaSize, int depthSize, int stencilSize, boolean dirtyRegions) {
super(glVersion, new int[] {
EGL10.EGL_RED_SIZE, redSize,
EGL10.EGL_GREEN_SIZE, greenSize,
@@ -694,7 +739,7 @@
EGL10.EGL_DEPTH_SIZE, depthSize,
EGL10.EGL_STENCIL_SIZE, stencilSize,
EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT |
- (RENDER_DIRTY_REGIONS ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0),
+ (dirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0),
EGL10.EGL_NONE });
mValue = new int[1];
mRedSize = redSize;
@@ -703,7 +748,8 @@
mAlphaSize = alphaSize;
mDepthSize = depthSize;
mStencilSize = stencilSize;
- }
+ mDirtyRegions = dirtyRegions;
+ }
@Override
EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs) {
@@ -716,7 +762,7 @@
int b = findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0);
int a = findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0);
boolean backBuffer;
- if (RENDER_DIRTY_REGIONS) {
+ if (mDirtyRegions) {
int surfaceType = findConfigAttrib(egl, display, config,
EGL_SURFACE_TYPE, 0);
backBuffer = (surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) != 0;
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 26dab81..88bb9fc 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2617,8 +2617,8 @@
newHeight = 0;
heightWidthRatio = 0;
}
- // Actual visible height.
- int actualViewHeight = getViewHeight();
+ // Actual visible content height.
+ int actualViewHeight = Math.round(getViewHeight() * mZoomManager.getInvScale());
// Avoid sending another message if the dimensions have not changed.
if (newWidth != mLastWidthSent || newHeight != mLastHeightSent || force ||
actualViewHeight != mLastActualHeightSent) {
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index c7ae2cf..bd903da 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -200,8 +200,6 @@
* check if a bitmap has changed.
*
* @return The current generation ID for this bitmap.
- *
- * @hide
*/
public int getGenerationId() {
return nativeGenerationId(mNativeBitmap);
@@ -752,7 +750,7 @@
}
// Scale by tdensity / sdensity, rounding up.
- return ( (size * tdensity) + (sdensity >> 1) ) / sdensity;
+ return ((size * tdensity) + (sdensity >> 1)) / sdensity;
}
/**
@@ -790,14 +788,12 @@
/**
* Tell the bitmap if all of the pixels are known to be opaque (false)
* or if some of the pixels may contain non-opaque alpha values (true).
- * Note, for some configs (e.g. RGB_565) this call is ignore, since it does
- * not support per-pixel alpha values.
+ * Note, for some configs (e.g. RGB_565) this call is ignored, since it
+ * does not support per-pixel alpha values.
*
* This is meant as a drawing hint, as in some cases a bitmap that is known
* to be opaque can take a faster drawing case than one that may have
* non-opaque per-pixel alpha values.
- *
- * @hide
*/
public void setHasAlpha(boolean hasAlpha) {
nativeSetHasAlpha(mNativeBitmap, hasAlpha);
@@ -1066,13 +1062,9 @@
* Given another bitmap, return true if it has the same dimensions, config,
* and pixel data as this bitmap. If any of those differ, return false.
* If other is null, return false.
- *
- * @hide (just needed internally right now)
*/
public boolean sameAs(Bitmap other) {
- return this == other ||
- (other != null &&
- nativeSameAs(mNativeBitmap, other.mNativeBitmap));
+ return this == other || (other != null && nativeSameAs(mNativeBitmap, other.mNativeBitmap));
}
/**
@@ -1099,7 +1091,13 @@
@Override
public void finalize() {
- nativeDestructor(mNativeBitmap);
+ try {
+ super.finalize();
+ } catch (Throwable t) {
+ // Ignore
+ } finally {
+ nativeDestructor(mNativeBitmap);
+ }
}
}
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 82948cb..f7d837a 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -175,6 +175,7 @@
int64_t mSeekTimeUs;
ReadOptions::SeekMode mSeekMode;
int64_t mTargetTimeUs;
+ bool mOutputPortSettingsChangedPending;
MediaBuffer *mLeftOverBuffer;
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 247ace7..fccd68c 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1434,6 +1434,7 @@
mSeekTimeUs(-1),
mSeekMode(ReadOptions::SEEK_CLOSEST_SYNC),
mTargetTimeUs(-1),
+ mOutputPortSettingsChangedPending(false),
mLeftOverBuffer(NULL),
mPaused(false),
mNativeWindow(nativeWindow) {
@@ -2344,6 +2345,14 @@
drainInputBuffers();
fillOutputBuffers();
}
+
+ if (mOutputPortSettingsChangedPending) {
+ CODEC_LOGV(
+ "Honoring deferred output port settings change.");
+
+ mOutputPortSettingsChangedPending = false;
+ onPortSettingsChanged(kPortIndexOutput);
+ }
}
break;
@@ -2407,6 +2416,8 @@
CODEC_LOGV("Now Executing.");
+ mOutputPortSettingsChangedPending = false;
+
setState(EXECUTING);
// Buffers will be submitted to the component in the first
@@ -2520,6 +2531,14 @@
CHECK_EQ((int)mState, (int)EXECUTING);
CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
+ CHECK(!mOutputPortSettingsChangedPending);
+
+ if (mPortStatus[kPortIndexOutput] != ENABLED) {
+ CODEC_LOGV("Deferring output port settings change.");
+ mOutputPortSettingsChangedPending = true;
+ return;
+ }
+
setState(RECONFIGURING);
if (mQuirks & kNeedsFlushBeforeDisable) {
@@ -2712,6 +2731,7 @@
if (srcBuffer->meta_data()->findInt64(
kKeyTargetTime, &targetTimeUs)
&& targetTimeUs >= 0) {
+ CODEC_LOGV("targetTimeUs = %lld us", targetTimeUs);
mTargetTimeUs = targetTimeUs;
} else {
mTargetTimeUs = -1;
@@ -3385,6 +3405,14 @@
}
if (seeking) {
+ while (mState == RECONFIGURING) {
+ mBufferFilled.wait(mLock);
+ }
+
+ if (mState != EXECUTING) {
+ return UNKNOWN_ERROR;
+ }
+
CODEC_LOGV("seeking to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
mSignalledEOS = false;
diff --git a/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp b/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp
index 9433178..489e5ad 100644
--- a/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp
+++ b/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp
@@ -205,7 +205,9 @@
vpx_image_t *img = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter);
if (img == NULL) {
- LOGI("on2 decoder did not return a frame.");
+ // The VPX format supports "internal-only" frames that are
+ // referenced by future content but never actually displayed, so
+ // this is a perfectly valid scenario.
*out = new MediaBuffer(0);
return OK;
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 25030d8..8ec1fd4 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -878,7 +878,8 @@
InstrumentedInputReader(const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& policy,
const sp<InputDispatcherInterface>& dispatcher) :
- InputReader(eventHub, policy, dispatcher) {
+ InputReader(eventHub, policy, dispatcher),
+ mNextDevice(NULL) {
}
virtual ~InstrumentedInputReader() {