diff options
-rw-r--r-- | cmds/dumpstate/Android.mk | 2 | ||||
-rw-r--r-- | cmds/dumpstate/dumpstate.cpp | 41 | ||||
-rw-r--r-- | cmds/dumpstate/utils.cpp | 8 | ||||
-rw-r--r-- | cmds/installd/commands.cpp | 77 | ||||
-rw-r--r-- | include/gui/BufferQueueCore.h | 2 | ||||
-rw-r--r-- | include/gui/BufferQueueProducer.h | 11 | ||||
-rw-r--r-- | include/gui/IGraphicBufferProducer.h | 15 | ||||
-rw-r--r-- | include/gui/Surface.h | 5 | ||||
-rw-r--r-- | libs/binder/Parcel.cpp | 6 | ||||
-rw-r--r-- | libs/binder/tests/binderLibTest.cpp | 52 | ||||
-rw-r--r-- | libs/gui/BufferQueueProducer.cpp | 14 | ||||
-rw-r--r-- | libs/gui/IGraphicBufferProducer.cpp | 6 | ||||
-rw-r--r-- | libs/gui/Surface.cpp | 4 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp | 4 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h | 2 | ||||
-rw-r--r-- | services/surfaceflinger/MonitoredProducer.cpp | 4 | ||||
-rw-r--r-- | services/surfaceflinger/MonitoredProducer.h | 2 |
17 files changed, 201 insertions, 54 deletions
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk index 0433f31eb2..e478651de0 100644 --- a/cmds/dumpstate/Android.mk +++ b/cmds/dumpstate/Android.mk @@ -10,7 +10,7 @@ LOCAL_SRC_FILES := dumpstate.cpp utils.cpp LOCAL_MODULE := dumpstate -LOCAL_SHARED_LIBRARIES := libcutils liblog libselinux libbase +LOCAL_SHARED_LIBRARIES := libcutils liblog libselinux libbase libhardware_legacy # ZipArchive support, the order matters here to get all symbols. LOCAL_STATIC_LIBRARIES := libziparchive libz libcrypto_static LOCAL_HAL_STATIC_LIBRARIES := libdumpstate diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index 001fb917ea..691863bbbb 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -22,6 +22,7 @@ #include <memory> #include <regex> #include <set> +#include <signal.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> @@ -38,6 +39,7 @@ #include <android-base/unique_fd.h> #include <android-base/file.h> #include <cutils/properties.h> +#include <hardware_legacy/power.h> #include "private/android_filesystem_config.h" @@ -83,6 +85,7 @@ static bool dry_run = false; #define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4) #define NUM_TOMBSTONES 10 #define WLUTIL "/vendor/xbin/wlutil" +#define WAKE_LOCK_NAME "dumpstate_wakelock" typedef struct { char name[TOMBSTONE_MAX_LEN]; @@ -1148,11 +1151,31 @@ static void usage() { VERSION_DEFAULT.c_str()); } -static void sigpipe_handler(int n) { - // don't complain to stderr or stdout +static void wake_lock_releaser() { + if (release_wake_lock(WAKE_LOCK_NAME) < 0) { + MYLOGE("Failed to release wake lock: %s \n", strerror(errno)); + } else { + MYLOGD("Wake lock released.\n"); + } +} + +static void sig_handler(int signo) { + wake_lock_releaser(); _exit(EXIT_FAILURE); } +static void register_sig_handler() { + struct sigaction sa; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = sig_handler; + sigaction(SIGPIPE, &sa, NULL); // broken pipe + sigaction(SIGSEGV, &sa, NULL); // segment fault + sigaction(SIGINT, &sa, NULL); // ctrl-c + sigaction(SIGTERM, &sa, NULL); // killed + sigaction(SIGQUIT, &sa, NULL); // quit +} + /* adds the temporary report to the existing .zip file, closes the .zip file, and removes the temporary file. */ @@ -1238,7 +1261,6 @@ static std::string SHA256_file_hash(std::string filepath) { } int main(int argc, char *argv[]) { - struct sigaction sigact; int do_add_date = 0; int do_zip_file = 0; int do_vibrate = 1; @@ -1255,6 +1277,14 @@ int main(int argc, char *argv[]) { MYLOGI("begin\n"); + if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) { + MYLOGE("Failed to acquire wake lock: %s \n", strerror(errno)); + } else { + MYLOGD("Wake lock acquired.\n"); + atexit(wake_lock_releaser); + register_sig_handler(); + } + dry_run = property_get_bool("dumpstate.dry_run", 0) != 0; if (is_dry_run()) { MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n"); @@ -1275,11 +1305,6 @@ int main(int argc, char *argv[]) { property_set("dumpstate.last_id", last_id); MYLOGI("dumpstate id: %lu\n", id); - /* clear SIGPIPE handler */ - memset(&sigact, 0, sizeof(sigact)); - sigact.sa_handler = sigpipe_handler; - sigaction(SIGPIPE, &sigact, NULL); - /* set as high priority, and protect from OOM killer */ setpriority(PRIO_PROCESS, 0, -20); diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp index ff66bf3357..b49d6efc04 100644 --- a/cmds/dumpstate/utils.cpp +++ b/cmds/dumpstate/utils.cpp @@ -909,7 +909,7 @@ bool drop_root_user() { } gid_t groups[] = { AID_LOG, AID_SDCARD_R, AID_SDCARD_RW, - AID_MOUNT, AID_INET, AID_NET_BW_STATS, AID_READPROC }; + AID_MOUNT, AID_INET, AID_NET_BW_STATS, AID_READPROC, AID_WAKELOCK }; if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) { MYLOGE("Unable to setgroups, aborting: %s\n", strerror(errno)); return false; @@ -930,8 +930,10 @@ bool drop_root_user() { capheader.version = _LINUX_CAPABILITY_VERSION_3; capheader.pid = 0; - capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG); - capdata[CAP_TO_INDEX(CAP_SYSLOG)].effective = CAP_TO_MASK(CAP_SYSLOG); + capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = + (CAP_TO_MASK(CAP_SYSLOG) | CAP_TO_MASK(CAP_BLOCK_SUSPEND)); + capdata[CAP_TO_INDEX(CAP_SYSLOG)].effective = + (CAP_TO_MASK(CAP_SYSLOG) | CAP_TO_MASK(CAP_BLOCK_SUSPEND)); capdata[0].inheritable = 0; capdata[1].inheritable = 0; diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp index 6533ab1ec6..2df48aa7dd 100644 --- a/cmds/installd/commands.cpp +++ b/cmds/installd/commands.cpp @@ -99,23 +99,64 @@ static std::string create_primary_profile(const std::string& profile_dir) { return StringPrintf("%s/%s", profile_dir.c_str(), PRIMARY_PROFILE_NAME); } -static int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid, - const char* pkgname, const char* seinfo) { +/** + * Perform restorecon of the given path, but only perform recursive restorecon + * if the label of that top-level file actually changed. This can save us + * significant time by avoiding no-op traversals of large filesystem trees. + */ +static int restorecon_app_data_lazy(const char* path, const char* seinfo, uid_t uid) { + int res = 0; + char* before = nullptr; + char* after = nullptr; + + // Note that SELINUX_ANDROID_RESTORECON_DATADATA flag is set by + // libselinux. Not needed here. + + if (lgetfilecon(path, &before) < 0) { + PLOG(ERROR) << "Failed before getfilecon for " << path; + goto fail; + } + if (selinux_android_restorecon_pkgdir(path, seinfo, uid, 0) < 0) { + PLOG(ERROR) << "Failed top-level restorecon for " << path; + goto fail; + } + if (lgetfilecon(path, &after) < 0) { + PLOG(ERROR) << "Failed after getfilecon for " << path; + goto fail; + } + + // If the initial top-level restorecon above changed the label, then go + // back and restorecon everything recursively + if (strcmp(before, after)) { + LOG(DEBUG) << "Detected label change from " << before << " to " << after << " at " << path + << "; running recursive restorecon"; + if (selinux_android_restorecon_pkgdir(path, seinfo, uid, + SELINUX_ANDROID_RESTORECON_RECURSE) < 0) { + PLOG(ERROR) << "Failed recursive restorecon for " << path; + goto fail; + } + } + + goto done; +fail: + res = -1; +done: + free(before); + free(after); + return res; +} + +static int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid) { if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) != 0) { PLOG(ERROR) << "Failed to prepare " << path; return -1; } - if (selinux_android_setfilecon(path.c_str(), pkgname, seinfo, uid) < 0) { - PLOG(ERROR) << "Failed to setfilecon " << path; - return -1; - } return 0; } static int prepare_app_dir(const std::string& parent, const char* name, mode_t target_mode, - uid_t uid, const char* pkgname, const char* seinfo) { - return prepare_app_dir(StringPrintf("%s/%s", parent.c_str(), name), target_mode, uid, pkgname, - seinfo); + uid_t uid) { + return prepare_app_dir(StringPrintf("%s/%s", parent.c_str(), name), target_mode, uid); } int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags, @@ -124,9 +165,14 @@ int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int mode_t target_mode = target_sdk_version >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751; if (flags & FLAG_STORAGE_CE) { auto path = create_data_user_ce_package_path(uuid, userid, pkgname); - if (prepare_app_dir(path, target_mode, uid, pkgname, seinfo) || - prepare_app_dir(path, "cache", 0771, uid, pkgname, seinfo) || - prepare_app_dir(path, "code_cache", 0771, uid, pkgname, seinfo)) { + if (prepare_app_dir(path, target_mode, uid) || + prepare_app_dir(path, "cache", 0771, uid) || + prepare_app_dir(path, "code_cache", 0771, uid)) { + return -1; + } + + // Consider restorecon over contents if label changed + if (restorecon_app_data_lazy(path.c_str(), seinfo, uid)) { return -1; } @@ -139,11 +185,16 @@ int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int } if (flags & FLAG_STORAGE_DE) { auto path = create_data_user_de_package_path(uuid, userid, pkgname); - if (prepare_app_dir(path, target_mode, uid, pkgname, seinfo)) { + if (prepare_app_dir(path, target_mode, uid)) { // TODO: include result once 25796509 is fixed return 0; } + // Consider restorecon over contents if label changed + if (restorecon_app_data_lazy(path.c_str(), seinfo, uid)) { + return -1; + } + if (property_get_bool("dalvik.vm.usejitprofiles")) { const std::string profile_path = create_data_user_profile_package_path(userid, pkgname); // read-write-execute only for the app user. diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h index 82bc121af3..cc5c536d13 100644 --- a/include/gui/BufferQueueCore.h +++ b/include/gui/BufferQueueCore.h @@ -182,6 +182,8 @@ private: // to this BufferQueue. It defaults to NO_CONNECTED_API, and gets updated // by the connect and disconnect methods. int mConnectedApi; + // PID of the process which last successfully called connect(...) + pid_t mConnectedPid; // mConnectedProducerToken is used to set a binder death notification on // the producer. diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h index d2bd32e0b3..b3291f446a 100644 --- a/include/gui/BufferQueueProducer.h +++ b/include/gui/BufferQueueProducer.h @@ -135,15 +135,8 @@ public: virtual status_t connect(const sp<IProducerListener>& listener, int api, bool producerControlledByApp, QueueBufferOutput* output); - // disconnect attempts to disconnect a producer API from the BufferQueue. - // Calling this method will cause any subsequent calls to other - // IGraphicBufferProducer methods to fail except for getAllocator and connect. - // Successfully calling connect after this will allow the other methods to - // succeed again. - // - // This method will fail if the the BufferQueue is not currently - // connected to the specified producer API. - virtual status_t disconnect(int api); + // See IGraphicBufferProducer::disconnect + virtual status_t disconnect(int api, DisconnectMode mode = DisconnectMode::Api); // Attaches a sideband buffer stream to the IGraphicBufferProducer. // diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h index 9353042e1e..31294187ad 100644 --- a/include/gui/IGraphicBufferProducer.h +++ b/include/gui/IGraphicBufferProducer.h @@ -457,17 +457,24 @@ public: virtual status_t connect(const sp<IProducerListener>& listener, int api, bool producerControlledByApp, QueueBufferOutput* output) = 0; + enum class DisconnectMode { + // Disconnect only the specified API. + Api, + // Disconnect any API originally connected from the process calling disconnect. + AllLocal + }; + // disconnect attempts to disconnect a client API from the // IGraphicBufferProducer. Calling this method will cause any subsequent // calls to other IGraphicBufferProducer methods to fail except for // getAllocator and connect. Successfully calling connect after this will // allow the other methods to succeed again. // - // This method will fail if the the IGraphicBufferProducer is not currently - // connected to the specified client API. - // // The api should be one of the NATIVE_WINDOW_API_* values in <window.h> // + // Alternatively if mode is AllLocal, then the API value is ignored, and any API + // connected from the same PID calling disconnect will be disconnected. + // // Disconnecting from an abandoned IGraphicBufferProducer is legal and // is considered a no-op. // @@ -476,7 +483,7 @@ public: // * the api specified does not match the one that was connected // * api was out of range (see above). // * DEAD_OBJECT - the token is hosted by an already-dead process - virtual status_t disconnect(int api) = 0; + virtual status_t disconnect(int api, DisconnectMode mode = DisconnectMode::Api) = 0; // Attaches a sideband buffer stream to the IGraphicBufferProducer. // diff --git a/include/gui/Surface.h b/include/gui/Surface.h index 85743908ec..eda7a80866 100644 --- a/include/gui/Surface.h +++ b/include/gui/Surface.h @@ -203,7 +203,6 @@ protected: virtual int lockBuffer_DEPRECATED(ANativeWindowBuffer* buffer); virtual int connect(int api); - virtual int disconnect(int api); virtual int setBufferCount(int bufferCount); virtual int setBuffersUserDimensions(uint32_t width, uint32_t height); virtual int setBuffersFormat(PixelFormat format); @@ -216,6 +215,10 @@ protected: virtual void setSurfaceDamage(android_native_rect_t* rects, size_t numRects); public: + virtual int disconnect(int api, + IGraphicBufferProducer::DisconnectMode mode = + IGraphicBufferProducer::DisconnectMode::Api); + virtual int setMaxDequeuedBufferCount(int maxDequeuedBuffers); virtual int setAsyncMode(bool async); virtual int setSharedBufferMode(bool sharedBufferMode); diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index 061cb08fde..572c284546 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -1427,13 +1427,13 @@ status_t readByteVectorInternal(const Parcel* parcel, return status; } - const void* data = parcel->readInplace(size); + T* data = const_cast<T*>(reinterpret_cast<const T*>(parcel->readInplace(size))); if (!data) { status = BAD_VALUE; return status; } - val->resize(size); - memcpy(val->data(), data, size); + val->reserve(size); + val->insert(val->end(), data, data + size); return status; } diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp index a98f11f2b3..cb0e965a65 100644 --- a/libs/binder/tests/binderLibTest.cpp +++ b/libs/binder/tests/binderLibTest.cpp @@ -56,6 +56,7 @@ enum BinderLibTestTranscationCode { BINDER_LIB_TEST_EXIT_TRANSACTION, BINDER_LIB_TEST_DELAYED_EXIT_TRANSACTION, BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION, + BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION, }; pid_t start_server_process(int arg2) @@ -684,6 +685,47 @@ TEST_F(BinderLibTest, CheckHandleZeroBinderHighBitsZeroCookie) { EXPECT_EQ(fb->binder >> 32, (binder_uintptr_t)0); } +TEST_F(BinderLibTest, FreedBinder) { + status_t ret; + + sp<IBinder> server = addServer(); + ASSERT_TRUE(server != NULL); + + __u32 freedHandle; + wp<IBinder> keepFreedBinder; + { + Parcel data, reply; + data.writeBool(false); /* request weak reference */ + ret = server->transact(BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION, data, &reply); + ASSERT_EQ(NO_ERROR, ret); + struct flat_binder_object *freed = (struct flat_binder_object *)(reply.data()); + freedHandle = freed->handle; + /* Add a weak ref to the freed binder so the driver does not + * delete its reference to it - otherwise the transaction + * fails regardless of whether the driver is fixed. + */ + keepFreedBinder = reply.readWeakBinder(); + } + { + Parcel data, reply; + data.writeStrongBinder(server); + /* Replace original handle with handle to the freed binder */ + struct flat_binder_object *strong = (struct flat_binder_object *)(data.data()); + __u32 oldHandle = strong->handle; + strong->handle = freedHandle; + ret = server->transact(BINDER_LIB_TEST_ADD_STRONG_REF_TRANSACTION, data, &reply); + /* Returns DEAD_OBJECT (-32) if target crashes and + * FAILED_TRANSACTION if the driver rejects the invalid + * object. + */ + EXPECT_EQ((status_t)FAILED_TRANSACTION, ret); + /* Restore original handle so parcel destructor does not use + * the wrong handle. + */ + strong->handle = oldHandle; + } +} + class BinderLibTestService : public BBinder { public: @@ -901,6 +943,16 @@ class BinderLibTestService : public BBinder while (wait(NULL) != -1 || errno != ECHILD) ; exit(EXIT_SUCCESS); + case BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION: { + bool strongRef = data.readBool(); + sp<IBinder> binder = new BBinder(); + if (strongRef) { + reply->writeStrongBinder(binder); + } else { + reply->writeWeakBinder(binder); + } + return NO_ERROR; + } default: return UNKNOWN_TRANSACTION; }; diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 30b6c334a3..e51144d79f 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -28,6 +28,7 @@ #define EGL_EGLEXT_PROTOTYPES +#include <binder/IPCThreadState.h> #include <gui/BufferItem.h> #include <gui/BufferQueueCore.h> #include <gui/BufferQueueProducer.h> @@ -1138,7 +1139,7 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener, status = BAD_VALUE; break; } - + mCore->mConnectedPid = IPCThreadState::self()->getCallingPid(); mCore->mBufferHasBeenQueued = false; mCore->mDequeueBufferCannotBlock = false; if (mDequeueTimeout < 0) { @@ -1151,7 +1152,7 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener, return status; } -status_t BufferQueueProducer::disconnect(int api) { +status_t BufferQueueProducer::disconnect(int api, DisconnectMode mode) { ATRACE_CALL(); BQ_LOGV("disconnect: api %d", api); @@ -1159,6 +1160,14 @@ status_t BufferQueueProducer::disconnect(int api) { sp<IConsumerListener> listener; { // Autolock scope Mutex::Autolock lock(mCore->mMutex); + + if (mode == DisconnectMode::AllLocal) { + if (IPCThreadState::self()->getCallingPid() != mCore->mConnectedPid) { + return NO_ERROR; + } + api = BufferQueueCore::CURRENTLY_CONNECTED_API; + } + mCore->waitWhileAllocatingLocked(); if (mCore->mIsAbandoned) { @@ -1197,6 +1206,7 @@ status_t BufferQueueProducer::disconnect(int api) { BufferQueueCore::INVALID_BUFFER_SLOT; mCore->mConnectedProducerListener = NULL; mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API; + mCore->mConnectedPid = -1; mCore->mSidebandStream.clear(); mCore->mDequeueCondition.broadcast(); listener = mCore->mConsumerListener; diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index 56656e3c16..846c205c00 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -270,10 +270,11 @@ public: return result; } - virtual status_t disconnect(int api) { + virtual status_t disconnect(int api, DisconnectMode mode) { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); data.writeInt32(api); + data.writeInt32(static_cast<int32_t>(mode)); status_t result =remote()->transact(DISCONNECT, data, &reply); if (result != NO_ERROR) { return result; @@ -621,7 +622,8 @@ status_t BnGraphicBufferProducer::onTransact( case DISCONNECT: { CHECK_INTERFACE(IGraphicBufferProducer, data, reply); int api = data.readInt32(); - status_t res = disconnect(api); + DisconnectMode mode = static_cast<DisconnectMode>(data.readInt32()); + status_t res = disconnect(api, mode); reply->writeInt32(res); return NO_ERROR; } diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index a0a742c13f..d78a681a5b 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -844,14 +844,14 @@ int Surface::connect(int api, const sp<IProducerListener>& listener) { } -int Surface::disconnect(int api) { +int Surface::disconnect(int api, IGraphicBufferProducer::DisconnectMode mode) { ATRACE_CALL(); ALOGV("Surface::disconnect"); Mutex::Autolock lock(mMutex); mSharedBufferSlot = BufferItem::INVALID_BUFFER_SLOT; mSharedBufferHasBeenQueued = false; freeAllBuffers(); - int err = mGraphicBufferProducer->disconnect(api); + int err = mGraphicBufferProducer->disconnect(api, mode); if (!err) { mReqFormat = 0; mReqWidth = 0; diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index 61bb0bd8d9..2190466ad9 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -563,8 +563,8 @@ status_t VirtualDisplaySurface::connect(const sp<IProducerListener>& listener, return result; } -status_t VirtualDisplaySurface::disconnect(int api) { - return mSource[SOURCE_SINK]->disconnect(api); +status_t VirtualDisplaySurface::disconnect(int api, DisconnectMode mode) { + return mSource[SOURCE_SINK]->disconnect(api, mode); } status_t VirtualDisplaySurface::setSidebandStream(const sp<NativeHandle>& /*stream*/) { diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index bf9b39c50d..70f717f8c2 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -115,7 +115,7 @@ private: virtual int query(int what, int* value); virtual status_t connect(const sp<IProducerListener>& listener, int api, bool producerControlledByApp, QueueBufferOutput* output); - virtual status_t disconnect(int api); + virtual status_t disconnect(int api, DisconnectMode mode); virtual status_t setSidebandStream(const sp<NativeHandle>& stream); virtual void allocateBuffers(uint32_t width, uint32_t height, PixelFormat format, uint32_t usage); diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp index 36cfa3718a..ffaee7a107 100644 --- a/services/surfaceflinger/MonitoredProducer.cpp +++ b/services/surfaceflinger/MonitoredProducer.cpp @@ -102,8 +102,8 @@ status_t MonitoredProducer::connect(const sp<IProducerListener>& listener, return mProducer->connect(listener, api, producerControlledByApp, output); } -status_t MonitoredProducer::disconnect(int api) { - return mProducer->disconnect(api); +status_t MonitoredProducer::disconnect(int api, DisconnectMode mode) { + return mProducer->disconnect(api, mode); } status_t MonitoredProducer::setSidebandStream(const sp<NativeHandle>& stream) { diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h index f64fe51ef5..66f6cf0bdb 100644 --- a/services/surfaceflinger/MonitoredProducer.h +++ b/services/surfaceflinger/MonitoredProducer.h @@ -50,7 +50,7 @@ public: virtual int query(int what, int* value); virtual status_t connect(const sp<IProducerListener>& token, int api, bool producerControlledByApp, QueueBufferOutput* output); - virtual status_t disconnect(int api); + virtual status_t disconnect(int api, DisconnectMode mode); virtual status_t setSidebandStream(const sp<NativeHandle>& stream); virtual void allocateBuffers(uint32_t width, uint32_t height, PixelFormat format, uint32_t usage); |