diff options
author | Ted Bonkenburg <tedbo@google.com> | 2011-07-25 10:24:30 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-07-25 10:24:30 -0700 |
commit | 5518dd92d38edd5902482841413722aa654cc2e7 (patch) | |
tree | 8fed33fc854d72b0000c8ad99565f8377c7e6607 | |
parent | 63d050034df5eedc9586e393d56444cd34681bd1 (diff) | |
parent | 0de171b0d490a5928d54d2fb67c912d140aac643 (diff) | |
download | frameworks_base-5518dd92d38edd5902482841413722aa654cc2e7.zip frameworks_base-5518dd92d38edd5902482841413722aa654cc2e7.tar.gz frameworks_base-5518dd92d38edd5902482841413722aa654cc2e7.tar.bz2 |
Merge "Add support for creating a Surface from a a SurfaceTexture."
-rw-r--r-- | core/java/android/view/Surface.java | 18 | ||||
-rw-r--r-- | core/jni/android_view_Surface.cpp | 36 | ||||
-rw-r--r-- | include/surfaceflinger/Surface.h | 7 | ||||
-rw-r--r-- | libs/gui/Surface.cpp | 56 | ||||
-rw-r--r-- | media/java/android/media/MediaPlayer.java | 29 |
5 files changed, 124 insertions, 22 deletions
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index c913bb3..836867b 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -161,6 +161,9 @@ public class Surface implements Parcelable { */ public static final int FLAGS_ORIENTATION_ANIMATION_DISABLE = 0x000000001; + // The mSurfaceControl will only be present for Surfaces used by the window + // server or system processes. When this class is parceled we defer to the + // mSurfaceControl to do the parceling. Otherwise we parcel the mNativeSurface. @SuppressWarnings("unused") private int mSurfaceControl; @SuppressWarnings("unused") @@ -202,6 +205,19 @@ public class Surface implements Parcelable { native private static void nativeClassInit(); static { nativeClassInit(); } + /** + * Create Surface from a SurfaceTexture. + * + * @param surfaceTexture The {@link SurfaceTexture} that is updated by this Surface. + * @hide + */ + public Surface(SurfaceTexture surfaceTexture) { + if (DEBUG_RELEASE) { + mCreationStack = new Exception(); + } + mCanvas = new CompatibleCanvas(); + initFromSurfaceTexture(surfaceTexture); + } /** * create a surface @@ -505,5 +521,7 @@ public class Surface implements Parcelable { private native void init(Parcel source); + private native void initFromSurfaceTexture(SurfaceTexture surfaceTexture); + private native int getIdentity(); } diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 0dc9293..4c1ca31 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -22,6 +22,7 @@ #include "android/graphics/GraphicsJNI.h" #include <binder/IMemory.h> +#include <gui/SurfaceTexture.h> #include <surfaceflinger/SurfaceComposerClient.h> #include <surfaceflinger/Surface.h> #include <ui/Region.h> @@ -38,6 +39,7 @@ #include "JNIHelp.h" #include <android_runtime/AndroidRuntime.h> #include <android_runtime/android_view_Surface.h> +#include <android_runtime/android_graphics_SurfaceTexture.h> #include <utils/misc.h> @@ -244,6 +246,19 @@ static void Surface_init( setSurfaceControl(env, clazz, surface); } +static void Surface_initFromSurfaceTexture( + JNIEnv* env, jobject clazz, jobject jst) +{ + sp<ISurfaceTexture> st(SurfaceTexture_getSurfaceTexture(env, jst)); + sp<Surface> surface(new Surface(st)); + if (surface == NULL) { + jniThrowException(env, OutOfResourcesException, NULL); + return; + } + setSurfaceControl(env, clazz, NULL); + setSurface(env, clazz, surface); +} + static void Surface_initParcel(JNIEnv* env, jobject clazz, jobject argParcel) { Parcel* parcel = (Parcel*)env->GetIntField(argParcel, no.native_parcel); @@ -761,10 +776,26 @@ static void Surface_writeToParcel( return; } + // The Java instance may have a SurfaceControl (in the case of the + // WindowManager or a system app). In that case, we defer to the + // SurfaceControl to send its ISurface. Otherwise, if the Surface is + // available we let it parcel itself. Finally, if the Surface is also + // NULL we fall back to using the SurfaceControl path which sends an + // empty surface; this matches legacy behavior. const sp<SurfaceControl>& control(getSurfaceControl(env, clazz)); - SurfaceControl::writeSurfaceToParcel(control, parcel); + if (control != NULL) { + SurfaceControl::writeSurfaceToParcel(control, parcel); + } else { + sp<Surface> surface(Surface_getSurface(env, clazz)); + if (surface != NULL) { + Surface::writeToParcel(surface, parcel); + } else { + SurfaceControl::writeSurfaceToParcel(NULL, parcel); + } + } if (flags & PARCELABLE_WRITE_RETURN_VALUE) { - setSurfaceControl(env, clazz, 0); + setSurfaceControl(env, clazz, NULL); + setSurface(env, clazz, NULL); } } @@ -784,6 +815,7 @@ static JNINativeMethod gSurfaceMethods[] = { {"nativeClassInit", "()V", (void*)nativeClassInit }, {"init", "(Landroid/view/SurfaceSession;ILjava/lang/String;IIIII)V", (void*)Surface_init }, {"init", "(Landroid/os/Parcel;)V", (void*)Surface_initParcel }, + {"initFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)V", (void*)Surface_initFromSurfaceTexture }, {"getIdentity", "()I", (void*)Surface_getIdentity }, {"destroy", "()V", (void*)Surface_destroy }, {"release", "()V", (void*)Surface_release }, diff --git a/include/surfaceflinger/Surface.h b/include/surfaceflinger/Surface.h index 9c352ad..0460bbd 100644 --- a/include/surfaceflinger/Surface.h +++ b/include/surfaceflinger/Surface.h @@ -122,7 +122,10 @@ public: uint32_t reserved[2]; }; + explicit Surface(const sp<ISurfaceTexture>& st); + static status_t writeToParcel(const sp<Surface>& control, Parcel* parcel); + static sp<Surface> readFromParcel(const Parcel& data); static bool isValid(const sp<Surface>& surface) { return (surface != 0) && surface->isValid(); @@ -147,14 +150,14 @@ private: Surface& operator = (Surface& rhs); Surface(const Surface& rhs); - Surface(const sp<SurfaceControl>& control); + explicit Surface(const sp<SurfaceControl>& control); Surface(const Parcel& data, const sp<IBinder>& ref); ~Surface(); /* * private stuff... */ - void init(); + void init(const sp<ISurfaceTexture>& surfaceTexture); static void cleanCachedSurfacesLocked(); diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index c4f9e53..ccf98e5 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -184,6 +184,7 @@ status_t SurfaceControl::writeSurfaceToParcel( identity = control->mIdentity; } parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL); + parcel->writeStrongBinder(NULL); // NULL ISurfaceTexture in this case. parcel->writeInt32(identity); return NO_ERROR; } @@ -192,7 +193,8 @@ sp<Surface> SurfaceControl::getSurface() const { Mutex::Autolock _l(mLock); if (mSurfaceData == 0) { - mSurfaceData = new Surface(const_cast<SurfaceControl*>(this)); + sp<SurfaceControl> surface_control(const_cast<SurfaceControl*>(this)); + mSurfaceData = new Surface(surface_control); } return mSurfaceData; } @@ -208,31 +210,58 @@ Surface::Surface(const sp<SurfaceControl>& surface) mSurface(surface->mSurface), mIdentity(surface->mIdentity) { - init(); + sp<ISurfaceTexture> st; + if (mSurface != NULL) { + st = mSurface->getSurfaceTexture(); + } + init(st); } Surface::Surface(const Parcel& parcel, const sp<IBinder>& ref) : SurfaceTextureClient() { - mSurface = interface_cast<ISurface>(ref); + mSurface = interface_cast<ISurface>(ref); + sp<IBinder> st_binder(parcel.readStrongBinder()); + sp<ISurfaceTexture> st; + if (st_binder != NULL) { + st = interface_cast<ISurfaceTexture>(st_binder); + } else if (mSurface != NULL) { + st = mSurface->getSurfaceTexture(); + } + mIdentity = parcel.readInt32(); - init(); + init(st); +} + +Surface::Surface(const sp<ISurfaceTexture>& st) + : SurfaceTextureClient(), + mSurface(NULL), + mIdentity(0) +{ + init(st); } status_t Surface::writeToParcel( const sp<Surface>& surface, Parcel* parcel) { sp<ISurface> sur; + sp<ISurfaceTexture> st; uint32_t identity = 0; if (Surface::isValid(surface)) { sur = surface->mSurface; + st = surface->getISurfaceTexture(); identity = surface->mIdentity; - } else if (surface != 0 && surface->mSurface != 0) { - LOGW("Parceling invalid surface with non-NULL ISurface as NULL: " - "mSurface = %p, mIdentity = %d", - surface->mSurface.get(), surface->mIdentity); + } else if (surface != 0 && + (surface->mSurface != NULL || + surface->getISurfaceTexture() != NULL)) { + LOGE("Parceling invalid surface with non-NULL ISurface/ISurfaceTexture as NULL: " + "mSurface = %p, surfaceTexture = %p, mIdentity = %d, ", + surface->mSurface.get(), surface->getISurfaceTexture().get(), + surface->mIdentity); } - parcel->writeStrongBinder(sur!=0 ? sur->asBinder() : NULL); + + parcel->writeStrongBinder(sur != NULL ? sur->asBinder() : NULL); + parcel->writeStrongBinder(st != NULL ? st->asBinder() : NULL); parcel->writeInt32(identity); return NO_ERROR; @@ -249,8 +278,8 @@ sp<Surface> Surface::readFromParcel(const Parcel& data) { surface = new Surface(data, binder); sCachedSurfaces.add(binder, surface); } - if (surface->mSurface == 0) { - surface = 0; + if (surface->mSurface == NULL && surface->getISurfaceTexture() == NULL) { + surface = 0; } cleanCachedSurfacesLocked(); return surface; @@ -267,10 +296,9 @@ void Surface::cleanCachedSurfacesLocked() { } } -void Surface::init() +void Surface::init(const sp<ISurfaceTexture>& surfaceTexture) { - if (mSurface != NULL) { - sp<ISurfaceTexture> surfaceTexture(mSurface->getSurfaceTexture()); + if (mSurface != NULL || surfaceTexture != NULL) { LOGE_IF(surfaceTexture==0, "got a NULL ISurfaceTexture from ISurface"); if (surfaceTexture != NULL) { setISurfaceTexture(surfaceTexture); diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index 482b437..95671bc 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -611,7 +611,7 @@ public class MediaPlayer * needed. Not calling this method when playing back a video will * result in only the audio track being played. * - * Either a surface or surface texture must be set if a display or video sink + * Either a surface holder or surface must be set if a display or video sink * is needed. Not calling this method or {@link #setTexture(SurfaceTexture)} * when playing back a video will result in only the audio track being played. * @@ -630,6 +630,27 @@ public class MediaPlayer } /** + * Sets the {@link Surface} to be used as the sink for the video portion of + * the media. This is similar to {@link #setDisplay(SurfaceHolder)}, but does not + * support {@link #setScreenOnWhilePlaying(boolean)} or {@link #updateSurfaceScreenOn()}. + * Setting a Surface will un-set any Surface or SurfaceHolder that was previously set. + * + * @param surface The {@link Surface} to be used for the video portion of the media. + * + * @hide Pending review by API council. + */ + public void setSurface(Surface surface) { + if (mScreenOnWhilePlaying && surface != null && mSurface != null) { + Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for Surface"); + } + mSurfaceHolder = null; + mSurface = surface; + mParcelSurfaceTexture = null; // TODO(tedbo): Remove. + _setVideoSurfaceOrSurfaceTexture(); + updateSurfaceScreenOn(); + } + + /** * Sets the {@link SurfaceTexture} to be used as the sink for the * video portion of the media. Either a surface or surface texture * must be set if a video sink is needed. The same surface texture @@ -665,7 +686,7 @@ public class MediaPlayer * @param pst The {@link ParcelSurfaceTexture} to be used as the sink for * the video portion of the media. * - * @hide Pending review by API council. + * @hide Pending removal when there are no more callers. */ public void setParcelSurfaceTexture(ParcelSurfaceTexture pst) { if (mScreenOnWhilePlaying && pst != null && mParcelSurfaceTexture == null) { @@ -1000,8 +1021,8 @@ public class MediaPlayer */ public void setScreenOnWhilePlaying(boolean screenOn) { if (mScreenOnWhilePlaying != screenOn) { - if (screenOn && mParcelSurfaceTexture != null) { - Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for SurfaceTexture"); + if (screenOn && mSurfaceHolder == null) { + Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective without a SurfaceHolder"); } mScreenOnWhilePlaying = screenOn; updateSurfaceScreenOn(); |