Merge "Avoid crashing in unlockCanvasAndPost" into klp-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
59210de17c
@@ -36,7 +36,7 @@ public class Surface implements Parcelable {
|
||||
throws OutOfResourcesException;
|
||||
private static native int nativeCreateFromSurfaceControl(int surfaceControlNativeObject);
|
||||
|
||||
private static native void nativeLockCanvas(int nativeObject, Canvas canvas, Rect dirty)
|
||||
private static native int nativeLockCanvas(int nativeObject, Canvas canvas, Rect dirty)
|
||||
throws OutOfResourcesException;
|
||||
private static native void nativeUnlockCanvasAndPost(int nativeObject, Canvas canvas);
|
||||
|
||||
@@ -72,6 +72,7 @@ public class Surface implements Parcelable {
|
||||
final Object mLock = new Object(); // protects the native state
|
||||
private String mName;
|
||||
int mNativeObject; // package scope only for SurfaceControl access
|
||||
private int mLockedObject;
|
||||
private int mGenerationId; // incremented each time mNativeObject changes
|
||||
private final Canvas mCanvas = new CompatibleCanvas();
|
||||
|
||||
@@ -233,7 +234,14 @@ public class Surface implements Parcelable {
|
||||
throws OutOfResourcesException, IllegalArgumentException {
|
||||
synchronized (mLock) {
|
||||
checkNotReleasedLocked();
|
||||
nativeLockCanvas(mNativeObject, mCanvas, inOutDirty);
|
||||
if (mLockedObject != 0) {
|
||||
// Ideally, nativeLockCanvas() would throw in this situation and prevent the
|
||||
// double-lock, but that won't happen if mNativeObject was updated. We can't
|
||||
// abandon the old mLockedObject because it might still be in use, so instead
|
||||
// we just refuse to re-lock the Surface.
|
||||
throw new RuntimeException("Surface was already locked");
|
||||
}
|
||||
mLockedObject = nativeLockCanvas(mNativeObject, mCanvas, inOutDirty);
|
||||
return mCanvas;
|
||||
}
|
||||
}
|
||||
@@ -252,11 +260,21 @@ public class Surface implements Parcelable {
|
||||
|
||||
synchronized (mLock) {
|
||||
checkNotReleasedLocked();
|
||||
nativeUnlockCanvasAndPost(mNativeObject, canvas);
|
||||
if (mNativeObject != mLockedObject) {
|
||||
Log.w(TAG, "WARNING: Surface's mNativeObject (0x" +
|
||||
Integer.toHexString(mNativeObject) + ") != mLockedObject (0x" +
|
||||
Integer.toHexString(mLockedObject) +")");
|
||||
}
|
||||
if (mLockedObject == 0) {
|
||||
throw new RuntimeException("Surface was not locked");
|
||||
}
|
||||
nativeUnlockCanvasAndPost(mLockedObject, canvas);
|
||||
nativeRelease(mLockedObject);
|
||||
mLockedObject = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @deprecated This API has been removed and is not supported. Do not use.
|
||||
*/
|
||||
@Deprecated
|
||||
@@ -343,6 +361,10 @@ public class Surface implements Parcelable {
|
||||
}
|
||||
|
||||
synchronized (mLock) {
|
||||
// nativeReadFromParcel() will either return mNativeObject, or
|
||||
// create a new native Surface and return it after reducing
|
||||
// the reference count on mNativeObject. Either way, it is
|
||||
// not necessary to call nativeRelease() here.
|
||||
mName = source.readString();
|
||||
setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
|
||||
}
|
||||
@@ -365,7 +387,8 @@ public class Surface implements Parcelable {
|
||||
@Override
|
||||
public String toString() {
|
||||
synchronized (mLock) {
|
||||
return "Surface(name=" + mName + ")";
|
||||
return "Surface(name=" + mName + ")/@0x" +
|
||||
Integer.toHexString(System.identityHashCode(this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,7 +486,7 @@ public class Surface implements Parcelable {
|
||||
public void getMatrix(Matrix m) {
|
||||
super.getMatrix(m);
|
||||
if (mOrigMatrix == null) {
|
||||
mOrigMatrix = new Matrix();
|
||||
mOrigMatrix = new Matrix();
|
||||
}
|
||||
mOrigMatrix.set(m);
|
||||
}
|
||||
|
||||
@@ -196,13 +196,13 @@ static inline void swapCanvasPtr(JNIEnv* env, jobject canvasObj, SkCanvas* newCa
|
||||
SkSafeUnref(previousCanvas);
|
||||
}
|
||||
|
||||
static void nativeLockCanvas(JNIEnv* env, jclass clazz,
|
||||
static jint nativeLockCanvas(JNIEnv* env, jclass clazz,
|
||||
jint nativeObject, jobject canvasObj, jobject dirtyRectObj) {
|
||||
sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
|
||||
|
||||
if (!isSurfaceValid(surface)) {
|
||||
doThrowIAE(env);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Rect dirtyRect;
|
||||
@@ -223,7 +223,7 @@ static void nativeLockCanvas(JNIEnv* env, jclass clazz,
|
||||
OutOfResourcesException :
|
||||
"java/lang/IllegalArgumentException";
|
||||
jniThrowException(env, exception, NULL);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Associate a SkCanvas object to this surface
|
||||
@@ -255,6 +255,13 @@ static void nativeLockCanvas(JNIEnv* env, jclass clazz,
|
||||
env->SetIntField(dirtyRectObj, gRectClassInfo.right, dirtyRect.right);
|
||||
env->SetIntField(dirtyRectObj, gRectClassInfo.bottom, dirtyRect.bottom);
|
||||
}
|
||||
|
||||
// Create another reference to the surface and return it. This reference
|
||||
// should be passed to nativeUnlockCanvasAndPost in place of mNativeObject,
|
||||
// because the latter could be replaced while the surface is locked.
|
||||
sp<Surface> lockedSurface(surface);
|
||||
lockedSurface->incStrong(&sRefBaseOwner);
|
||||
return (int) lockedSurface.get();
|
||||
}
|
||||
|
||||
static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz,
|
||||
@@ -351,7 +358,7 @@ static JNINativeMethod gSurfaceMethods[] = {
|
||||
(void*)nativeIsValid },
|
||||
{"nativeIsConsumerRunningBehind", "(I)Z",
|
||||
(void*)nativeIsConsumerRunningBehind },
|
||||
{"nativeLockCanvas", "(ILandroid/graphics/Canvas;Landroid/graphics/Rect;)V",
|
||||
{"nativeLockCanvas", "(ILandroid/graphics/Canvas;Landroid/graphics/Rect;)I",
|
||||
(void*)nativeLockCanvas },
|
||||
{"nativeUnlockCanvasAndPost", "(ILandroid/graphics/Canvas;)V",
|
||||
(void*)nativeUnlockCanvasAndPost },
|
||||
|
||||
Reference in New Issue
Block a user