diff options
53 files changed, 362 insertions, 436 deletions
diff --git a/data/etc/android.hardware.device_unique_attestation.xml b/data/etc/android.hardware.device_unique_attestation.xml new file mode 100644 index 0000000000..309be7a2c1 --- /dev/null +++ b/data/etc/android.hardware.device_unique_attestation.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2020 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- Feature for devices with Keymaster that support unique attestation. --> +<permissions> + <feature name="android.hardware.device_unique_attestation" /> +</permissions> diff --git a/include/ui/FatVector.h b/include/ui/FatVector.h deleted file mode 120000 index c2047c07e1..0000000000 --- a/include/ui/FatVector.h +++ /dev/null @@ -1 +0,0 @@ -../../libs/ui/include/ui/FatVector.h
\ No newline at end of file diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp index aeca12b582..43b0da307b 100644 --- a/libs/binder/AppOpsManager.cpp +++ b/libs/binder/AppOpsManager.cpp @@ -30,24 +30,10 @@ namespace android { -namespace { - -#if defined(__BRILLO__) -// Because Brillo has no application model, security policy is managed -// statically (at build time) with SELinux controls. -// As a consequence, it also never runs the AppOpsManager service. -const int APP_OPS_MANAGER_UNAVAILABLE_MODE = AppOpsManager::MODE_ALLOWED; -#else -const int APP_OPS_MANAGER_UNAVAILABLE_MODE = AppOpsManager::MODE_IGNORED; -#endif // defined(__BRILLO__) - -} // namespace - -static String16 _appops("appops"); -static pthread_mutex_t gClientIdMutex = PTHREAD_MUTEX_INITIALIZER; -static sp<IBinder> gClientId; - static const sp<IBinder>& getClientId() { + static pthread_mutex_t gClientIdMutex = PTHREAD_MUTEX_INITIALIZER; + static sp<IBinder> gClientId; + pthread_mutex_lock(&gClientIdMutex); if (gClientId == nullptr) { gClientId = new BBinder(); @@ -56,22 +42,13 @@ static const sp<IBinder>& getClientId() { return gClientId; } -thread_local uint64_t notedAppOpsInThisBinderTransaction[2]; -thread_local int32_t uidOfThisBinderTransaction = -1; - -// Whether an appop should be collected: 0 == not initialized, 1 == don't note, 2 == note -uint8_t appOpsToNote[AppOpsManager::_NUM_OP] = {0}; - AppOpsManager::AppOpsManager() { } -#if defined(__BRILLO__) -// There is no AppOpsService on Brillo -sp<IAppOpsService> AppOpsManager::getService() { return NULL; } -#else sp<IAppOpsService> AppOpsManager::getService() { + static String16 _appops("appops"); std::lock_guard<Mutex> scoped_lock(mLock); int64_t startTime = 0; @@ -96,14 +73,13 @@ sp<IAppOpsService> AppOpsManager::getService() } return service; } -#endif // defined(__BRILLO__) int32_t AppOpsManager::checkOp(int32_t op, int32_t uid, const String16& callingPackage) { sp<IAppOpsService> service = getService(); return service != nullptr ? service->checkOperation(op, uid, callingPackage) - : APP_OPS_MANAGER_UNAVAILABLE_MODE; + : AppOpsManager::MODE_IGNORED; } int32_t AppOpsManager::checkAudioOpNoThrow(int32_t op, int32_t usage, int32_t uid, @@ -111,7 +87,7 @@ int32_t AppOpsManager::checkAudioOpNoThrow(int32_t op, int32_t usage, int32_t ui sp<IAppOpsService> service = getService(); return service != nullptr ? service->checkAudioOperation(op, usage, uid, callingPackage) - : APP_OPS_MANAGER_UNAVAILABLE_MODE; + : AppOpsManager::MODE_IGNORED; } int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage) { @@ -125,7 +101,7 @@ int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPa int32_t mode = service != nullptr ? service->noteOperation(op, uid, callingPackage, featureId, shouldCollectNotes(op), message) - : APP_OPS_MANAGER_UNAVAILABLE_MODE; + : AppOpsManager::MODE_IGNORED; return mode; } @@ -143,7 +119,7 @@ int32_t AppOpsManager::startOpNoThrow(int32_t op, int32_t uid, const String16& c int32_t mode = service != nullptr ? service->startOperation(getClientId(), op, uid, callingPackage, featureId, startIfModeDefault, shouldCollectNotes(op), message) - : APP_OPS_MANAGER_UNAVAILABLE_MODE; + : AppOpsManager::MODE_IGNORED; return mode; } @@ -192,6 +168,9 @@ void AppOpsManager::setCameraAudioRestriction(int32_t mode) { // check it the appops needs to be collected and cache result bool AppOpsManager::shouldCollectNotes(int32_t opcode) { + // Whether an appop should be collected: 0 == not initialized, 1 == don't note, 2 == note + static uint8_t appOpsToNote[AppOpsManager::_NUM_OP] = {0}; + if (appOpsToNote[opcode] == 0) { if (getService()->shouldCollectNotes(opcode)) { appOpsToNote[opcode] = 2; diff --git a/libs/gui/BufferHubConsumer.cpp b/libs/gui/BufferHubConsumer.cpp index 0ddb87e0be..b5cdeb280a 100644 --- a/libs/gui/BufferHubConsumer.cpp +++ b/libs/gui/BufferHubConsumer.cpp @@ -147,16 +147,6 @@ status_t BufferHubConsumer::discardFreeBuffers() { return INVALID_OPERATION; } -status_t BufferHubConsumer::setFrameRate(float /*frameRate*/) { - ALOGE("BufferHubConsumer::setFrameRate: not implemented."); - return INVALID_OPERATION; -} - -status_t BufferHubConsumer::getFrameRate(float* /*frameRate*/) const { - ALOGE("BufferHubConsumer::getFrameRate: not implemented."); - return INVALID_OPERATION; -} - status_t BufferHubConsumer::dumpState(const String8& /*prefix*/, String8* /*outResult*/) const { ALOGE("BufferHubConsumer::dumpState: not implemented."); return INVALID_OPERATION; diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp index 4435265bb2..da6143c59f 100644 --- a/libs/gui/BufferQueueConsumer.cpp +++ b/libs/gui/BufferQueueConsumer.cpp @@ -783,18 +783,6 @@ status_t BufferQueueConsumer::discardFreeBuffers() { return NO_ERROR; } -status_t BufferQueueConsumer::setFrameRate(float frameRate) { - std::lock_guard<std::mutex> lock(mCore->mMutex); - mCore->mFrameRate = frameRate; - return NO_ERROR; -} - -status_t BufferQueueConsumer::getFrameRate(float* frameRate) const { - std::lock_guard<std::mutex> lock(mCore->mMutex); - *frameRate = mCore->mFrameRate; - return NO_ERROR; -} - status_t BufferQueueConsumer::dumpState(const String8& prefix, String8* outResult) const { struct passwd* pwd = getpwnam("shell"); uid_t shellUid = pwd ? pwd->pw_uid : 0; diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp index 9e5d681b37..a1803d8f0e 100644 --- a/libs/gui/BufferQueueCore.cpp +++ b/libs/gui/BufferQueueCore.cpp @@ -130,8 +130,7 @@ BufferQueueCore::BufferQueueCore() mLastQueuedSlot(INVALID_BUFFER_SLOT), mUniqueId(getUniqueId()), mAutoPrerotation(false), - mTransformHintInUse(0), - mFrameRate(0) { + mTransformHintInUse(0) { int numStartingBuffers = getMaxBufferCountLocked(); for (int s = 0; s < numStartingBuffers; s++) { mFreeSlots.insert(s); diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 9e86838592..3f4c5da193 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -1676,14 +1676,4 @@ status_t BufferQueueProducer::setAutoPrerotation(bool autoPrerotation) { return NO_ERROR; } -status_t BufferQueueProducer::setFrameRate(float frameRate) { - ATRACE_CALL(); - BQ_LOGV("setFrameRate: %.0f", frameRate); - - std::lock_guard<std::mutex> lock(mCore->mMutex); - - mCore->mFrameRate = frameRate; - return NO_ERROR; -} - } // namespace android diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp index 515f45c546..9f91d9d3aa 100644 --- a/libs/gui/ConsumerBase.cpp +++ b/libs/gui/ConsumerBase.cpp @@ -363,24 +363,6 @@ status_t ConsumerBase::discardFreeBuffers() { return OK; } -status_t ConsumerBase::setFrameRate(float frameRate) { - Mutex::Autolock _l(mMutex); - if (mAbandoned) { - CB_LOGE("setFrameRate: ConsumerBase is abandoned!"); - return NO_INIT; - } - return mConsumer->setFrameRate(frameRate); -} - -status_t ConsumerBase::getFrameRate(float* frameRate) { - Mutex::Autolock _l(mMutex); - if (mAbandoned) { - CB_LOGE("getFrameRate: ConsumerBase is abandoned!"); - return NO_INIT; - } - return mConsumer->getFrameRate(frameRate); -} - void ConsumerBase::dumpState(String8& result) const { dumpState(result, ""); } diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp index 2521a7cbd7..c705d3926d 100644 --- a/libs/gui/IGraphicBufferConsumer.cpp +++ b/libs/gui/IGraphicBufferConsumer.cpp @@ -51,8 +51,6 @@ enum class Tag : uint32_t { GET_SIDEBAND_STREAM, GET_OCCUPANCY_HISTORY, DISCARD_FREE_BUFFERS, - SET_FRAME_RATE, - GET_FRAME_RATE, DUMP_STATE, LAST = DUMP_STATE, }; @@ -165,16 +163,6 @@ public: Tag::DISCARD_FREE_BUFFERS); } - status_t setFrameRate(float frameRate) override { - using Signature = decltype(&IGraphicBufferConsumer::setFrameRate); - return callRemote<Signature>(Tag::SET_FRAME_RATE, frameRate); - } - - status_t getFrameRate(float* frameRate) const override { - using Signature = decltype(&IGraphicBufferConsumer::getFrameRate); - return callRemote<Signature>(Tag::GET_FRAME_RATE, frameRate); - } - status_t dumpState(const String8& prefix, String8* outResult) const override { using Signature = status_t (IGraphicBufferConsumer::*)(const String8&, String8*) const; return callRemote<Signature>(Tag::DUMP_STATE, prefix, outResult); @@ -232,10 +220,6 @@ status_t BnGraphicBufferConsumer::onTransact(uint32_t code, const Parcel& data, return callLocal(data, reply, &IGraphicBufferConsumer::getOccupancyHistory); case Tag::DISCARD_FREE_BUFFERS: return callLocal(data, reply, &IGraphicBufferConsumer::discardFreeBuffers); - case Tag::SET_FRAME_RATE: - return callLocal(data, reply, &IGraphicBufferConsumer::setFrameRate); - case Tag::GET_FRAME_RATE: - return callLocal(data, reply, &IGraphicBufferConsumer::getFrameRate); case Tag::DUMP_STATE: { using Signature = status_t (IGraphicBufferConsumer::*)(const String8&, String8*) const; return callLocal<Signature>(data, reply, &IGraphicBufferConsumer::dumpState); diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index 7b5596e43c..ad00939976 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -74,7 +74,6 @@ enum { GET_CONSUMER_USAGE, SET_LEGACY_BUFFER_DROP, SET_AUTO_PREROTATION, - SET_FRAME_RATE, }; class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer> @@ -560,14 +559,6 @@ public: } return result; } - - virtual status_t setFrameRate(float frameRate) { - Parcel data, reply; - data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); - data.writeFloat(frameRate); - status_t result = remote()->transact(SET_FRAME_RATE, data, &reply, IBinder::FLAG_ONEWAY); - return result; - } }; // Out-of-line virtual method definition to trigger vtable emission in this @@ -700,8 +691,6 @@ public: status_t setAutoPrerotation(bool autoPrerotation) override { return mBase->setAutoPrerotation(autoPrerotation); } - - status_t setFrameRate(float frameRate) override { return mBase->setFrameRate(frameRate); } }; IMPLEMENT_HYBRID_META_INTERFACE(GraphicBufferProducer, @@ -721,12 +710,6 @@ status_t IGraphicBufferProducer::setAutoPrerotation(bool autoPrerotation) { return INVALID_OPERATION; } -status_t IGraphicBufferProducer::setFrameRate(float frameRate) { - // No-op for IGBP other than BufferQueue. - (void)frameRate; - return INVALID_OPERATION; -} - status_t IGraphicBufferProducer::exportToParcel(Parcel* parcel) { status_t res = OK; res = parcel->writeUint32(USE_BUFFER_QUEUE); @@ -1096,13 +1079,6 @@ status_t BnGraphicBufferProducer::onTransact( reply->writeInt32(result); return NO_ERROR; } - case SET_FRAME_RATE: { - CHECK_INTERFACE(IGraphicBuffer, data, reply); - float frameRate = data.readFloat(); - status_t result = setFrameRate(frameRate); - reply->writeInt32(result); - return NO_ERROR; - } } return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index ce41eaba1d..04c21a9e1d 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -1281,6 +1281,9 @@ status_t BnSurfaceComposer::onTransact( std::unordered_set<sp<IBinder>, SpHash<IBinder>> excludeHandles; int numExcludeHandles = data.readInt32(); + if (numExcludeHandles >= static_cast<int>(MAX_LAYERS)) { + return BAD_VALUE; + } excludeHandles.reserve(numExcludeHandles); for (int i = 0; i < numExcludeHandles; i++) { excludeHandles.emplace(data.readStrongBinder()); diff --git a/libs/gui/include/gui/BufferHubConsumer.h b/libs/gui/include/gui/BufferHubConsumer.h index d75620342e..d38077014b 100644 --- a/libs/gui/include/gui/BufferHubConsumer.h +++ b/libs/gui/include/gui/BufferHubConsumer.h @@ -93,12 +93,6 @@ public: // See |IGraphicBufferConsumer::discardFreeBuffers| status_t discardFreeBuffers() override; - // See |IGraphicBufferConsumer::setFrameRate| - status_t setFrameRate(float frameRate) override; - - // See |IGraphicBufferConsumer::getFrameRate| - status_t getFrameRate(float* frameRate) const override; - // See |IGraphicBufferConsumer::dumpState| status_t dumpState(const String8& prefix, String8* outResult) const override; diff --git a/libs/gui/include/gui/BufferQueueConsumer.h b/libs/gui/include/gui/BufferQueueConsumer.h index e9f04490d8..7db69eca9d 100644 --- a/libs/gui/include/gui/BufferQueueConsumer.h +++ b/libs/gui/include/gui/BufferQueueConsumer.h @@ -149,12 +149,6 @@ public: // See IGraphicBufferConsumer::discardFreeBuffers virtual status_t discardFreeBuffers() override; - // See IGraphicBufferConsumer::setFrameRate. - virtual status_t setFrameRate(float frameRate) override; - - // See IGraphicBufferConsumer::getFrameRate. - virtual status_t getFrameRate(float* frameRate) const override; - // dump our state in a String status_t dumpState(const String8& prefix, String8* outResult) const override; diff --git a/libs/gui/include/gui/BufferQueueCore.h b/libs/gui/include/gui/BufferQueueCore.h index 05c20742f9..557c28b1b7 100644 --- a/libs/gui/include/gui/BufferQueueCore.h +++ b/libs/gui/include/gui/BufferQueueCore.h @@ -354,9 +354,6 @@ private: // mTransformHintInUse is to cache the mTransformHint used by the producer. uint32_t mTransformHintInUse; - // The frame rate the app intends to run at. - float mFrameRate; - }; // class BufferQueueCore } // namespace android diff --git a/libs/gui/include/gui/BufferQueueProducer.h b/libs/gui/include/gui/BufferQueueProducer.h index cbace5bb8b..a7f7d1defa 100644 --- a/libs/gui/include/gui/BufferQueueProducer.h +++ b/libs/gui/include/gui/BufferQueueProducer.h @@ -198,9 +198,6 @@ public: // See IGraphicBufferProducer::setAutoPrerotation virtual status_t setAutoPrerotation(bool autoPrerotation); - // See IGraphicBufferProducer::setFrameRate - virtual status_t setFrameRate(float frameRate) override; - private: // This is required by the IBinder::DeathRecipient interface virtual void binderDied(const wp<IBinder>& who); diff --git a/libs/gui/include/gui/ConsumerBase.h b/libs/gui/include/gui/ConsumerBase.h index cfed9aa6bd..8ff0cd0f6e 100644 --- a/libs/gui/include/gui/ConsumerBase.h +++ b/libs/gui/include/gui/ConsumerBase.h @@ -111,12 +111,6 @@ public: // See IGraphicBufferConsumer::discardFreeBuffers status_t discardFreeBuffers(); - // See IGraphicBufferConsumer::setFrameRate - status_t setFrameRate(float frameRate); - - // See IGraphicBufferConsumer::getFrameRate - status_t getFrameRate(float* frameRate); - private: ConsumerBase(const ConsumerBase&); void operator=(const ConsumerBase&); diff --git a/libs/gui/include/gui/IGraphicBufferConsumer.h b/libs/gui/include/gui/IGraphicBufferConsumer.h index 56fe949c9c..0b92e7df62 100644 --- a/libs/gui/include/gui/IGraphicBufferConsumer.h +++ b/libs/gui/include/gui/IGraphicBufferConsumer.h @@ -275,16 +275,6 @@ public: // call to free up any of its locally cached buffers. virtual status_t discardFreeBuffers() = 0; - // Set the frame rate the producer will run at. - // - // Return of a value other than NO_ERROR means an unknown error has occurred. - virtual status_t setFrameRate(float frameRate) = 0; - - // Get the frame rate the producer will run at. - // - // Return of a value other than NO_ERROR means an unknown error has occurred. - virtual status_t getFrameRate(float* frameRate) const = 0; - // dump state into a string virtual status_t dumpState(const String8& prefix, String8* outResult) const = 0; diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h index 87989da19b..d7f34920c4 100644 --- a/libs/gui/include/gui/IGraphicBufferProducer.h +++ b/libs/gui/include/gui/IGraphicBufferProducer.h @@ -639,9 +639,6 @@ public: // the width and height used for dequeueBuffer will be additionally swapped. virtual status_t setAutoPrerotation(bool autoPrerotation); - // Sets the apps intended frame rate. - virtual status_t setFrameRate(float frameRate); - #ifndef NO_BINDER // Static method exports any IGraphicBufferProducer object to a parcel. It // handles null producer as well. diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 0659f0de06..09487eab8b 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -76,6 +76,8 @@ class ISurfaceComposer: public IInterface { public: DECLARE_META_INTERFACE(SurfaceComposer) + static constexpr size_t MAX_LAYERS = 4096; + // flags for setTransactionState() enum { eSynchronous = 0x01, diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index ad7cbfe914..917c0d4831 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -178,7 +178,6 @@ public: status_t getUniqueId(uint64_t* outId) const; status_t getConsumerUsage(uint64_t* outUsage) const; - // See IGraphicBufferProducer::setFrameRate status_t setFrameRate(float frameRate, int8_t compatibility); protected: diff --git a/libs/gui/include/gui/mock/GraphicBufferConsumer.h b/libs/gui/include/gui/mock/GraphicBufferConsumer.h index e940cf3248..98f24c2d44 100644 --- a/libs/gui/include/gui/mock/GraphicBufferConsumer.h +++ b/libs/gui/include/gui/mock/GraphicBufferConsumer.h @@ -49,8 +49,6 @@ public: MOCK_CONST_METHOD1(getSidebandStream, status_t(sp<NativeHandle>*)); MOCK_METHOD2(getOccupancyHistory, status_t(bool, std::vector<OccupancyTracker::Segment>*)); MOCK_METHOD0(discardFreeBuffers, status_t()); - MOCK_METHOD1(setFrameRate, status_t(float)); - MOCK_CONST_METHOD1(getFrameRate, status_t(float*)); MOCK_CONST_METHOD2(dumpState, status_t(const String8&, String8*)); }; diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp index 0f7e2fb936..0ff33ac747 100644 --- a/libs/nativedisplay/AChoreographer.cpp +++ b/libs/nativedisplay/AChoreographer.cpp @@ -185,9 +185,18 @@ void Choreographer::unregisterRefreshRateCallback(AChoreographer_refreshRateCall } void Choreographer::scheduleCallbacks() { - AutoMutex _{mLock}; - nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); - if (mFrameCallbacks.top().dueTime <= now) { + const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); + nsecs_t dueTime; + { + AutoMutex _{mLock}; + // If there are no pending callbacks then don't schedule a vsync + if (mFrameCallbacks.empty()) { + return; + } + dueTime = mFrameCallbacks.top().dueTime; + } + + if (dueTime <= now) { ALOGV("choreographer %p ~ scheduling vsync", this); scheduleVsync(); return; diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index 416ebfefc4..0d4305b868 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -381,15 +381,6 @@ GLESRenderEngine::GLESRenderEngine(const RenderEngineCreationArgs& args, EGLDisp LOG_ALWAYS_FATAL_IF(!success, "can't make default context current"); } - const uint16_t protTexData[] = {0}; - glGenTextures(1, &mProtectedTexName); - glBindTexture(GL_TEXTURE_2D, mProtectedTexName); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData); - // mColorBlindnessCorrection = M; if (mUseColorManagement) { diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h index 4cd0b3d3b5..32dbad1050 100644 --- a/libs/renderengine/gl/GLESRenderEngine.h +++ b/libs/renderengine/gl/GLESRenderEngine.h @@ -178,7 +178,6 @@ private: EGLSurface mDummySurface; EGLContext mProtectedEGLContext; EGLSurface mProtectedDummySurface; - GLuint mProtectedTexName; GLint mMaxViewportDims[2]; GLint mMaxTextureSize; GLuint mVpWidth; diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp index cd2a448c3e..bf487c4aec 100644 --- a/libs/ui/Region.cpp +++ b/libs/ui/Region.cpp @@ -67,20 +67,19 @@ const Region Region::INVALID_REGION(Rect::INVALID_RECT); // ---------------------------------------------------------------------------- Region::Region() { - mStorage.push_back(Rect(0, 0)); + mStorage.add(Rect(0,0)); } Region::Region(const Region& rhs) + : mStorage(rhs.mStorage) { - mStorage.clear(); - mStorage.insert(mStorage.begin(), rhs.mStorage.begin(), rhs.mStorage.end()); #if defined(VALIDATE_REGIONS) validate(rhs, "rhs copy-ctor"); #endif } Region::Region(const Rect& rhs) { - mStorage.push_back(rhs); + mStorage.add(rhs); } Region::~Region() @@ -101,8 +100,8 @@ Region::~Region() * final, correctly ordered region buffer. Each rectangle will be compared with the span directly * above it, and subdivided to resolve any remaining T-junctions. */ -static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end, FatVector<Rect>& dst, - int spanDirection) { +static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end, + Vector<Rect>& dst, int spanDirection) { dst.clear(); const Rect* current = end - 1; @@ -110,7 +109,7 @@ static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end, F // add first span immediately do { - dst.push_back(*current); + dst.add(*current); current--; } while (current->top == lastTop && current >= begin); @@ -148,12 +147,12 @@ static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end, F if (prev.right <= left) break; if (prev.right > left && prev.right < right) { - dst.push_back(Rect(prev.right, top, right, bottom)); + dst.add(Rect(prev.right, top, right, bottom)); right = prev.right; } if (prev.left > left && prev.left < right) { - dst.push_back(Rect(prev.left, top, right, bottom)); + dst.add(Rect(prev.left, top, right, bottom)); right = prev.left; } @@ -167,12 +166,12 @@ static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end, F if (prev.left >= right) break; if (prev.left > left && prev.left < right) { - dst.push_back(Rect(left, top, prev.left, bottom)); + dst.add(Rect(left, top, prev.left, bottom)); left = prev.left; } if (prev.right > left && prev.right < right) { - dst.push_back(Rect(left, top, prev.right, bottom)); + dst.add(Rect(left, top, prev.right, bottom)); left = prev.right; } // if an entry in the previous span is too far left, nothing further right in the @@ -184,7 +183,7 @@ static void reverseRectsResolvingJunctions(const Rect* begin, const Rect* end, F } if (left < right) { - dst.push_back(Rect(left, top, right, bottom)); + dst.add(Rect(left, top, right, bottom)); } current--; @@ -202,14 +201,13 @@ Region Region::createTJunctionFreeRegion(const Region& r) { if (r.isEmpty()) return r; if (r.isRect()) return r; - FatVector<Rect> reversed; + Vector<Rect> reversed; reverseRectsResolvingJunctions(r.begin(), r.end(), reversed, direction_RTL); Region outputRegion; - reverseRectsResolvingJunctions(reversed.data(), reversed.data() + reversed.size(), - outputRegion.mStorage, direction_LTR); - outputRegion.mStorage.push_back( - r.getBounds()); // to make region valid, mStorage must end with bounds + reverseRectsResolvingJunctions(reversed.begin(), reversed.end(), + outputRegion.mStorage, direction_LTR); + outputRegion.mStorage.add(r.getBounds()); // to make region valid, mStorage must end with bounds #if defined(VALIDATE_REGIONS) validate(outputRegion, "T-Junction free region"); @@ -224,8 +222,7 @@ Region& Region::operator = (const Region& rhs) validate(*this, "this->operator="); validate(rhs, "rhs.operator="); #endif - mStorage.clear(); - mStorage.insert(mStorage.begin(), rhs.mStorage.begin(), rhs.mStorage.end()); + mStorage = rhs.mStorage; return *this; } @@ -234,7 +231,7 @@ Region& Region::makeBoundsSelf() if (mStorage.size() >= 2) { const Rect bounds(getBounds()); mStorage.clear(); - mStorage.push_back(bounds); + mStorage.add(bounds); } return *this; } @@ -258,25 +255,25 @@ bool Region::contains(int x, int y) const { void Region::clear() { mStorage.clear(); - mStorage.push_back(Rect(0, 0)); + mStorage.add(Rect(0,0)); } void Region::set(const Rect& r) { mStorage.clear(); - mStorage.push_back(r); + mStorage.add(r); } void Region::set(int32_t w, int32_t h) { mStorage.clear(); - mStorage.push_back(Rect(w, h)); + mStorage.add(Rect(w, h)); } void Region::set(uint32_t w, uint32_t h) { mStorage.clear(); - mStorage.push_back(Rect(w, h)); + mStorage.add(Rect(w, h)); } bool Region::isTriviallyEqual(const Region& region) const { @@ -302,7 +299,8 @@ bool Region::hasSameRects(const Region& other) const { void Region::addRectUnchecked(int l, int t, int r, int b) { Rect rect(l,t,r,b); - mStorage.insert(mStorage.end() - 1, rect); + size_t where = mStorage.size() - 1; + mStorage.insertAt(rect, where, 1); } // ---------------------------------------------------------------------------- @@ -352,7 +350,7 @@ Region& Region::translateSelf(int x, int y) { Region& Region::scaleSelf(float sx, float sy) { size_t count = mStorage.size(); - Rect* rects = mStorage.data(); + Rect* rects = mStorage.editArray(); while (count) { rects->left = static_cast<int32_t>(static_cast<float>(rects->left) * sx + 0.5f); rects->right = static_cast<int32_t>(static_cast<float>(rects->right) * sx + 0.5f); @@ -457,10 +455,10 @@ const Region Region::operation(const Region& rhs, int dx, int dy, uint32_t op) c class Region::rasterizer : public region_operator<Rect>::region_rasterizer { Rect bounds; - FatVector<Rect>& storage; + Vector<Rect>& storage; Rect* head; Rect* tail; - FatVector<Rect> span; + Vector<Rect> span; Rect* cur; public: explicit rasterizer(Region& reg) @@ -487,8 +485,8 @@ Region::rasterizer::~rasterizer() flushSpan(); } if (storage.size()) { - bounds.top = storage.front().top; - bounds.bottom = storage.back().bottom; + bounds.top = storage.itemAt(0).top; + bounds.bottom = storage.top().bottom; if (storage.size() == 1) { storage.clear(); } @@ -496,7 +494,7 @@ Region::rasterizer::~rasterizer() bounds.left = 0; bounds.right = 0; } - storage.push_back(bounds); + storage.add(bounds); } void Region::rasterizer::operator()(const Rect& rect) @@ -511,15 +509,15 @@ void Region::rasterizer::operator()(const Rect& rect) return; } } - span.push_back(rect); - cur = span.data() + (span.size() - 1); + span.add(rect); + cur = span.editArray() + (span.size() - 1); } void Region::rasterizer::flushSpan() { bool merge = false; if (tail-head == ssize_t(span.size())) { - Rect const* p = span.data(); + Rect const* p = span.editArray(); Rect const* q = head; if (p->top == q->bottom) { merge = true; @@ -534,17 +532,17 @@ void Region::rasterizer::flushSpan() } } if (merge) { - const int bottom = span.front().bottom; + const int bottom = span[0].bottom; Rect* r = head; while (r != tail) { r->bottom = bottom; r++; } } else { - bounds.left = min(span.front().left, bounds.left); - bounds.right = max(span.back().right, bounds.right); - storage.insert(storage.end(), span.begin(), span.end()); - tail = storage.data() + storage.size(); + bounds.left = min(span.itemAt(0).left, bounds.left); + bounds.right = max(span.top().right, bounds.right); + storage.appendVector(span); + tail = storage.editArray() + storage.size(); head = tail - span.size(); } span.clear(); @@ -552,7 +550,7 @@ void Region::rasterizer::flushSpan() bool Region::validate(const Region& reg, const char* name, bool silent) { - if (reg.mStorage.empty()) { + if (reg.mStorage.isEmpty()) { ALOGE_IF(!silent, "%s: mStorage is empty, which is never valid", name); // return immediately as the code below assumes mStorage is non-empty return false; @@ -691,8 +689,9 @@ void Region::boolean_operation(uint32_t op, Region& dst, } sk_dst.op(sk_lhs, sk_rhs, sk_op); - if (sk_dst.empty() && dst.empty()) return; - + if (sk_dst.isEmpty() && dst.isEmpty()) + return; + bool same = true; Region::const_iterator head = dst.begin(); Region::const_iterator const tail = dst.end(); @@ -787,7 +786,7 @@ void Region::translate(Region& reg, int dx, int dy) validate(reg, "translate (before)"); #endif size_t count = reg.mStorage.size(); - Rect* rects = reg.mStorage.data(); + Rect* rects = reg.mStorage.editArray(); while (count) { rects->offsetBy(dx, dy); rects++; @@ -867,25 +866,24 @@ status_t Region::unflatten(void const* buffer, size_t size) { ALOGE("Region::unflatten() failed, invalid region"); return BAD_VALUE; } - mStorage.clear(); - mStorage.insert(mStorage.begin(), result.mStorage.begin(), result.mStorage.end()); + mStorage = result.mStorage; return NO_ERROR; } // ---------------------------------------------------------------------------- Region::const_iterator Region::begin() const { - return mStorage.data(); + return mStorage.array(); } Region::const_iterator Region::end() const { // Workaround for b/77643177 // mStorage should never be empty, but somehow it is and it's causing // an abort in ubsan - if (mStorage.empty()) return mStorage.data(); + if (mStorage.isEmpty()) return mStorage.array(); size_t numRects = isRect() ? 1 : mStorage.size() - 1; - return mStorage.data() + numRects; + return mStorage.array() + numRects; } Rect const* Region::getArray(size_t* count) const { diff --git a/libs/ui/include/ui/FatVector.h b/libs/ui/include/ui/FatVector.h deleted file mode 100644 index 25fe3a0a2a..0000000000 --- a/libs/ui/include/ui/FatVector.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2019, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_REGION_FAT_VECTOR_H -#define ANDROID_REGION_FAT_VECTOR_H - -#include <stddef.h> -#include <stdlib.h> -#include <utils/Log.h> -#include <type_traits> - -#include <vector> - -namespace android { - -template <typename T, size_t SIZE = 4> -class InlineStdAllocator { -public: - struct Allocation { - private: - Allocation(const Allocation&) = delete; - void operator=(const Allocation&) = delete; - - public: - Allocation() {} - // char array instead of T array, so memory is uninitialized, with no destructors run - char array[sizeof(T) * SIZE]; - bool inUse = false; - }; - - typedef T value_type; // needed to implement std::allocator - typedef T* pointer; // needed to implement std::allocator - - explicit InlineStdAllocator(Allocation& allocation) : mAllocation(allocation) {} - InlineStdAllocator(const InlineStdAllocator& other) : mAllocation(other.mAllocation) {} - ~InlineStdAllocator() {} - - T* allocate(size_t num, const void* = 0) { - if (!mAllocation.inUse && num <= SIZE) { - mAllocation.inUse = true; - return static_cast<T*>(static_cast<void*>(mAllocation.array)); - } else { - return static_cast<T*>(static_cast<void*>(malloc(num * sizeof(T)))); - } - } - - void deallocate(pointer p, size_t) { - if (p == static_cast<T*>(static_cast<void*>(mAllocation.array))) { - mAllocation.inUse = false; - } else { - // 'free' instead of delete here - destruction handled separately - free(p); - } - } - Allocation& mAllocation; -}; - -/** - * std::vector with SIZE elements preallocated into an internal buffer. - * - * Useful for avoiding the cost of malloc in cases where only SIZE or - * fewer elements are needed in the common case. - */ -template <typename T, size_t SIZE = 4> -class FatVector : public std::vector<T, InlineStdAllocator<T, SIZE>> { -public: - FatVector() - : std::vector<T, InlineStdAllocator<T, SIZE>>(InlineStdAllocator<T, SIZE>(mAllocation)) { - this->reserve(SIZE); - } - - explicit FatVector(size_t capacity) : FatVector() { this->resize(capacity); } - -private: - typename InlineStdAllocator<T, SIZE>::Allocation mAllocation; -}; - -} // namespace android - -#endif // ANDROID_REGION_FAT_VECTOR_H diff --git a/libs/ui/include/ui/Region.h b/libs/ui/include/ui/Region.h index 6bb7b8d21c..2db3b10f13 100644 --- a/libs/ui/include/ui/Region.h +++ b/libs/ui/include/ui/Region.h @@ -21,13 +21,13 @@ #include <sys/types.h> #include <ostream> +#include <utils/Vector.h> + #include <ui/Rect.h> #include <utils/Flattenable.h> #include <android-base/macros.h> -#include "FatVector.h" - #include <string> namespace android { @@ -180,7 +180,7 @@ private: // with an extra Rect as the last element which is set to the // bounds of the region. However, if the region is // a simple Rect then mStorage contains only that rect. - FatVector<Rect> mStorage; + Vector<Rect> mStorage; }; @@ -235,3 +235,4 @@ static inline void PrintTo(const Region& region, ::std::ostream* os) { }; // namespace android #endif // ANDROID_UI_REGION_H + diff --git a/libs/ui/include_vndk/ui/FatVector.h b/libs/ui/include_vndk/ui/FatVector.h deleted file mode 120000 index bf30166784..0000000000 --- a/libs/ui/include_vndk/ui/FatVector.h +++ /dev/null @@ -1 +0,0 @@ -../../include/ui/FatVector.h
\ No newline at end of file diff --git a/services/inputflinger/BlockingQueue.h b/services/inputflinger/BlockingQueue.h index db9f26ec12..b612ca77ce 100644 --- a/services/inputflinger/BlockingQueue.h +++ b/services/inputflinger/BlockingQueue.h @@ -45,10 +45,7 @@ public: T pop() { std::unique_lock lock(mLock); android::base::ScopedLockAssertion assumeLock(mLock); - mHasElements.wait(lock, [this]{ - android::base::ScopedLockAssertion assumeLock(mLock); - return !this->mQueue.empty(); - }); + mHasElements.wait(lock, [this]() REQUIRES(mLock) { return !this->mQueue.empty(); }); T t = std::move(mQueue.front()); mQueue.erase(mQueue.begin()); return t; diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp index ae9a34882e..e5e83d752c 100644 --- a/services/inputflinger/InputClassifier.cpp +++ b/services/inputflinger/InputClassifier.cpp @@ -250,7 +250,7 @@ void MotionClassifier::callInputClassifierHal() { case ClassifierEventType::DEVICE_RESET: { const int32_t deviceId = *(event.getDeviceId()); halResponseOk = mService->resetDevice(deviceId).isOk(); - setClassification(deviceId, MotionClassification::NONE); + clearDeviceState(deviceId); break; } case ClassifierEventType::HAL_RESET: { @@ -321,6 +321,12 @@ void MotionClassifier::updateLastDownTime(int32_t deviceId, nsecs_t downTime) { mClassifications[deviceId] = MotionClassification::NONE; } +void MotionClassifier::clearDeviceState(int32_t deviceId) { + std::scoped_lock lock(mLock); + mClassifications.erase(deviceId); + mLastDownTimes.erase(deviceId); +} + MotionClassification MotionClassifier::classify(const NotifyMotionArgs& args) { if ((args.action & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_DOWN) { updateLastDownTime(args.deviceId, args.downTime); @@ -455,6 +461,7 @@ void InputClassifier::serviceDied(uint64_t /*cookie*/, void InputClassifier::dump(std::string& dump) { std::scoped_lock lock(mLock); dump += "Input Classifier State:\n"; + dump += StringPrintf(INDENT1 "Deep press: %s\n", deepPressEnabled() ? "enabled" : "disabled"); dump += INDENT1 "Motion Classifier:\n"; if (mMotionClassifier) { diff --git a/services/inputflinger/InputClassifier.h b/services/inputflinger/InputClassifier.h index 47e20dbf75..96923526da 100644 --- a/services/inputflinger/InputClassifier.h +++ b/services/inputflinger/InputClassifier.h @@ -212,6 +212,8 @@ private: void updateLastDownTime(int32_t deviceId, nsecs_t downTime); + void clearDeviceState(int32_t deviceId); + /** * Exit the InputClassifier HAL thread. * Useful for tests to ensure proper cleanup. diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index f5a99cadd7..18f7f44fa5 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -564,8 +564,6 @@ void BufferQueueLayer::gatherBufferInfo() { mBufferInfo.mApi = mConsumer->getCurrentApi(); mBufferInfo.mPixelFormat = mFormat; mBufferInfo.mTransformToDisplayInverse = mConsumer->getTransformToDisplayInverse(); - float latchedFrameRate; - mConsumer->getFrameRate(&latchedFrameRate); } sp<Layer> BufferQueueLayer::createClone() { diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp index 550ec6173a..06e0cbb044 100644 --- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp +++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp @@ -124,24 +124,20 @@ public: static std::unique_ptr<HalWrapper> connect() { // Power HAL 1.3 is not guaranteed to be available, thus we need to query // Power HAL 1.0 first and try to cast it to Power HAL 1.3. - // Power HAL 1.0 is always available, thus if we fail to query it, it means - // Power HAL is not available temporarily and we should retry later. However, - // if Power HAL 1.0 is available and we can't cast it to Power HAL 1.3, - // it means Power HAL 1.3 is not available at all, so we should stop trying. sp<V1_3::IPower> powerHal = nullptr; - if (sHasPowerHal_1_3) { - sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService(); - if (powerHal_1_0 != nullptr) { - // Try to cast to Power HAL 1.3 - powerHal = V1_3::IPower::castFrom(powerHal_1_0); - if (powerHal == nullptr) { - ALOGW("No Power HAL 1.3 service in system"); - sHasPowerHal_1_3 = false; - } else { - ALOGI("Loaded Power HAL 1.3 service"); - } + sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService(); + if (powerHal_1_0 != nullptr) { + // Try to cast to Power HAL 1.3 + powerHal = V1_3::IPower::castFrom(powerHal_1_0); + if (powerHal == nullptr) { + ALOGW("No Power HAL 1.3 service in system, disabling PowerAdvisor"); + } else { + ALOGI("Loaded Power HAL 1.3 service"); } + } else { + ALOGW("No Power HAL found, disabling PowerAdvisor"); } + if (powerHal == nullptr) { return nullptr; } @@ -162,12 +158,9 @@ public: } private: - static bool sHasPowerHal_1_3; const sp<V1_3::IPower> mPowerHal = nullptr; }; -bool HidlPowerHalWrapper::sHasPowerHal_1_3 = true; - class AidlPowerHalWrapper : public PowerAdvisor::HalWrapper { public: AidlPowerHalWrapper(sp<IPower> powerHal) : mPowerHal(std::move(powerHal)) { @@ -226,7 +219,13 @@ private: PowerAdvisor::HalWrapper* PowerAdvisor::getPowerHal() { static std::unique_ptr<HalWrapper> sHalWrapper = nullptr; + static bool sHasHal = true; + + if (!sHasHal) { + return nullptr; + } + // If we used to have a HAL, but it stopped responding, attempt to reconnect if (mReconnectPowerHal) { sHalWrapper = nullptr; mReconnectPowerHal = false; @@ -244,6 +243,12 @@ PowerAdvisor::HalWrapper* PowerAdvisor::getPowerHal() { sHalWrapper = HidlPowerHalWrapper::connect(); } + // If we make it to this point and still don't have a HAL, it's unlikely we + // will, so stop trying + if (sHalWrapper == nullptr) { + sHasHal = false; + } + return sHalWrapper.get(); } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 766871e3b0..64cfb3d699 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -719,9 +719,14 @@ std::vector<compositionengine::LayerFE::LayerSettings> Layer::prepareClientCompo Hwc2::IComposerClient::Composition Layer::getCompositionType( const sp<const DisplayDevice>& display) const { const auto outputLayer = findOutputLayerForDisplay(display); - LOG_FATAL_IF(!outputLayer); - return outputLayer->getState().hwc ? (*outputLayer->getState().hwc).hwcCompositionType - : Hwc2::IComposerClient::Composition::CLIENT; + if (outputLayer == nullptr) { + return Hwc2::IComposerClient::Composition::INVALID; + } + if (outputLayer->getState().hwc) { + return (*outputLayer->getState().hwc).hwcCompositionType; + } else { + return Hwc2::IComposerClient::Composition::CLIENT; + } } bool Layer::getClearClientTarget(const sp<const DisplayDevice>& display) const { @@ -2052,13 +2057,20 @@ void Layer::setInputInfo(const InputWindowInfo& info) { setTransactionFlags(eTransactionNeeded); } -LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags) const { +LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags, + const sp<const DisplayDevice>& device) const { LayerProto* layerProto = layersProto.add_layers(); writeToProtoDrawingState(layerProto, traceFlags); writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags); + // Only populate for the primary display. + if (device) { + const Hwc2::IComposerClient::Composition compositionType = getCompositionType(device); + layerProto->set_hwc_composition_type(static_cast<HwcCompositionType>(compositionType)); + } + for (const sp<Layer>& layer : mDrawingChildren) { - layer->writeToProto(layersProto, traceFlags); + layer->writeToProto(layersProto, traceFlags, device); } return layerProto; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 5d2144aed4..20d72324c3 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -506,7 +506,8 @@ public: bool isRemovedFromCurrentState() const; LayerProto* writeToProto(LayersProto& layersProto, - uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const; + uint32_t traceFlags = SurfaceTracing::TRACE_ALL, + const sp<const DisplayDevice>& device = nullptr) const; // Write states that are modified by the main thread. This includes drawing // state as well as buffer data. This should be called in the main or tracing diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp index 40a63d77b5..5009e10532 100644 --- a/services/surfaceflinger/MonitoredProducer.cpp +++ b/services/surfaceflinger/MonitoredProducer.cpp @@ -162,10 +162,6 @@ status_t MonitoredProducer::setAutoPrerotation(bool autoPrerotation) { return mProducer->setAutoPrerotation(autoPrerotation); } -status_t MonitoredProducer::setFrameRate(float frameRate) { - return mProducer->setFrameRate(frameRate); -} - IBinder* MonitoredProducer::onAsBinder() { return this; } diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h index 4bda831aeb..788919b3da 100644 --- a/services/surfaceflinger/MonitoredProducer.h +++ b/services/surfaceflinger/MonitoredProducer.h @@ -71,7 +71,6 @@ public: virtual status_t getUniqueId(uint64_t* outId) const override; virtual status_t getConsumerUsage(uint64_t* outUsage) const override; virtual status_t setAutoPrerotation(bool autoPrerotation) override; - virtual status_t setFrameRate(float frameRate) override; // The Layer which created this producer, and on which queued Buffer's will be displayed. sp<Layer> getLayer() const; diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 682679c703..c675971156 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -168,9 +168,9 @@ bool RefreshRateOverlay::createLayer() { } void RefreshRateOverlay::primeCache() { - auto allRefreshRates = mFlinger.mRefreshRateConfigs->getAllRefreshRates(); + auto& allRefreshRates = mFlinger.mRefreshRateConfigs->getAllRefreshRates(); if (allRefreshRates.size() == 1) { - auto fps = allRefreshRates.begin()->second.fps; + auto fps = allRefreshRates.begin()->second->fps; half4 color = {LOW_FPS_COLOR, ALPHA}; mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color)); return; @@ -178,8 +178,8 @@ void RefreshRateOverlay::primeCache() { std::vector<uint32_t> supportedFps; supportedFps.reserve(allRefreshRates.size()); - for (auto [ignored, refreshRate] : allRefreshRates) { - supportedFps.push_back(refreshRate.fps); + for (auto& [ignored, refreshRate] : allRefreshRates) { + supportedFps.push_back(refreshRate->fps); } std::sort(supportedFps.begin(), supportedFps.end()); diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp index b755798a92..b4365bf03f 100644 --- a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp @@ -82,14 +82,14 @@ bool LayerInfoV2::isFrequent(nsecs_t now) const { } } - const auto numFrames = std::distance(it, mFrameTimes.end()) - 1; - if (numFrames <= 0) { + const auto numFrames = std::distance(it, mFrameTimes.end()); + if (numFrames < FREQUENT_LAYER_WINDOW_SIZE) { return false; } // Layer is considered frequent if the average frame rate is higher than the threshold const auto totalTime = mFrameTimes.back().queueTime - it->queueTime; - return (1e9f * numFrames) / totalTime >= MIN_FPS_FOR_FREQUENT_LAYER; + return (1e9f * (numFrames - 1)) / totalTime >= MIN_FPS_FOR_FREQUENT_LAYER; } bool LayerInfoV2::hasEnoughDataForHeuristic() const { diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp index 63d9c4bc5a..c04447d106 100644 --- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp +++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp @@ -71,10 +71,10 @@ std::unordered_map<float, PhaseOffsets::Offsets> PhaseOffsets::initializeOffsets std::unordered_map<float, Offsets> offsets; for (const auto& [ignored, refreshRate] : refreshRateConfigs.getAllRefreshRates()) { - if (refreshRate.fps > 65.0f) { - offsets.emplace(refreshRate.fps, getHighFpsOffsets(refreshRate.vsyncPeriod)); + if (refreshRate->fps > 65.0f) { + offsets.emplace(refreshRate->fps, getHighFpsOffsets(refreshRate->vsyncPeriod)); } else { - offsets.emplace(refreshRate.fps, getDefaultOffsets(refreshRate.vsyncPeriod)); + offsets.emplace(refreshRate->fps, getDefaultOffsets(refreshRate->vsyncPeriod)); } } return offsets; @@ -238,7 +238,7 @@ static std::vector<float> getRefreshRatesFromConfigs( refreshRates.reserve(allRefreshRates.size()); for (const auto& [ignored, refreshRate] : allRefreshRates) { - refreshRates.emplace_back(refreshRate.fps); + refreshRates.emplace_back(refreshRate->fps); } return refreshRates; diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 1765d2d8f7..9edbaee22f 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -235,13 +235,13 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2( ? getBestRefreshRate(scores.rbegin(), scores.rend()) : getBestRefreshRate(scores.begin(), scores.end()); - return bestRefreshRate == nullptr ? *mCurrentRefreshRate : *bestRefreshRate; + return *bestRefreshRate; } template <typename Iter> const RefreshRate* RefreshRateConfigs::getBestRefreshRate(Iter begin, Iter end) const { - const RefreshRate* bestRefreshRate = nullptr; - float max = 0; + const RefreshRate* bestRefreshRate = begin->first; + float max = begin->second; for (auto i = begin; i != end; ++i) { const auto [refreshRate, score] = *i; ALOGV("%s scores %.2f", refreshRate->name.c_str(), score); @@ -286,12 +286,12 @@ const RefreshRate& RefreshRateConfigs::getCurrentRefreshRateByPolicyLocked() con mCurrentRefreshRate) != mAvailableRefreshRates.end()) { return *mCurrentRefreshRate; } - return mRefreshRates.at(mDefaultConfig); + return *mRefreshRates.at(mDefaultConfig); } void RefreshRateConfigs::setCurrentConfigId(HwcConfigIndexType configId) { std::lock_guard lock(mLock); - mCurrentRefreshRate = &mRefreshRates.at(configId); + mCurrentRefreshRate = mRefreshRates.at(configId).get(); } RefreshRateConfigs::RefreshRateConfigs(const std::vector<InputConfig>& configs, @@ -326,7 +326,7 @@ status_t RefreshRateConfigs::setPolicy(HwcConfigIndexType defaultConfigId, float if (mRefreshRates.count(defaultConfigId) == 0) { return BAD_VALUE; } - const RefreshRate& refreshRate = mRefreshRates.at(defaultConfigId); + const RefreshRate& refreshRate = *mRefreshRates.at(defaultConfigId); if (!refreshRate.inPolicy(minRefreshRate, maxRefreshRate)) { return BAD_VALUE; } @@ -361,10 +361,10 @@ void RefreshRateConfigs::getSortedRefreshRateList( outRefreshRates->clear(); outRefreshRates->reserve(mRefreshRates.size()); for (const auto& [type, refreshRate] : mRefreshRates) { - if (shouldAddRefreshRate(refreshRate)) { + if (shouldAddRefreshRate(*refreshRate)) { ALOGV("getSortedRefreshRateList: config %d added to list policy", - refreshRate.configId.value()); - outRefreshRates->push_back(&refreshRate); + refreshRate->configId.value()); + outRefreshRates->push_back(refreshRate.get()); } } @@ -376,7 +376,7 @@ void RefreshRateConfigs::getSortedRefreshRateList( void RefreshRateConfigs::constructAvailableRefreshRates() { // Filter configs based on current policy and sort based on vsync period - HwcConfigGroupType group = mRefreshRates.at(mDefaultConfig).configGroup; + HwcConfigGroupType group = mRefreshRates.at(mDefaultConfig)->configGroup; ALOGV("constructAvailableRefreshRates: default %d group %d min %.2f max %.2f", mDefaultConfig.value(), group.value(), mMinRefreshRateFps, mMaxRefreshRateFps); getSortedRefreshRateList( @@ -403,16 +403,15 @@ void RefreshRateConfigs::init(const std::vector<InputConfig>& configs, LOG_ALWAYS_FATAL_IF(configs.empty()); LOG_ALWAYS_FATAL_IF(currentHwcConfig.value() >= configs.size()); - auto buildRefreshRate = [&](InputConfig config) -> RefreshRate { - const float fps = 1e9f / config.vsyncPeriod; - return RefreshRate(config.configId, config.vsyncPeriod, config.configGroup, - base::StringPrintf("%2.ffps", fps), fps); - }; - for (const auto& config : configs) { - mRefreshRates.emplace(config.configId, buildRefreshRate(config)); + const float fps = 1e9f / config.vsyncPeriod; + mRefreshRates.emplace(config.configId, + std::make_unique<RefreshRate>(config.configId, config.vsyncPeriod, + config.configGroup, + base::StringPrintf("%2.ffps", fps), + fps)); if (config.configId == currentHwcConfig) { - mCurrentRefreshRate = &mRefreshRates.at(config.configId); + mCurrentRefreshRate = mRefreshRates.at(config.configId).get(); } } diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index c8aec86db3..9cd59593bb 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -59,6 +59,8 @@ public: configGroup(configGroup), name(std::move(name)), fps(fps) {} + + RefreshRate(const RefreshRate&) = delete; // This config ID corresponds to the position of the config in the vector that is stored // on the device. const HwcConfigIndexType configId; @@ -85,7 +87,8 @@ public: bool operator==(const RefreshRate& other) const { return !(*this != other); } }; - using AllRefreshRatesMapType = std::unordered_map<HwcConfigIndexType, const RefreshRate>; + using AllRefreshRatesMapType = + std::unordered_map<HwcConfigIndexType, std::unique_ptr<const RefreshRate>>; // Sets the current policy to choose refresh rates. Returns NO_ERROR if the requested policy is // valid, or a negative error value otherwise. policyChanged, if non-null, will be set to true @@ -163,7 +166,7 @@ public: // Returns the refresh rate that corresponds to a HwcConfigIndexType. This won't change at // runtime. const RefreshRate& getRefreshRateFromConfigId(HwcConfigIndexType configId) const { - return mRefreshRates.at(configId); + return *mRefreshRates.at(configId); }; // Stores the current configId the device operates at diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 54442391ea..96fa0610d0 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -463,7 +463,7 @@ void Scheduler::chooseRefreshRateForContent() { return; } mFeatures.configId = newConfigId; - auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); + auto& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); mSchedulerCallback.changeRefreshRate(newRefreshRate, ConfigEvent::Changed); } } @@ -515,7 +515,7 @@ void Scheduler::kernelIdleTimerCallback(TimerState state) { // TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate // magic number - const auto refreshRate = mRefreshRateConfigs.getCurrentRefreshRate(); + const auto& refreshRate = mRefreshRateConfigs.getCurrentRefreshRate(); constexpr float FPS_THRESHOLD_FOR_KERNEL_TIMER = 65.0f; if (state == TimerState::Reset && refreshRate.fps > FPS_THRESHOLD_FOR_KERNEL_TIMER) { // If we're not in performance mode then the kernel timer shouldn't do diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.cpp b/services/surfaceflinger/Scheduler/VSyncReactor.cpp index 949ba4ca52..8987dcdc58 100644 --- a/services/surfaceflinger/Scheduler/VSyncReactor.cpp +++ b/services/surfaceflinger/Scheduler/VSyncReactor.cpp @@ -19,8 +19,10 @@ #define LOG_TAG "VSyncReactor" //#define LOG_NDEBUG 0 #include "VSyncReactor.h" +#include <cutils/properties.h> #include <log/log.h> #include <utils/Trace.h> +#include "../TracedOrdinal.h" #include "TimeKeeper.h" #include "VSyncDispatch.h" #include "VSyncTracker.h" @@ -32,12 +34,35 @@ nsecs_t SystemClock::now() const { return systemTime(SYSTEM_TIME_MONOTONIC); } +class PredictedVsyncTracer { +public: + PredictedVsyncTracer(VSyncDispatch& dispatch) + : mRegistration(dispatch, + std::bind(&PredictedVsyncTracer::callback, this, std::placeholders::_1, + std::placeholders::_2), + "PredictedVsyncTracer") { + mRegistration.schedule(0, 0); + } + +private: + TracedOrdinal<bool> mParity = {"VSYNC-predicted", 0}; + VSyncCallbackRegistration mRegistration; + + void callback(nsecs_t /*vsyncTime*/, nsecs_t /*targetWakeupTim*/) { + mParity = !mParity; + mRegistration.schedule(0, 0); + } +}; + VSyncReactor::VSyncReactor(std::unique_ptr<Clock> clock, std::unique_ptr<VSyncDispatch> dispatch, std::unique_ptr<VSyncTracker> tracker, size_t pendingFenceLimit) : mClock(std::move(clock)), mTracker(std::move(tracker)), mDispatch(std::move(dispatch)), - mPendingLimit(pendingFenceLimit) {} + mPendingLimit(pendingFenceLimit), + mPredictedVsyncTracer(property_get_bool("debug.sf.show_predicted_vsync", false) + ? std::make_unique<PredictedVsyncTracer>(*mDispatch) + : nullptr) {} VSyncReactor::~VSyncReactor() = default; @@ -287,7 +312,7 @@ status_t VSyncReactor::addEventListener(const char* name, nsecs_t phase, auto it = mCallbacks.find(callback); if (it == mCallbacks.end()) { // TODO (b/146557561): resolve lastCallbackTime semantics in DispSync i/f. - static auto constexpr maxListeners = 3; + static auto constexpr maxListeners = 4; if (mCallbacks.size() >= maxListeners) { ALOGE("callback %s not added, exceeded callback limit of %i (currently %zu)", name, maxListeners, mCallbacks.size()); diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.h b/services/surfaceflinger/Scheduler/VSyncReactor.h index aa8a38d871..7d8a8e3bb0 100644 --- a/services/surfaceflinger/Scheduler/VSyncReactor.h +++ b/services/surfaceflinger/Scheduler/VSyncReactor.h @@ -30,6 +30,7 @@ class Clock; class VSyncDispatch; class VSyncTracker; class CallbackRepeater; +class PredictedVsyncTracer; // TODO (b/145217110): consider renaming. class VSyncReactor : public android::DispSync { @@ -86,6 +87,8 @@ private: std::unordered_map<DispSync::Callback*, std::unique_ptr<CallbackRepeater>> mCallbacks GUARDED_BY(mMutex); + + const std::unique_ptr<PredictedVsyncTracer> mPredictedVsyncTracer; }; class SystemClock : public Clock { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 1d00624199..e764d24eaa 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -367,7 +367,7 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI property_get("ro.sf.blurs_are_expensive", value, "0"); mBlursAreExpensive = atoi(value); - const size_t defaultListSize = MAX_LAYERS; + const size_t defaultListSize = ISurfaceComposer::MAX_LAYERS; auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize)); mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize; @@ -903,18 +903,27 @@ int SurfaceFlinger::getActiveConfig(const sp<IBinder>& displayToken) { void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) { ATRACE_CALL(); - auto refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(info.configId); + auto& refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(info.configId); ALOGV("setDesiredActiveConfig(%s)", refreshRate.name.c_str()); - // Don't check against the current mode yet. Worst case we set the desired - // config twice. However event generation config might have changed so we need to update it - // accordingly std::lock_guard<std::mutex> lock(mActiveConfigLock); - const Scheduler::ConfigEvent prevConfig = mDesiredActiveConfig.event; - mDesiredActiveConfig = info; - mDesiredActiveConfig.event = mDesiredActiveConfig.event | prevConfig; + if (mDesiredActiveConfigChanged) { + // If a config change is pending, just cache the latest request in + // mDesiredActiveConfig + const Scheduler::ConfigEvent prevConfig = mDesiredActiveConfig.event; + mDesiredActiveConfig = info; + mDesiredActiveConfig.event = mDesiredActiveConfig.event | prevConfig; + } else { + // Check is we are already at the desired config + const auto display = getDefaultDisplayDeviceLocked(); + if (!display || display->getActiveConfig() == refreshRate.configId) { + return; + } + + // Initiate a config change. + mDesiredActiveConfigChanged = true; + mDesiredActiveConfig = info; - if (!mDesiredActiveConfigChanged) { // This will trigger HWC refresh without resetting the idle timer. repaintEverythingForHWC(); // Start receiving vsync samples now, so that we can detect a period @@ -927,7 +936,6 @@ void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) { mPhaseConfiguration->setRefreshRateFps(refreshRate.fps); mVSyncModulator->setPhaseOffsets(mPhaseConfiguration->getCurrentOffsets()); } - mDesiredActiveConfigChanged = true; if (mRefreshRateOverlay) { mRefreshRateOverlay->changeRefreshRate(refreshRate); @@ -976,7 +984,7 @@ void SurfaceFlinger::setActiveConfigInternal() { mRefreshRateStats->setConfigMode(mUpcomingActiveConfig.configId); display->setActiveConfig(mUpcomingActiveConfig.configId); - auto refreshRate = + auto& refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(mUpcomingActiveConfig.configId); mPhaseConfiguration->setRefreshRateFps(refreshRate.fps); mVSyncModulator->setPhaseOffsets(mPhaseConfiguration->getCurrentOffsets()); @@ -996,7 +1004,7 @@ void SurfaceFlinger::desiredActiveConfigChangeDone() { mDesiredActiveConfig.event = Scheduler::ConfigEvent::None; mDesiredActiveConfigChanged = false; - auto const refreshRate = + const auto& refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(mDesiredActiveConfig.configId); mScheduler->resyncToHardwareVsync(true, refreshRate.vsyncPeriod); mPhaseConfiguration->setRefreshRateFps(refreshRate.fps); @@ -1029,7 +1037,7 @@ bool SurfaceFlinger::performSetActiveConfig() { desiredActiveConfig = mDesiredActiveConfig; } - auto refreshRate = + auto& refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(desiredActiveConfig.configId); ALOGV("performSetActiveConfig changing active config to %d(%s)", refreshRate.configId.value(), refreshRate.name.c_str()); @@ -1066,7 +1074,9 @@ bool SurfaceFlinger::performSetActiveConfig() { mUpcomingActiveConfig.configId.value(), constraints, &outTimeline); if (status != NO_ERROR) { - LOG_ALWAYS_FATAL("setActiveConfigWithConstraints failed: %d", status); + // setActiveConfigWithConstraints may fail if a hotplug event is just about + // to be sent. We just log the error in this case. + ALOGW("setActiveConfigWithConstraints failed: %d", status); return false; } @@ -3058,9 +3068,9 @@ status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBind parent = parentLayer; } - if (mNumLayers >= MAX_LAYERS) { + if (mNumLayers >= ISurfaceComposer::MAX_LAYERS) { ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(), - MAX_LAYERS); + ISurfaceComposer::MAX_LAYERS); return NO_MEMORY; } @@ -4450,13 +4460,20 @@ void SurfaceFlinger::dumpWideColorInfo(std::string& result) const { } LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { + Mutex::Autolock _l(mStateLock); + const auto device = getDefaultDisplayDeviceLocked(); LayersProto layersProto; for (const sp<Layer>& layer : mDrawingState.layersSortedByZ) { - layer->writeToProto(layersProto, traceFlags); + layer->writeToProto(layersProto, traceFlags, device); } + return layersProto; } +void SurfaceFlinger::dumpHwc(std::string& result) const { + getHwComposer().dump(result); +} + void SurfaceFlinger::dumpOffscreenLayersProto(LayersProto& layersProto, uint32_t traceFlags) const { // Add a fake invisible root layer to the proto output and parent all the offscreen layers to // it. @@ -4471,7 +4488,8 @@ void SurfaceFlinger::dumpOffscreenLayersProto(LayersProto& layersProto, uint32_t rootProto->add_children(offscreenLayer->sequence); // Add layer - LayerProto* layerProto = offscreenLayer->writeToProto(layersProto, traceFlags); + LayerProto* layerProto = + offscreenLayer->writeToProto(layersProto, traceFlags, nullptr /*device*/); layerProto->set_parent(offscreenRootLayerId); } } @@ -5120,7 +5138,7 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r n = data.readInt32(); if (n == 1 && !mRefreshRateOverlay) { mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this); - auto current = mRefreshRateConfigs->getCurrentRefreshRate(); + auto& current = mRefreshRateConfigs->getCurrentRefreshRate(); mRefreshRateOverlay->changeRefreshRate(current); } else if (n == 0) { mRefreshRateOverlay.reset(); @@ -5169,7 +5187,7 @@ void SurfaceFlinger::kernelTimerChanged(bool expired) { if (mRefreshRateOverlay) { const auto kernelTimerEnabled = property_get_bool(KERNEL_IDLE_TIMER_PROP, false); const bool timerExpired = kernelTimerEnabled && expired; - const auto& current = [this]() { + const auto& current = [this]() -> const RefreshRate& { std::lock_guard<std::mutex> lock(mActiveConfigLock); if (mDesiredActiveConfigChanged) { return mRefreshRateConfigs->getRefreshRateFromConfigId( @@ -5849,7 +5867,7 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal(const sp<DisplayDe display->getActiveConfig(), vsyncPeriod); auto configId = mScheduler->getPreferredConfigId(); - auto preferredRefreshRate = configId + auto& preferredRefreshRate = configId ? mRefreshRateConfigs->getRefreshRateFromConfigId(*configId) // NOTE: Choose the default config ID, if Scheduler doesn't have one in mind. : mRefreshRateConfigs->getRefreshRateFromConfigId(defaultConfig); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 477d7a5c5c..e7f9930392 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -351,7 +351,6 @@ private: // every half hour. enum { LOG_FRAME_STATS_PERIOD = 30*60*60 }; - static const size_t MAX_LAYERS = 4096; static const int MAX_TRACING_MEMORY = 100 * 1024 * 1024; // 100MB protected: @@ -921,6 +920,8 @@ private: LayersProto dumpDrawingStateProto(uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const; void dumpOffscreenLayersProto(LayersProto& layersProto, uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const; + // Dumps state from HW Composer + void dumpHwc(std::string& result) const; LayersProto dumpProtoFromMainThread(uint32_t traceFlags = SurfaceTracing::TRACE_ALL) EXCLUDES(mStateLock); void dumpOffscreenLayers(std::string& result) EXCLUDES(mStateLock); @@ -974,7 +975,7 @@ private: // Can't be unordered_set because wp<> isn't hashable std::set<wp<IBinder>> mGraphicBufferProducerList; - size_t mMaxGraphicBufferProducerListSize = MAX_LAYERS; + size_t mMaxGraphicBufferProducerListSize = ISurfaceComposer::MAX_LAYERS; // protected by mStateLock (but we could use another lock) bool mLayersRemoved = false; diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp index eb5c7de0fe..c5556ec28f 100644 --- a/services/surfaceflinger/SurfaceTracing.cpp +++ b/services/surfaceflinger/SurfaceTracing.cpp @@ -170,6 +170,12 @@ LayersTraceProto SurfaceTracing::traceLayersLocked(const char* where) { mFlinger.dumpOffscreenLayersProto(layers); entry.mutable_layers()->Swap(&layers); + if (mTraceFlags & SurfaceTracing::TRACE_HWC) { + std::string hwcDump; + mFlinger.dumpHwc(hwcDump); + entry.set_hwc_blob(hwcDump); + } + return entry; } diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h index 18524f02d8..3c24881d7c 100644 --- a/services/surfaceflinger/SurfaceTracing.h +++ b/services/surfaceflinger/SurfaceTracing.h @@ -56,6 +56,7 @@ public: TRACE_CRITICAL = 1 << 0, TRACE_INPUT = 1 << 1, TRACE_EXTRA = 1 << 2, + TRACE_HWC = 1 << 3, TRACE_ALL = 0xffffffff }; void setTraceFlags(uint32_t flags); diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index 8afe5039f8..7f1f542e4b 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -9,6 +9,23 @@ message LayersProto { repeated LayerProto layers = 1; } +// Must match definition in the IComposerClient HAL +enum HwcCompositionType { + // Invalid composition type + INVALID = 0; + // Layer was composited by the client into the client target buffer + CLIENT = 1; + // Layer was composited by the device through hardware overlays + DEVICE = 2; + // Layer was composited by the device using a color + SOLID_COLOR = 3; + // Similar to DEVICE, but the layer position may have been asynchronously set + // through setCursorPosition + CURSOR = 4; + // Layer was composited by the device via a sideband stream. + SIDEBAND = 5; +} + // Information about each layer. message LayerProto { // unique id per layer. @@ -73,7 +90,7 @@ message LayerProto { int32 window_type = 33 [deprecated=true]; int32 app_id = 34 [deprecated=true]; // The layer's composition type - int32 hwc_composition_type = 35; + HwcCompositionType hwc_composition_type = 35; // If it's a buffer layer, indicate if the content is protected bool is_protected = 36; // Current frame number being rendered. @@ -190,4 +207,4 @@ message InputWindowInfoProto { message ColorTransformProto { // This will be a 4x4 matrix of float values repeated float val = 1; -}
\ No newline at end of file +} diff --git a/services/surfaceflinger/layerproto/layerstrace.proto b/services/surfaceflinger/layerproto/layerstrace.proto index bee17d2d86..ac33a0ef9c 100644 --- a/services/surfaceflinger/layerproto/layerstrace.proto +++ b/services/surfaceflinger/layerproto/layerstrace.proto @@ -48,4 +48,7 @@ message LayersTraceProto { optional string where = 2; optional LayersProto layers = 3; + + // Blob for the current HWC information for all layers, reported by dumpsys. + optional string hwc_blob = 4; } diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp index 959c256262..37da76b172 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp @@ -36,6 +36,7 @@ class LayerHistoryTestV2 : public testing::Test { protected: static constexpr auto PRESENT_TIME_HISTORY_SIZE = LayerInfoV2::HISTORY_SIZE; static constexpr auto MAX_FREQUENT_LAYER_PERIOD_NS = LayerInfoV2::MAX_FREQUENT_LAYER_PERIOD_NS; + static constexpr auto FREQUENT_LAYER_WINDOW_SIZE = LayerInfoV2::FREQUENT_LAYER_WINDOW_SIZE; static constexpr float LO_FPS = 30.f; static constexpr auto LO_FPS_PERIOD = static_cast<nsecs_t>(1e9f / LO_FPS); @@ -451,5 +452,61 @@ TEST_F(LayerHistoryTestV2, multipleLayers) { EXPECT_EQ(0, frequentLayerCount(time)); } +TEST_F(LayerHistoryTestV2, inactiveLayers) { + auto layer = createLayer(); + + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(Layer::FrameRate())); + + nsecs_t time = systemTime(); + + // the very first updates makes the layer frequent + for (int i = 0; i < FREQUENT_LAYER_WINDOW_SIZE - 1; i++) { + history().record(layer.get(), time, time); + time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); + + EXPECT_EQ(1, layerCount()); + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + } + + // the next update with the MAX_FREQUENT_LAYER_PERIOD_NS will get us to infrequent + history().record(layer.get(), time, time); + time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); + + EXPECT_EQ(1, layerCount()); + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + // advance the time for the previous frame to be inactive + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + + // Now event if we post a quick few frame we should stay infrequent + for (int i = 0; i < FREQUENT_LAYER_WINDOW_SIZE - 1; i++) { + history().record(layer.get(), time, time); + time += HI_FPS_PERIOD; + + EXPECT_EQ(1, layerCount()); + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + } + + // More quick frames will get us to frequent again + history().record(layer.get(), time, time); + time += HI_FPS_PERIOD; + + EXPECT_EQ(1, layerCount()); + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); +} + } // namespace } // namespace android::scheduler diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index e7e7f66c95..4a179b6d0f 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -93,8 +93,8 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap) { auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); - const auto minRate = refreshRateConfigs->getMinRefreshRate(); - const auto performanceRate = refreshRateConfigs->getMaxRefreshRate(); + const auto& minRate = refreshRateConfigs->getMinRefreshRate(); + const auto& performanceRate = refreshRateConfigs->getMaxRefreshRate(); RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; ASSERT_EQ(expectedDefaultConfig, minRate); @@ -102,8 +102,8 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap) { 90}; ASSERT_EQ(expectedPerformanceConfig, performanceRate); - const auto minRateByPolicy = refreshRateConfigs->getMinRefreshRateByPolicy(); - const auto performanceRateByPolicy = refreshRateConfigs->getMaxRefreshRateByPolicy(); + const auto& minRateByPolicy = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto& performanceRateByPolicy = refreshRateConfigs->getMaxRefreshRateByPolicy(); ASSERT_EQ(minRateByPolicy, minRate); ASSERT_EQ(performanceRateByPolicy, performanceRate); } @@ -115,10 +115,10 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differe auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); - const auto minRate = refreshRateConfigs->getMinRefreshRateByPolicy(); - const auto performanceRate = refreshRateConfigs->getMaxRefreshRate(); - const auto minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy(); - const auto performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); + const auto& minRate = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto& performanceRate = refreshRateConfigs->getMaxRefreshRate(); + const auto& minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto& performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; ASSERT_EQ(expectedDefaultConfig, minRate); @@ -128,8 +128,8 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differe ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_90, 60, 90, nullptr), 0); refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); - const auto minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy(); - const auto performanceRate90 = refreshRateConfigs->getMaxRefreshRateByPolicy(); + const auto& minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto& performanceRate90 = refreshRateConfigs->getMaxRefreshRateByPolicy(); RefreshRate expectedPerformanceConfig = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_1, "90fps", 90}; @@ -145,8 +145,8 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_policyChange) { auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); - auto minRate = refreshRateConfigs->getMinRefreshRateByPolicy(); - auto performanceRate = refreshRateConfigs->getMaxRefreshRateByPolicy(); + auto& minRate = refreshRateConfigs->getMinRefreshRateByPolicy(); + auto& performanceRate = refreshRateConfigs->getMaxRefreshRateByPolicy(); RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; ASSERT_EQ(expectedDefaultConfig, minRate); @@ -156,8 +156,8 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_policyChange) { ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 60, 60, nullptr), 0); - auto minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy(); - auto performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); + auto& minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy(); + auto& performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); ASSERT_EQ(expectedDefaultConfig, minRate60); ASSERT_EQ(expectedDefaultConfig, performanceRate60); } @@ -169,19 +169,19 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getCurrentRefreshRate) { auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(configs, /*currentConfigId=*/HWC_CONFIG_ID_60); { - auto current = refreshRateConfigs->getCurrentRefreshRate(); + auto& current = refreshRateConfigs->getCurrentRefreshRate(); EXPECT_EQ(current.configId, HWC_CONFIG_ID_60); } refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); { - auto current = refreshRateConfigs->getCurrentRefreshRate(); + auto& current = refreshRateConfigs->getCurrentRefreshRate(); EXPECT_EQ(current.configId, HWC_CONFIG_ID_90); } ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_90, 90, 90, nullptr), 0); { - auto current = refreshRateConfigs->getCurrentRefreshRate(); + auto& current = refreshRateConfigs->getCurrentRefreshRate(); EXPECT_EQ(current.configId, HWC_CONFIG_ID_90); } } |