Merge changes I61ae54f3,I57cb668e,I7a3f1e1a,Id28a2f9b into jb-mr2-dev
* changes:
Add BufferQueueInterposer and use it for virtual displays
Add DisplaySurface abstraction
Fix argument types in IGraphicBufferProducer methods
Minor cleanups/fixes before virtual display refactoring
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 26c2d1c..29838e4 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -117,6 +117,7 @@
static bool g_compress = false;
static bool g_nohup = false;
static int g_initialSleepSecs = 0;
+static const char* g_kernelTraceFuncs = NULL;
/* Global state */
static bool g_traceAborted = false;
@@ -132,6 +133,30 @@
static const char* k_tracingOverwriteEnablePath =
"/sys/kernel/debug/tracing/options/overwrite";
+static const char* k_currentTracerPath =
+ "/sys/kernel/debug/tracing/current_tracer";
+
+static const char* k_printTgidPath =
+ "/sys/kernel/debug/tracing/options/print-tgid";
+
+static const char* k_funcgraphAbsTimePath =
+ "/sys/kernel/debug/tracing/options/funcgraph-abstime";
+
+static const char* k_funcgraphCpuPath =
+ "/sys/kernel/debug/tracing/options/funcgraph-cpu";
+
+static const char* k_funcgraphProcPath =
+ "/sys/kernel/debug/tracing/options/funcgraph-proc";
+
+static const char* k_funcgraphFlatPath =
+ "/sys/kernel/debug/tracing/options/funcgraph-flat";
+
+static const char* k_funcgraphDurationPath =
+ "/sys/kernel/debug/tracing/options/funcgraph-duration";
+
+static const char* k_ftraceFilterPath =
+ "/sys/kernel/debug/tracing/set_ftrace_filter";
+
static const char* k_tracingOnPath =
"/sys/kernel/debug/tracing/tracing_on";
@@ -148,10 +173,22 @@
return access(filename, W_OK) != -1;
}
-// Write a string to a file, returning true if the write was successful.
-static bool writeStr(const char* filename, const char* str)
+// Truncate a file.
+static bool truncateFile(const char* path)
{
- int fd = open(filename, O_WRONLY);
+ int err = truncate(path, 0);
+ if (err != 0) {
+ fprintf(stderr, "error truncating %s: %s (%d)\n", path,
+ strerror(errno), errno);
+ return false;
+ }
+
+ return true;
+}
+
+static bool _writeStr(const char* filename, const char* str, int flags)
+{
+ int fd = open(filename, flags);
if (fd == -1) {
fprintf(stderr, "error opening %s: %s (%d)\n", filename,
strerror(errno), errno);
@@ -171,6 +208,18 @@
return ok;
}
+// Write a string to a file, returning true if the write was successful.
+static bool writeStr(const char* filename, const char* str)
+{
+ return _writeStr(filename, str, O_WRONLY);
+}
+
+// Append a string to a file, returning true if the write was successful.
+static bool appendStr(const char* filename, const char* str)
+{
+ return _writeStr(filename, str, O_APPEND|O_WRONLY);
+}
+
// Enable or disable a kernel option by writing a "1" or a "0" into a /sys
// file.
static bool setKernelOptionEnable(const char* filename, bool enable)
@@ -244,16 +293,7 @@
// Clear the contents of the kernel trace.
static bool clearTrace()
{
- int traceFD = creat(k_tracePath, 0);
- if (traceFD == -1) {
- fprintf(stderr, "error truncating %s: %s (%d)\n", k_tracePath,
- strerror(errno), errno);
- return false;
- }
-
- close(traceFD);
-
- return true;
+ return truncateFile(k_tracePath);
}
// Set the size of the kernel's trace buffer in kilobytes.
@@ -275,6 +315,14 @@
return writeStr(k_traceClockPath, enable ? "global" : "local");
}
+static bool setPrintTgidEnableIfPresent(bool enable)
+{
+ if (fileExists(k_printTgidPath)) {
+ return setKernelOptionEnable(k_printTgidPath, enable);
+ }
+ return true;
+}
+
// Poke all the binder-enabled processes in the system to get them to re-read
// their system properties.
static bool pokeBinderServices()
@@ -330,8 +378,90 @@
return ok;
}
-// Enable tracing in the kernel.
-static bool startTrace()
+// Verify that the comma separated list of functions are being traced by the
+// kernel.
+static bool verifyKernelTraceFuncs(const char* funcs)
+{
+ int fd = open(k_ftraceFilterPath, O_RDONLY);
+ if (fd == -1) {
+ fprintf(stderr, "error opening %s: %s (%d)\n", k_ftraceFilterPath,
+ strerror(errno), errno);
+ return false;
+ }
+
+ char buf[4097];
+ ssize_t n = read(fd, buf, 4096);
+ close(fd);
+ if (n == -1) {
+ fprintf(stderr, "error reading %s: %s (%d)\n", k_ftraceFilterPath,
+ strerror(errno), errno);
+ return false;
+ }
+
+ buf[n] = '\0';
+ String8 funcList = String8::format("\n%s", buf);
+
+ // Make sure that every function listed in funcs is in the list we just
+ // read from the kernel.
+ bool ok = true;
+ char* myFuncs = strdup(funcs);
+ char* func = strtok(myFuncs, ",");
+ while (func) {
+ String8 fancyFunc = String8::format("\n%s\n", func);
+ bool found = funcList.find(fancyFunc.string(), 0) >= 0;
+ if (!found || func[0] == '\0') {
+ fprintf(stderr, "error: \"%s\" is not a valid kernel function "
+ "to trace.\n", func);
+ ok = false;
+ }
+ func = strtok(NULL, ",");
+ }
+ free(myFuncs);
+
+ return ok;
+}
+
+// Set the comma separated list of functions that the kernel is to trace.
+static bool setKernelTraceFuncs(const char* funcs)
+{
+ bool ok = true;
+
+ if (funcs == NULL || funcs[0] == '\0') {
+ // Disable kernel function tracing.
+ ok &= writeStr(k_currentTracerPath, "nop");
+ if (fileExists(k_ftraceFilterPath)) {
+ ok &= truncateFile(k_ftraceFilterPath);
+ }
+ } else {
+ // Enable kernel function tracing.
+ ok &= writeStr(k_currentTracerPath, "function_graph");
+ ok &= setKernelOptionEnable(k_funcgraphAbsTimePath, true);
+ ok &= setKernelOptionEnable(k_funcgraphCpuPath, true);
+ ok &= setKernelOptionEnable(k_funcgraphProcPath, true);
+ ok &= setKernelOptionEnable(k_funcgraphFlatPath, true);
+
+ // Set the requested filter functions.
+ ok &= truncateFile(k_ftraceFilterPath);
+ char* myFuncs = strdup(funcs);
+ char* func = strtok(myFuncs, ",");
+ while (func) {
+ ok &= appendStr(k_ftraceFilterPath, func);
+ func = strtok(NULL, ",");
+ }
+ free(myFuncs);
+
+ // Verify that the set functions are being traced.
+ if (ok) {
+ ok &= verifyKernelTraceFuncs(funcs);
+ }
+ }
+
+ return ok;
+}
+
+// Set all the kernel tracing settings to the desired state for this trace
+// capture.
+static bool setUpTrace()
{
bool ok = true;
@@ -339,6 +469,8 @@
ok &= setTraceOverwriteEnable(g_traceOverwrite);
ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
ok &= setGlobalClockEnable(true);
+ ok &= setPrintTgidEnableIfPresent(true);
+ ok &= setKernelTraceFuncs(g_kernelTraceFuncs);
// Set up the tags property.
uint64_t tags = 0;
@@ -373,18 +505,12 @@
}
}
- // Enable tracing.
- ok &= setTracingEnabled(true);
-
return ok;
}
-// Disable tracing in the kernel.
-static void stopTrace()
+// Reset all the kernel tracing settings to their default state.
+static void cleanUpTrace()
{
- // Disable tracing.
- setTracingEnabled(false);
-
// Disable all tracing that we're able to.
disableKernelTraceEvents();
@@ -393,10 +519,23 @@
// Set the options back to their defaults.
setTraceOverwriteEnable(true);
+ setTraceBufferSizeKB(1);
setGlobalClockEnable(false);
+ setPrintTgidEnableIfPresent(false);
+ setKernelTraceFuncs(NULL);
+}
- // Note that we can't reset the trace buffer size here because that would
- // clear the trace before we've read it.
+
+// Enable tracing in the kernel.
+static bool startTrace()
+{
+ return setTracingEnabled(true);
+}
+
+// Disable tracing in the kernel.
+static void stopTrace()
+{
+ setTracingEnabled(false);
}
// Read the current kernel trace and write it to stdout.
@@ -556,6 +695,7 @@
fprintf(stderr, "options include:\n"
" -b N use a trace buffer size of N KB\n"
" -c trace into a circular buffer\n"
+ " -k fname,... trace the listed kernel functions\n"
" -n ignore signals\n"
" -s N sleep for N seconds before tracing [default 0]\n"
" -t N trace for N seconds [defualt 5]\n"
@@ -592,7 +732,7 @@
{ 0, 0, 0, 0 }
};
- ret = getopt_long(argc, argv, "b:cns:t:z",
+ ret = getopt_long(argc, argv, "b:ck:ns:t:z",
long_options, &option_index);
if (ret < 0) {
@@ -614,6 +754,10 @@
g_traceOverwrite = true;
break;
+ case 'k':
+ g_kernelTraceFuncs = optarg;
+ break;
+
case 'n':
g_nohup = true;
break;
@@ -663,7 +807,9 @@
sleep(g_initialSleepSecs);
}
- bool ok = startTrace();
+ bool ok = true;
+ ok &= setUpTrace();
+ ok &= startTrace();
if (ok && traceStart) {
printf("capturing trace...");
@@ -709,7 +855,7 @@
// Reset the trace buffer size to 1.
if (traceStop)
- setTraceBufferSizeKB(1);
+ cleanUpTrace();
return g_traceAborted ? 1 : 0;
}
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 08eddcb..47f9552 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -103,16 +103,23 @@
uint32_t reqWidth, uint32_t reqHeight,
uint32_t minLayerZ, uint32_t maxLayerZ) = 0;
- /* triggers screen off and waits for it to complete */
+ /* triggers screen off and waits for it to complete
+ * requires ACCESS_SURFACE_FLINGER permission.
+ */
virtual void blank(const sp<IBinder>& display) = 0;
- /* triggers screen on and waits for it to complete */
+ /* triggers screen on and waits for it to complete
+ * requires ACCESS_SURFACE_FLINGER permission.
+ */
virtual void unblank(const sp<IBinder>& display) = 0;
/* returns information about a display
* intended to be used to get information about built-in displays */
virtual status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) = 0;
+ /* Capture the specified screen. requires READ_FRAME_BUFFER permission
+ * This function will fail if there is a secure window on screen.
+ */
virtual status_t captureScreen(const sp<IBinder>& display,
const sp<IGraphicBufferProducer>& producer,
uint32_t reqWidth, uint32_t reqHeight,
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 5996c90..1677c76 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -108,7 +108,7 @@
void Layer::onFirstRef()
{
// Creates a custom BufferQueue for SurfaceFlingerConsumer to use
- sp<BufferQueue> bq = new SurfaceTextureLayer();
+ sp<BufferQueue> bq = new SurfaceTextureLayer(mFlinger);
mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(mTextureName, true,
GL_TEXTURE_EXTERNAL_OES, false, bq);
@@ -153,8 +153,9 @@
mFlinger->signalLayerUpdate();
}
-// called with SurfaceFlinger::mStateLock as soon as the layer is entered
-// in the purgatory list
+// called with SurfaceFlinger::mStateLock from the drawing thread after
+// the layer has been remove from the current state list (and just before
+// it's removed from the drawing state list)
void Layer::onRemoved() {
mSurfaceFlingerConsumer->abandon();
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 88c7fa0..7fcbd2e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -573,39 +573,7 @@
const sp<IGraphicBufferProducer>& bufferProducer) const {
Mutex::Autolock _l(mStateLock);
sp<IBinder> surfaceTextureBinder(bufferProducer->asBinder());
-
- // We want to determine whether the IGraphicBufferProducer was created by
- // SurfaceFlinger. Check to see if we can find it in the layer list.
- const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
- size_t count = currentLayers.size();
- for (size_t i=0 ; i<count ; i++) {
- const sp<Layer>& layer(currentLayers[i]);
- // Get the consumer interface of SurfaceFlingerConsumer's
- // BufferQueue. If it's the same Binder object as the graphic
- // buffer producer interface, return success.
- sp<IBinder> lbcBinder = layer->getBufferQueue()->asBinder();
- if (lbcBinder == surfaceTextureBinder) {
- return true;
- }
- }
-
- // Check the layers in the purgatory. This check is here so that if a
- // GLConsumer gets destroyed before all the clients are done using it,
- // the error will not be reported as "surface XYZ is not authenticated", but
- // will instead fail later on when the client tries to use the surface,
- // which should be reported as "surface XYZ returned an -ENODEV". The
- // purgatorized layers are no less authentic than the visible ones, so this
- // should not cause any harm.
- size_t purgatorySize = mLayerPurgatory.size();
- for (size_t i=0 ; i<purgatorySize ; i++) {
- const sp<Layer>& layer(mLayerPurgatory.itemAt(i));
- sp<IBinder> lbcBinder = layer->getBufferQueue()->asBinder();
- if (lbcBinder == surfaceTextureBinder) {
- return true;
- }
- }
-
- return false;
+ return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0;
}
status_t SurfaceFlinger::getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) {
@@ -1674,6 +1642,7 @@
void SurfaceFlinger::addClientLayer(const sp<Client>& client,
const sp<IBinder>& handle,
+ const sp<IGraphicBufferProducer>& gbc,
const sp<Layer>& lbc)
{
// attach this layer to the client
@@ -1682,45 +1651,22 @@
// add this layer to the current state list
Mutex::Autolock _l(mStateLock);
mCurrentState.layersSortedByZ.add(lbc);
+ mGraphicBufferProducerList.add(gbc->asBinder());
}
status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer)
{
Mutex::Autolock _l(mStateLock);
- status_t err = purgatorizeLayer_l(layer);
- if (err == NO_ERROR)
- setTransactionFlags(eTransactionNeeded);
- return err;
-}
-
-status_t SurfaceFlinger::removeLayer_l(const sp<Layer>& layer)
-{
ssize_t index = mCurrentState.layersSortedByZ.remove(layer);
if (index >= 0) {
+ mLayersPendingRemoval.push(layer);
mLayersRemoved = true;
+ setTransactionFlags(eTransactionNeeded);
return NO_ERROR;
}
return status_t(index);
}
-status_t SurfaceFlinger::purgatorizeLayer_l(const sp<Layer>& layer)
-{
- // First add the layer to the purgatory list, which makes sure it won't
- // go away, then remove it from the main list (through a transaction).
- ssize_t err = removeLayer_l(layer);
- if (err >= 0) {
- mLayerPurgatory.add(layer);
- }
-
- mLayersPendingRemoval.push(layer);
-
- // it's possible that we don't find a layer, because it might
- // have been destroyed already -- this is not technically an error
- // from the user because there is a race between Client::destroySurface(),
- // ~Client() and ~LayerCleaner().
- return (err == NAME_NOT_FOUND) ? status_t(NO_ERROR) : err;
-}
-
uint32_t SurfaceFlinger::peekTransactionFlags(uint32_t flags)
{
return android_atomic_release_load(&mTransactionFlags);
@@ -1955,7 +1901,7 @@
}
if (result == NO_ERROR) {
- addClientLayer(client, *handle, layer);
+ addClientLayer(client, *handle, *gbp, layer);
setTransactionFlags(eTransactionNeeded);
}
return result;
@@ -2008,44 +1954,25 @@
status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle)
{
- /*
- * called by the window manager, when a surface should be marked for
- * destruction.
- *
- * The surface is removed from the current and drawing lists, but placed
- * in the purgatory queue, so it's not destroyed right-away (we need
- * to wait for all client's references to go away first).
- */
-
- status_t err = NAME_NOT_FOUND;
- Mutex::Autolock _l(mStateLock);
- sp<Layer> layer = client->getLayerUser(handle);
-
- if (layer != 0) {
- err = purgatorizeLayer_l(layer);
- if (err == NO_ERROR) {
- setTransactionFlags(eTransactionNeeded);
- }
+ // called by the window manager when it wants to remove a Layer
+ status_t err = NO_ERROR;
+ sp<Layer> l(client->getLayerUser(handle));
+ if (l != NULL) {
+ err = removeLayer(l);
+ ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
+ "error removing layer=%p (%s)", l.get(), strerror(-err));
}
return err;
}
status_t SurfaceFlinger::onLayerDestroyed(const wp<Layer>& layer)
{
- // called by ~LayerCleaner() when all references are gone
+ // called by ~LayerCleaner() when all references to the IBinder (handle)
+ // are gone
status_t err = NO_ERROR;
sp<Layer> l(layer.promote());
if (l != NULL) {
- Mutex::Autolock _l(mStateLock);
- err = removeLayer_l(l);
- if (err == NAME_NOT_FOUND) {
- // The surface wasn't in the current list, which means it was
- // removed already, which means it is in the purgatory,
- // and need to be removed from there.
- ssize_t idx = mLayerPurgatory.remove(l);
- ALOGE_IF(idx < 0,
- "layer=%p is not in the purgatory list", l.get());
- }
+ err = removeLayer(l);
ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
"error removing layer=%p (%s)", l.get(), strerror(-err));
}
@@ -2357,18 +2284,6 @@
}
/*
- * Dump the layers in the purgatory
- */
-
- const size_t purgatorySize = mLayerPurgatory.size();
- snprintf(buffer, SIZE, "Purgatory state (%d entries)\n", purgatorySize);
- result.append(buffer);
- for (size_t i=0 ; i<purgatorySize ; i++) {
- const sp<Layer>& layer(mLayerPurgatory.itemAt(i));
- layer->shortDump(result, buffer, SIZE);
- }
-
- /*
* Dump Display state
*/
@@ -2482,6 +2397,7 @@
{
switch (code) {
case CREATE_CONNECTION:
+ case CREATE_DISPLAY:
case SET_TRANSACTION_STATE:
case BOOT_FINISHED:
case BLANK:
@@ -2500,6 +2416,7 @@
break;
}
case CAPTURE_SCREEN:
+ case CAPTURE_SCREEN_DEPRECATED:
{
// codes that require permission check
IPCThreadState* ipc = IPCThreadState::self();
@@ -2717,9 +2634,11 @@
const Layer::State& state(layer->drawingState());
if (state.layerStack == hw->getLayerStack()) {
if (state.z >= minLayerZ && state.z <= maxLayerZ) {
- if (filtering) layer->setFiltering(true);
- layer->draw(hw);
- if (filtering) layer->setFiltering(false);
+ if (layer->isVisible()) {
+ if (filtering) layer->setFiltering(true);
+ layer->draw(hw);
+ if (filtering) layer->setFiltering(false);
+ }
}
}
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index f124347..e6734d2 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -128,6 +128,7 @@
friend class Client;
friend class DisplayEventConnection;
friend class Layer;
+ friend class SurfaceTextureLayer;
// We're reference counted, never destroy SurfaceFlinger directly
virtual ~SurfaceFlinger();
@@ -272,8 +273,6 @@
// called in response to the window-manager calling
// ISurfaceComposerClient::destroySurface()
- // The specified layer is first placed in a purgatory list
- // until all references from the client are released.
status_t onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle);
// called when all clients have released all their references to
@@ -285,11 +284,10 @@
status_t removeLayer(const sp<Layer>& layer);
// add a layer to SurfaceFlinger
- void addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
- const sp<Layer>& lbc);
-
- status_t removeLayer_l(const sp<Layer>& layer);
- status_t purgatorizeLayer_l(const sp<Layer>& layer);
+ void addClientLayer(const sp<Client>& client,
+ const sp<IBinder>& handle,
+ const sp<IGraphicBufferProducer>& gbc,
+ const sp<Layer>& lbc);
/* ------------------------------------------------------------------------
* Boot animation, on/off animations and screen capture
@@ -403,10 +401,10 @@
State mCurrentState;
volatile int32_t mTransactionFlags;
Condition mTransactionCV;
- SortedVector< sp<Layer> > mLayerPurgatory;
bool mTransactionPending;
bool mAnimTransactionPending;
Vector< sp<Layer> > mLayersPendingRemoval;
+ SortedVector< wp<IBinder> > mGraphicBufferProducerList;
// protected by mStateLock (but we could use another lock)
bool mLayersRemoved;
diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp
index 395c8c8..d0f0dae 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.cpp
+++ b/services/surfaceflinger/SurfaceTextureLayer.cpp
@@ -20,17 +20,35 @@
#include <utils/Errors.h>
+#include "SurfaceFlinger.h"
#include "SurfaceTextureLayer.h"
namespace android {
// ---------------------------------------------------------------------------
-SurfaceTextureLayer::SurfaceTextureLayer()
- : BufferQueue(true) {
+SurfaceTextureLayer::SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger)
+ : BufferQueue(true), flinger(flinger) {
}
SurfaceTextureLayer::~SurfaceTextureLayer() {
+ // remove ourselves from SurfaceFlinger's list. We do this asynchronously
+ // because we don't know where this dtor is called from, it could be
+ // called with the mStateLock held, leading to a dead-lock (it actually
+ // happens).
+ class MessageCleanUpList : public MessageBase {
+ sp<SurfaceFlinger> flinger;
+ wp<IBinder> gbp;
+ public:
+ MessageCleanUpList(const sp<SurfaceFlinger>& flinger, const wp<IBinder>& gbp)
+ : flinger(flinger), gbp(gbp) { }
+ virtual bool handler() {
+ Mutex::Autolock _l(flinger->mStateLock);
+ flinger->mGraphicBufferProducerList.remove(gbp);
+ return true;
+ }
+ };
+ flinger->postMessageAsync( new MessageCleanUpList(flinger, this) );
}
status_t SurfaceTextureLayer::connect(int api, QueueBufferOutput* output) {
diff --git a/services/surfaceflinger/SurfaceTextureLayer.h b/services/surfaceflinger/SurfaceTextureLayer.h
index a75ccf4..13cff2f 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.h
+++ b/services/surfaceflinger/SurfaceTextureLayer.h
@@ -28,15 +28,16 @@
// ---------------------------------------------------------------------------
class Layer;
+class SurfaceFlinger;
/*
* This is a thin wrapper around BufferQueue, used by the Layer class.
*/
-class SurfaceTextureLayer : public BufferQueue
-{
+class SurfaceTextureLayer : public BufferQueue {
+ sp<SurfaceFlinger> flinger;
public:
- SurfaceTextureLayer();
- ~SurfaceTextureLayer();
+ SurfaceTextureLayer(const sp<SurfaceFlinger>& flinger);
+ virtual ~SurfaceTextureLayer();
// After calling the superclass connect(), set or clear synchronous
// mode appropriately for the specified API.