Loading libs/binder/RpcTransportUtils.h +13 −27 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #pragma once #include <binder/unique_fd.h> #include <binder/Functional.h> #include <poll.h> #include "Constants.h" Loading Loading @@ -76,10 +77,16 @@ status_t interruptableReadOrWrite( size_t enomemWaitUs = 0; size_t enomemTotalUs = 0; size_t numSysCalls = 0; auto syscallBugCatcher = binder::impl::make_scope_guard([&]() { if (numSysCalls > 1000) { ALOGE("Too many calls to %s! Spinning? %zu", funName, numSysCalls); } }); bool havePolled = false; while (true) { ssize_t processSize = -1; bool skipPollingAndContinue = false; // set when we should retry immediately // This block dynamically adjusts packet sizes down to work around a // limitation in the vsock driver where large packets are sometimes Loading Loading @@ -110,6 +117,8 @@ status_t interruptableReadOrWrite( "chunkRemaining never zero - see EMPTY IOVEC ISSUE above"); } ++numSysCalls; // MAIN ACTION if (MAYBE_TRUE_IN_FLAKE_MODE) { LOG_RPC_DETAIL("Injecting ENOMEM."); Loading @@ -127,15 +136,6 @@ status_t interruptableReadOrWrite( niovs = old_niovs; // (A) - restored iovs[i].iov_len = old_len; // (B) - restored } // altPoll may introduce long waiting since it assumes if it cannot write // data, that it needs to wait to send more to give time for the producer // consumer problem to be solved - otherwise it will busy loop. However, // for this workaround, we are breaking up the transaction intentionally, // not because the transaction won't fit, but to avoid a bug in the kernel // for how it combines messages. So, when we artificially simulate a // limited send, don't poll and just keep on sending data. skipPollingAndContinue = !canSendFullTransaction; } // HANDLE RESULT OF SEND OR RECEIVE Loading Loading @@ -170,14 +170,6 @@ status_t interruptableReadOrWrite( LOG_RPC_DETAIL("Sleeping %zuus due to ENOMEM.", enomemWaitUs); usleep(enomemWaitUs); } // Need to survey socket code to see if polling in this situation is // guaranteed to be non-blocking. // NOTE: if the other side needs to deallocate memory, and that is the // only deallocatable memory in the entire system, but we need altPoll // to drain commands to unstick it so it can do that, then this could // cause a deadlock, but this is not realistic on Android. skipPollingAndContinue = true; } else if (havePolled || (savedErrno != EAGAIN && savedErrno != EWOULDBLOCK)) { // Still return the error on later passes, since it would expose // a problem with polling Loading Loading @@ -215,21 +207,15 @@ status_t interruptableReadOrWrite( } // METHOD OF POLLING if (skipPollingAndContinue) { // Since we aren't polling, manually check if we should shutdown. This ensures any bug // leading to an infinite loop can still be recovered from. if (fdTrigger->isTriggered()) { return DEAD_OBJECT; } // continue; } else if (altPoll) { if (altPoll) { if (status_t status = (*altPoll)(); status != OK) return status; if (fdTrigger->isTriggered()) { // altPoll may not check this return DEAD_OBJECT; } } else { if (status_t status = fdTrigger->triggerablePoll(socket, event); status != OK) if (status_t status = fdTrigger->triggerablePoll(socket, event); status != OK) { return status; } if (!havePolled) havePolled = true; } } Loading libs/gui/SurfaceControl.cpp +7 −6 Original line number Diff line number Diff line Loading @@ -197,22 +197,23 @@ const std::string& SurfaceControl::getName() const { return mName; } std::shared_ptr<Choreographer> SurfaceControl::getChoreographer() { Choreographer* SurfaceControl::getChoreographer() { if (mChoreographer) { return mChoreographer; return mChoreographer.get(); } sp<Looper> looper = Looper::getForThread(); if (!looper.get()) { ALOGE("%s: No looper prepared for thread", __func__); return nullptr; } mChoreographer = std::make_shared<Choreographer>(looper, getHandle()); status_t result = mChoreographer->initialize(); auto choreographer = sp<Choreographer>::make(looper, getHandle()); status_t result = choreographer->initialize(); if (result != OK) { ALOGE("Failed to initialize choreographer"); mChoreographer = nullptr; return nullptr; } return mChoreographer; mChoreographer = std::move(choreographer); return mChoreographer.get(); } sp<IGraphicBufferProducer> SurfaceControl::getIGraphicBufferProducer() Loading libs/gui/include/gui/Choreographer.h +3 −3 Original line number Diff line number Diff line Loading @@ -79,9 +79,6 @@ public: }; static Context gChoreographers; explicit Choreographer(const sp<Looper>& looper, const sp<IBinder>& layerHandle = nullptr) EXCLUDES(gChoreographers.lock); void postFrameCallbackDelayed(AChoreographer_frameCallback cb, AChoreographer_frameCallback64 cb64, AChoreographer_vsyncCallback vsyncCallback, void* data, Loading Loading @@ -114,6 +111,9 @@ public: private: Choreographer(const Choreographer&) = delete; explicit Choreographer(const sp<Looper>& looper, const sp<IBinder>& layerHandle = nullptr) EXCLUDES(gChoreographers.lock); friend class sp<Choreographer>; void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count, VsyncEventData vsyncEventData) override; Loading libs/gui/include/gui/SurfaceControl.h +3 −3 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include <android/gui/ISurfaceComposerClient.h> #include <gui/Choreographer.h> #include <ui/FrameStats.h> #include <ui/PixelFormat.h> #include <ui/Region.h> Loading @@ -36,7 +37,6 @@ namespace android { // --------------------------------------------------------------------------- class Choreographer; class IGraphicBufferProducer; class Surface; class SurfaceComposerClient; Loading Loading @@ -82,7 +82,7 @@ public: const std::string& getName() const; // TODO(b/267195698): Consider renaming. std::shared_ptr<Choreographer> getChoreographer(); Choreographer* getChoreographer(); sp<IGraphicBufferProducer> getIGraphicBufferProducer(); Loading Loading @@ -134,7 +134,7 @@ private: PixelFormat mFormat = PIXEL_FORMAT_NONE; uint32_t mCreateFlags = 0; uint64_t mFallbackFrameNumber = 100; std::shared_ptr<Choreographer> mChoreographer; sp<Choreographer> mChoreographer; }; }; // namespace android Loading libs/nativewindow/rust/src/lib.rs +39 −7 Original line number Diff line number Diff line Loading @@ -33,11 +33,11 @@ use ffi::{ AHardwareBuffer, AHardwareBuffer_Desc, AHardwareBuffer_Plane, AHardwareBuffer_Planes, AHardwareBuffer_readFromParcel, AHardwareBuffer_writeToParcel, ARect, }; use std::ffi::c_void; use std::fmt::{self, Debug, Formatter}; use std::mem::{forget, ManuallyDrop}; use std::os::fd::{AsRawFd, BorrowedFd, FromRawFd, OwnedFd}; use std::ptr::{self, null, null_mut, NonNull}; use std::{ffi::c_void, rc::Rc}; /// Wrapper around a C `AHardwareBuffer_Desc`. #[derive(Clone, Debug, PartialEq, Eq)] Loading Loading @@ -349,15 +349,20 @@ impl HardwareBuffer { ffi::AHardwareBuffer_lockPlanes(self.0.as_ptr(), usage.0, fence, rect, &mut planes) }; status_result(status)?; // `AHardwareBuffer_unlock` unlocks all the planes together, so we use a shared guard. let guard = Rc::new(HardwareBufferGuard { buffer: self, address: NonNull::new(planes.planes[0].data) .expect("AHardwareBuffer_lockPlanes set a null plane data"), }); let plane_count = planes.planeCount.try_into().unwrap(); Ok(planes.planes[..plane_count] .iter() .map(|plane| PlaneGuard { guard: HardwareBufferGuard { buffer: self, _guard: guard.clone(), address: NonNull::new(plane.data) .expect("AHardwareBuffer_lockAndGetInfo set a null outVirtualAddress"), }, .expect("AHardwareBuffer_lockPlanes set a null plane data"), pixel_stride: plane.pixelStride, row_stride: plane.rowStride, }) Loading Loading @@ -566,7 +571,9 @@ pub struct LockedBufferInfo<'a> { #[derive(Debug)] pub struct PlaneGuard<'a> { /// The locked buffer guard. pub guard: HardwareBufferGuard<'a>, _guard: Rc<HardwareBufferGuard<'a>>, /// The address of the buffer plane in memory. pub address: NonNull<c_void>, /// The stride in bytes between the color channel for one pixel to the next pixel. pub pixel_stride: u32, /// The stride in bytes between rows in the buffer. Loading Loading @@ -830,4 +837,29 @@ mod test { assert_eq!(info.stride, WIDTH * 4); drop(info); } #[test] fn lock_planes() { let buffer = HardwareBuffer::new(&HardwareBufferDescription::new( 1024, 512, 1, AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, 0, )) .expect("Failed to create buffer"); // SAFETY: No other threads or processes have access to the buffer. let plane_guards = unsafe { buffer.lock_planes( AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, None, None, ) } .unwrap(); drop(plane_guards); } } Loading
libs/binder/RpcTransportUtils.h +13 −27 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #pragma once #include <binder/unique_fd.h> #include <binder/Functional.h> #include <poll.h> #include "Constants.h" Loading Loading @@ -76,10 +77,16 @@ status_t interruptableReadOrWrite( size_t enomemWaitUs = 0; size_t enomemTotalUs = 0; size_t numSysCalls = 0; auto syscallBugCatcher = binder::impl::make_scope_guard([&]() { if (numSysCalls > 1000) { ALOGE("Too many calls to %s! Spinning? %zu", funName, numSysCalls); } }); bool havePolled = false; while (true) { ssize_t processSize = -1; bool skipPollingAndContinue = false; // set when we should retry immediately // This block dynamically adjusts packet sizes down to work around a // limitation in the vsock driver where large packets are sometimes Loading Loading @@ -110,6 +117,8 @@ status_t interruptableReadOrWrite( "chunkRemaining never zero - see EMPTY IOVEC ISSUE above"); } ++numSysCalls; // MAIN ACTION if (MAYBE_TRUE_IN_FLAKE_MODE) { LOG_RPC_DETAIL("Injecting ENOMEM."); Loading @@ -127,15 +136,6 @@ status_t interruptableReadOrWrite( niovs = old_niovs; // (A) - restored iovs[i].iov_len = old_len; // (B) - restored } // altPoll may introduce long waiting since it assumes if it cannot write // data, that it needs to wait to send more to give time for the producer // consumer problem to be solved - otherwise it will busy loop. However, // for this workaround, we are breaking up the transaction intentionally, // not because the transaction won't fit, but to avoid a bug in the kernel // for how it combines messages. So, when we artificially simulate a // limited send, don't poll and just keep on sending data. skipPollingAndContinue = !canSendFullTransaction; } // HANDLE RESULT OF SEND OR RECEIVE Loading Loading @@ -170,14 +170,6 @@ status_t interruptableReadOrWrite( LOG_RPC_DETAIL("Sleeping %zuus due to ENOMEM.", enomemWaitUs); usleep(enomemWaitUs); } // Need to survey socket code to see if polling in this situation is // guaranteed to be non-blocking. // NOTE: if the other side needs to deallocate memory, and that is the // only deallocatable memory in the entire system, but we need altPoll // to drain commands to unstick it so it can do that, then this could // cause a deadlock, but this is not realistic on Android. skipPollingAndContinue = true; } else if (havePolled || (savedErrno != EAGAIN && savedErrno != EWOULDBLOCK)) { // Still return the error on later passes, since it would expose // a problem with polling Loading Loading @@ -215,21 +207,15 @@ status_t interruptableReadOrWrite( } // METHOD OF POLLING if (skipPollingAndContinue) { // Since we aren't polling, manually check if we should shutdown. This ensures any bug // leading to an infinite loop can still be recovered from. if (fdTrigger->isTriggered()) { return DEAD_OBJECT; } // continue; } else if (altPoll) { if (altPoll) { if (status_t status = (*altPoll)(); status != OK) return status; if (fdTrigger->isTriggered()) { // altPoll may not check this return DEAD_OBJECT; } } else { if (status_t status = fdTrigger->triggerablePoll(socket, event); status != OK) if (status_t status = fdTrigger->triggerablePoll(socket, event); status != OK) { return status; } if (!havePolled) havePolled = true; } } Loading
libs/gui/SurfaceControl.cpp +7 −6 Original line number Diff line number Diff line Loading @@ -197,22 +197,23 @@ const std::string& SurfaceControl::getName() const { return mName; } std::shared_ptr<Choreographer> SurfaceControl::getChoreographer() { Choreographer* SurfaceControl::getChoreographer() { if (mChoreographer) { return mChoreographer; return mChoreographer.get(); } sp<Looper> looper = Looper::getForThread(); if (!looper.get()) { ALOGE("%s: No looper prepared for thread", __func__); return nullptr; } mChoreographer = std::make_shared<Choreographer>(looper, getHandle()); status_t result = mChoreographer->initialize(); auto choreographer = sp<Choreographer>::make(looper, getHandle()); status_t result = choreographer->initialize(); if (result != OK) { ALOGE("Failed to initialize choreographer"); mChoreographer = nullptr; return nullptr; } return mChoreographer; mChoreographer = std::move(choreographer); return mChoreographer.get(); } sp<IGraphicBufferProducer> SurfaceControl::getIGraphicBufferProducer() Loading
libs/gui/include/gui/Choreographer.h +3 −3 Original line number Diff line number Diff line Loading @@ -79,9 +79,6 @@ public: }; static Context gChoreographers; explicit Choreographer(const sp<Looper>& looper, const sp<IBinder>& layerHandle = nullptr) EXCLUDES(gChoreographers.lock); void postFrameCallbackDelayed(AChoreographer_frameCallback cb, AChoreographer_frameCallback64 cb64, AChoreographer_vsyncCallback vsyncCallback, void* data, Loading Loading @@ -114,6 +111,9 @@ public: private: Choreographer(const Choreographer&) = delete; explicit Choreographer(const sp<Looper>& looper, const sp<IBinder>& layerHandle = nullptr) EXCLUDES(gChoreographers.lock); friend class sp<Choreographer>; void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count, VsyncEventData vsyncEventData) override; Loading
libs/gui/include/gui/SurfaceControl.h +3 −3 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include <android/gui/ISurfaceComposerClient.h> #include <gui/Choreographer.h> #include <ui/FrameStats.h> #include <ui/PixelFormat.h> #include <ui/Region.h> Loading @@ -36,7 +37,6 @@ namespace android { // --------------------------------------------------------------------------- class Choreographer; class IGraphicBufferProducer; class Surface; class SurfaceComposerClient; Loading Loading @@ -82,7 +82,7 @@ public: const std::string& getName() const; // TODO(b/267195698): Consider renaming. std::shared_ptr<Choreographer> getChoreographer(); Choreographer* getChoreographer(); sp<IGraphicBufferProducer> getIGraphicBufferProducer(); Loading Loading @@ -134,7 +134,7 @@ private: PixelFormat mFormat = PIXEL_FORMAT_NONE; uint32_t mCreateFlags = 0; uint64_t mFallbackFrameNumber = 100; std::shared_ptr<Choreographer> mChoreographer; sp<Choreographer> mChoreographer; }; }; // namespace android Loading
libs/nativewindow/rust/src/lib.rs +39 −7 Original line number Diff line number Diff line Loading @@ -33,11 +33,11 @@ use ffi::{ AHardwareBuffer, AHardwareBuffer_Desc, AHardwareBuffer_Plane, AHardwareBuffer_Planes, AHardwareBuffer_readFromParcel, AHardwareBuffer_writeToParcel, ARect, }; use std::ffi::c_void; use std::fmt::{self, Debug, Formatter}; use std::mem::{forget, ManuallyDrop}; use std::os::fd::{AsRawFd, BorrowedFd, FromRawFd, OwnedFd}; use std::ptr::{self, null, null_mut, NonNull}; use std::{ffi::c_void, rc::Rc}; /// Wrapper around a C `AHardwareBuffer_Desc`. #[derive(Clone, Debug, PartialEq, Eq)] Loading Loading @@ -349,15 +349,20 @@ impl HardwareBuffer { ffi::AHardwareBuffer_lockPlanes(self.0.as_ptr(), usage.0, fence, rect, &mut planes) }; status_result(status)?; // `AHardwareBuffer_unlock` unlocks all the planes together, so we use a shared guard. let guard = Rc::new(HardwareBufferGuard { buffer: self, address: NonNull::new(planes.planes[0].data) .expect("AHardwareBuffer_lockPlanes set a null plane data"), }); let plane_count = planes.planeCount.try_into().unwrap(); Ok(planes.planes[..plane_count] .iter() .map(|plane| PlaneGuard { guard: HardwareBufferGuard { buffer: self, _guard: guard.clone(), address: NonNull::new(plane.data) .expect("AHardwareBuffer_lockAndGetInfo set a null outVirtualAddress"), }, .expect("AHardwareBuffer_lockPlanes set a null plane data"), pixel_stride: plane.pixelStride, row_stride: plane.rowStride, }) Loading Loading @@ -566,7 +571,9 @@ pub struct LockedBufferInfo<'a> { #[derive(Debug)] pub struct PlaneGuard<'a> { /// The locked buffer guard. pub guard: HardwareBufferGuard<'a>, _guard: Rc<HardwareBufferGuard<'a>>, /// The address of the buffer plane in memory. pub address: NonNull<c_void>, /// The stride in bytes between the color channel for one pixel to the next pixel. pub pixel_stride: u32, /// The stride in bytes between rows in the buffer. Loading Loading @@ -830,4 +837,29 @@ mod test { assert_eq!(info.stride, WIDTH * 4); drop(info); } #[test] fn lock_planes() { let buffer = HardwareBuffer::new(&HardwareBufferDescription::new( 1024, 512, 1, AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, 0, )) .expect("Failed to create buffer"); // SAFETY: No other threads or processes have access to the buffer. let plane_guards = unsafe { buffer.lock_planes( AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, None, None, ) } .unwrap(); drop(plane_guards); } }