Merge "Use IServiceManager method to check app permission" into sc-dev
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index a3b7b13..6b5cf04 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -540,10 +540,16 @@
bool BufferStateLayer::setSidebandStream(const sp<NativeHandle>& sidebandStream) {
if (mDrawingState.sidebandStream == sidebandStream) return false;
+
+ if (mDrawingState.sidebandStream != nullptr && sidebandStream == nullptr) {
+ mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount();
+ } else if (sidebandStream != nullptr) {
+ mFlinger->mTunnelModeEnabledReporter->incrementTunnelModeCount();
+ }
+
mDrawingState.sidebandStream = sidebandStream;
mDrawingState.modified = true;
setTransactionFlags(eTransactionNeeded);
-
if (!mSidebandStreamChanged.exchange(true)) {
// mSidebandStreamChanged was false
mFlinger->signalLayerUpdate();
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp b/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp
index 8423a12..936dba3 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp
@@ -42,7 +42,13 @@
}
Flags<LayerStateField> LayerState::update(compositionengine::OutputLayer* layer) {
- ALOGE_IF(layer != mOutputLayer, "[%s] Expected mOutputLayer to never change", __func__);
+ ALOGE_IF(mOutputLayer != layer && layer->getLayerFE().getSequence() != mId.get(),
+ "[%s] Expected mOutputLayer ID to never change: %d, %d", __func__,
+ layer->getLayerFE().getSequence(), mId.get());
+
+ // It's possible for the OutputLayer pointer to change even when the layer is logically the
+ // same, i.e., the LayerFE is the same. An example use-case is screen rotation.
+ mOutputLayer = layer;
Flags<LayerStateField> differences;
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp
index be2510f..f077470 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp
@@ -113,15 +113,6 @@
}
}
- for (LayerId removedLayer : removedLayers) {
- if (const auto layerEntry = mPreviousLayers.find(removedLayer);
- layerEntry != mPreviousLayers.end()) {
- const auto& [id, state] = *layerEntry;
- ALOGV("Removed layer %s", state.getName().c_str());
- mPreviousLayers.erase(removedLayer);
- }
- }
-
mCurrentLayers.clear();
mCurrentLayers.reserve(currentLayerIds.size());
std::transform(currentLayerIds.cbegin(), currentLayerIds.cend(),
@@ -135,6 +126,7 @@
mFlattenedHash =
mFlattener.flattenLayers(mCurrentLayers, hash, std::chrono::steady_clock::now());
const bool layersWereFlattened = hash != mFlattenedHash;
+
ALOGV("[%s] Initial hash %zx flattened hash %zx", __func__, hash, mFlattenedHash);
if (mPredictorEnabled) {
@@ -148,6 +140,17 @@
ALOGV("[%s] No prediction found\n", __func__);
}
}
+
+ // Clean up the set of previous layers now that the view of the LayerStates in the flattener are
+ // up-to-date.
+ for (LayerId removedLayer : removedLayers) {
+ if (const auto layerEntry = mPreviousLayers.find(removedLayer);
+ layerEntry != mPreviousLayers.end()) {
+ const auto& [id, state] = *layerEntry;
+ ALOGV("Removed layer %s", state.getName().c_str());
+ mPreviousLayers.erase(removedLayer);
+ }
+ }
}
void Planner::reportFinalPlan(
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/LayerStateTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/LayerStateTest.cpp
index a09ce14..9ad3ab4 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/LayerStateTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/LayerStateTest.cpp
@@ -117,6 +117,22 @@
EXPECT_EQ(&mOutputLayer, mLayerState->getOutputLayer());
}
+TEST_F(LayerStateTest, updateOutputLayer) {
+ OutputLayerCompositionState outputLayerCompositionState;
+ LayerFECompositionState layerFECompositionState;
+ setupMocksForLayer(mOutputLayer, mLayerFE, outputLayerCompositionState,
+ layerFECompositionState);
+ mLayerState = std::make_unique<LayerState>(&mOutputLayer);
+ EXPECT_EQ(&mOutputLayer, mLayerState->getOutputLayer());
+
+ mock::OutputLayer newOutputLayer;
+ mock::LayerFE newLayerFE;
+ setupMocksForLayer(newOutputLayer, newLayerFE, outputLayerCompositionState,
+ layerFECompositionState);
+ mLayerState->update(&newOutputLayer);
+ EXPECT_EQ(&newOutputLayer, mLayerState->getOutputLayer());
+}
+
TEST_F(LayerStateTest, getId) {
OutputLayerCompositionState outputLayerCompositionState;
LayerFECompositionState layerFECompositionState;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 6c9905e..ad31b3f 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -70,6 +70,7 @@
#include "MonitoredProducer.h"
#include "SurfaceFlinger.h"
#include "TimeStats/TimeStats.h"
+#include "TunnelModeEnabledReporter.h"
#include "input/InputWindow.h"
#define DEBUG_RESIZE 0
@@ -172,6 +173,10 @@
mFrameTracker.logAndResetStats(mName);
mFlinger->onLayerDestroyed(this);
+
+ if (mDrawingState.sidebandStream != nullptr) {
+ mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount();
+ }
}
LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp<Client> client, std::string name,
@@ -700,11 +705,6 @@
mNeedsFiltering = getActiveTransform(s).needsBilinearFiltering();
}
- if (mDrawingState.inputInfoChanged) {
- flags |= eInputInfoChanged;
- mDrawingState.inputInfoChanged = false;
- }
-
commitTransaction(mDrawingState);
return flags;
@@ -777,6 +777,8 @@
mDrawingState.z = z;
mDrawingState.modified = true;
+ mFlinger->mSomeChildrenChanged = true;
+
// Discard all relative layering.
if (mDrawingState.zOrderRelativeOf != nullptr) {
sp<Layer> strongRelative = mDrawingState.zOrderRelativeOf.promote();
@@ -827,6 +829,8 @@
return false;
}
+ mFlinger->mSomeChildrenChanged = true;
+
mDrawingState.sequence++;
mDrawingState.modified = true;
mDrawingState.z = relativeZ;
@@ -1986,7 +1990,7 @@
mDrawingState.inputInfo = info;
mDrawingState.touchableRegionCrop = extractLayerFromBinder(info.touchableRegionCropHandle);
mDrawingState.modified = true;
- mDrawingState.inputInfoChanged = true;
+ mFlinger->mInputInfoChanged = true;
setTransactionFlags(eTransactionNeeded);
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 84d6d3f..ec9bb7c 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -186,7 +186,6 @@
float cornerRadius;
int backgroundBlurRadius;
- bool inputInfoChanged;
InputWindowInfo inputInfo;
wp<Layer> touchableRegionCrop;
@@ -997,7 +996,7 @@
// This layer can be a cursor on some displays.
bool mPotentialCursor{false};
- LayerVector mCurrentChildren{LayerVector::StateSet::Drawing};
+ LayerVector mCurrentChildren{LayerVector::StateSet::Current};
LayerVector mDrawingChildren{LayerVector::StateSet::Drawing};
wp<Layer> mCurrentParent;
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index 18a2891..6b2d745 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -140,6 +140,11 @@
outTransformMatrix);
}
+status_t MonitoredProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence,
+ Rect* outRect, uint32_t* outTransform) {
+ return mProducer->getLastQueuedBuffer(outBuffer, outFence, outRect, outTransform);
+}
+
void MonitoredProducer::getFrameTimestamps(FrameEventHistoryDelta* outDelta) {
mProducer->getFrameTimestamps(outDelta);
}
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index 788919b..3778277 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -64,6 +64,8 @@
virtual status_t setLegacyBufferDrop(bool drop) override;
virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
sp<Fence>* outFence, float outTransformMatrix[16]) override;
+ virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence,
+ Rect* outRect, uint32_t* outTransform) override;
virtual IBinder* onAsBinder();
virtual status_t setSharedBufferMode(bool sharedBufferMode) override;
virtual status_t setAutoRefresh(bool autoRefresh) override;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b99531b..f346465 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -342,6 +342,7 @@
mEventQueue(mFactory.createMessageQueue()),
mCompositionEngine(mFactory.createCompositionEngine()),
mHwcServiceName(base::GetProperty("debug.sf.hwc_service_name"s, "default"s)),
+ mTunnelModeEnabledReporter(new TunnelModeEnabledReporter()),
mInternalDisplayDensity(getDensityFromProperty("ro.sf.lcd_density", true)),
mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)) {
ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str());
@@ -2664,9 +2665,7 @@
sp<DisplayDevice> display = getFactory().createDisplayDevice(creationArgs);
- if (maxFrameBufferAcquiredBuffers >= 3) {
- nativeWindowSurface->preallocateBuffers();
- }
+ nativeWindowSurface->preallocateBuffers();
ColorMode defaultColorMode = ColorMode::NATIVE;
Dataspace defaultDataSpace = Dataspace::UNKNOWN;
@@ -2923,24 +2922,8 @@
processDisplayChangesLocked();
processDisplayHotplugEventsLocked();
}
-
- // Commit layer transactions. This needs to happen after display transactions are
- // committed because some geometry logic relies on display orientation.
- if ((transactionFlags & eTraversalNeeded) || mForceTraversal || displayTransactionNeeded) {
- mForceTraversal = false;
- mCurrentState.traverse([&](Layer* layer) {
- uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
- if (!trFlags && !displayTransactionNeeded) return;
-
- const uint32_t flags = layer->doTransaction(0);
- if (flags & Layer::eVisibleRegion)
- mVisibleRegionsDirty = true;
-
- if (flags & Layer::eInputInfoChanged) {
- mInputInfoChanged = true;
- }
- });
- }
+ mForceTraversal = false;
+ mForceTransactionDisplayChange = displayTransactionNeeded;
if (mSomeChildrenChanged) {
mVisibleRegionsDirty = true;
@@ -3169,7 +3152,6 @@
mRegionSamplingThread =
new RegionSamplingThread(*this, RegionSamplingThread::EnvironmentTimingTunables());
mFpsReporter = new FpsReporter(*mFrameTimeline, *this);
- mTunnelModeEnabledReporter = new TunnelModeEnabledReporter(*this);
// Dispatch a mode change request for the primary display on scheduler
// initialization, so that the EventThreads always contain a reference to a
// prior configuration.
@@ -3240,9 +3222,12 @@
// clear the "changed" flags in current state
mCurrentState.colorMatrixChanged = false;
- for (const auto& rootLayer : mDrawingState.layersSortedByZ) {
- rootLayer->commitChildList();
+ if (mVisibleRegionsDirty) {
+ for (const auto& rootLayer : mDrawingState.layersSortedByZ) {
+ rootLayer->commitChildList();
+ }
}
+
// TODO(b/163019109): See if this traversal is needed at all...
if (!mOffscreenLayers.empty()) {
mDrawingState.traverse([&](Layer* layer) {
@@ -3301,7 +3286,14 @@
// Display is now waiting on Layer 1's frame, which is behind layer 0's
// second frame. But layer 0's second frame could be waiting on display.
mDrawingState.traverse([&](Layer* layer) {
- if (layer->hasReadyFrame()) {
+ uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
+ if (trFlags || mForceTransactionDisplayChange) {
+ const uint32_t flags = layer->doTransaction(0);
+ if (flags & Layer::eVisibleRegion)
+ mVisibleRegionsDirty = true;
+ }
+
+ if (layer->hasReadyFrame()) {
frameQueued = true;
if (layer->shouldPresentNow(expectedPresentTime)) {
mLayersWithQueuedFrames.emplace(layer);
@@ -3309,10 +3301,11 @@
ATRACE_NAME("!layer->shouldPresentNow()");
layer->useEmptyDamage();
}
- } else {
+ } else {
layer->useEmptyDamage();
}
});
+ mForceTransactionDisplayChange = false;
// The client can continue submitting buffers for offscreen layers, but they will not
// be shown on screen. Therefore, we need to latch and release buffers of offscreen
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 81f569a..f33df86 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -364,6 +364,7 @@
// For unit tests
friend class TestableSurfaceFlinger;
friend class TransactionApplicationTest;
+ friend class TunnelModeEnabledReporterTest;
using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate;
using VsyncModulator = scheduler::VsyncModulator;
@@ -1234,6 +1235,7 @@
// TODO: Also move visibleRegions over to a boolean system.
bool mInputInfoChanged = false;
bool mSomeChildrenChanged;
+ bool mForceTransactionDisplayChange = false;
bool mGeometryInvalid = false;
bool mAnimCompositionPending = false;
diff --git a/services/surfaceflinger/TunnelModeEnabledReporter.cpp b/services/surfaceflinger/TunnelModeEnabledReporter.cpp
index 48e3216..4497caf 100644
--- a/services/surfaceflinger/TunnelModeEnabledReporter.cpp
+++ b/services/surfaceflinger/TunnelModeEnabledReporter.cpp
@@ -26,17 +26,10 @@
namespace android {
-TunnelModeEnabledReporter::TunnelModeEnabledReporter(SurfaceFlinger& flinger) : mFlinger(flinger) {}
+TunnelModeEnabledReporter::TunnelModeEnabledReporter() {}
void TunnelModeEnabledReporter::updateTunnelModeStatus() {
- bool tunnelModeEnabled = false;
- mFlinger.mCurrentState.traverse([&](Layer* layer) {
- auto& state = layer->getDrawingState();
- if (state.sidebandStream != nullptr) {
- tunnelModeEnabled = true;
- return;
- }
- });
+ bool tunnelModeEnabled = mTunnelModeCount > 0;
dispatchTunnelModeEnabled(tunnelModeEnabled);
}
diff --git a/services/surfaceflinger/TunnelModeEnabledReporter.h b/services/surfaceflinger/TunnelModeEnabledReporter.h
index d55507a..935502a 100644
--- a/services/surfaceflinger/TunnelModeEnabledReporter.h
+++ b/services/surfaceflinger/TunnelModeEnabledReporter.h
@@ -29,7 +29,7 @@
class TunnelModeEnabledReporter : public IBinder::DeathRecipient {
public:
- TunnelModeEnabledReporter(SurfaceFlinger& flinger);
+ TunnelModeEnabledReporter();
// Checks if there is a tunnel mode enabled state change and if so, dispatches the updated
// tunnel mode enabled/disabled state to the registered listeners
@@ -49,6 +49,9 @@
// Deregisters a TunnelModeEnabled listener
void removeListener(const sp<gui::ITunnelModeEnabledListener>& listener);
+ inline void incrementTunnelModeCount() { mTunnelModeCount++; }
+ inline void decrementTunnelModeCount() { mTunnelModeCount--; }
+
private:
mutable std::mutex mMutex;
struct WpHash {
@@ -57,10 +60,10 @@
}
};
- SurfaceFlinger& mFlinger;
std::unordered_map<wp<IBinder>, sp<gui::ITunnelModeEnabledListener>, WpHash> mListeners
GUARDED_BY(mMutex);
bool mTunnelModeEnabled GUARDED_BY(mMutex) = false;
+ uint32_t mTunnelModeCount = 0;
};
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp b/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp
index d7d7ea7..e4f7469 100644
--- a/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp
@@ -27,6 +27,7 @@
#include "TunnelModeEnabledReporter.h"
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/MockEventThread.h"
+#include "mock/MockMessageQueue.h"
namespace android {
@@ -71,15 +72,20 @@
sp<TestableTunnelModeEnabledListener> mTunnelModeEnabledListener =
new TestableTunnelModeEnabledListener();
sp<TunnelModeEnabledReporter> mTunnelModeEnabledReporter =
- new TunnelModeEnabledReporter(*(mFlinger.flinger()));
+ new TunnelModeEnabledReporter();
+
+ mock::MessageQueue* mMessageQueue = new mock::MessageQueue();
};
TunnelModeEnabledReporterTest::TunnelModeEnabledReporterTest() {
const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_test_info();
ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
+
+ mFlinger.mutableEventQueue().reset(mMessageQueue);
setupScheduler();
mFlinger.setupComposer(std::make_unique<Hwc2::mock::Composer>());
+ mFlinger.flinger()->mTunnelModeEnabledReporter = mTunnelModeEnabledReporter;
mTunnelModeEnabledReporter->dispatchTunnelModeEnabled(false);
}
@@ -156,16 +162,18 @@
sp<NativeHandle> stream =
NativeHandle::create(reinterpret_cast<native_handle_t*>(DEFAULT_SIDEBAND_STREAM),
false);
- mFlinger.setLayerSidebandStream(layer, stream);
+ layer->setSidebandStream(stream);
mFlinger.mutableCurrentState().layersSortedByZ.add(layer);
mTunnelModeEnabledReporter->updateTunnelModeStatus();
mTunnelModeEnabledReporter->addListener(mTunnelModeEnabledListener);
EXPECT_EQ(true, mTunnelModeEnabledListener->mTunnelModeEnabled);
mTunnelModeEnabledReporter->removeListener(mTunnelModeEnabledListener);
-
mFlinger.mutableCurrentState().layersSortedByZ.remove(layer);
+ layer = nullptr;
+
mTunnelModeEnabledReporter->updateTunnelModeStatus();
mTunnelModeEnabledReporter->addListener(mTunnelModeEnabledListener);
+
EXPECT_EQ(false, mTunnelModeEnabledListener->mTunnelModeEnabled);
}
@@ -178,7 +186,7 @@
sp<NativeHandle> stream =
NativeHandle::create(reinterpret_cast<native_handle_t*>(DEFAULT_SIDEBAND_STREAM),
false);
- mFlinger.setLayerSidebandStream(layerWithSidebandStream, stream);
+ layerWithSidebandStream->setSidebandStream(stream);
mFlinger.mutableCurrentState().layersSortedByZ.add(simpleLayer);
mFlinger.mutableCurrentState().layersSortedByZ.add(layerWithSidebandStream);
@@ -186,6 +194,7 @@
EXPECT_EQ(true, mTunnelModeEnabledListener->mTunnelModeEnabled);
mFlinger.mutableCurrentState().layersSortedByZ.remove(layerWithSidebandStream);
+ layerWithSidebandStream = nullptr;
mTunnelModeEnabledReporter->updateTunnelModeStatus();
EXPECT_EQ(false, mTunnelModeEnabledListener->mTunnelModeEnabled);
}
diff --git a/services/vibratorservice/VibratorHalWrapper.cpp b/services/vibratorservice/VibratorHalWrapper.cpp
index f15a963..a375808 100644
--- a/services/vibratorservice/VibratorHalWrapper.cpp
+++ b/services/vibratorservice/VibratorHalWrapper.cpp
@@ -135,6 +135,18 @@
if (mInfoCache.mSupportedBraking.isFailed()) {
mInfoCache.mSupportedBraking = getSupportedBrakingInternal();
}
+ if (mInfoCache.mPrimitiveDelayMax.isFailed()) {
+ mInfoCache.mPrimitiveDelayMax = getPrimitiveDelayMaxInternal();
+ }
+ if (mInfoCache.mPwlePrimitiveDurationMax.isFailed()) {
+ mInfoCache.mPwlePrimitiveDurationMax = getPrimitiveDurationMaxInternal();
+ }
+ if (mInfoCache.mCompositionSizeMax.isFailed()) {
+ mInfoCache.mCompositionSizeMax = getCompositionSizeMaxInternal();
+ }
+ if (mInfoCache.mPwleSizeMax.isFailed()) {
+ mInfoCache.mPwleSizeMax = getPwleSizeMaxInternal();
+ }
if (mInfoCache.mMinFrequency.isFailed()) {
mInfoCache.mMinFrequency = getMinFrequencyInternal();
}
@@ -209,6 +221,26 @@
return HalResult<std::vector<milliseconds>>::unsupported();
}
+HalResult<milliseconds> HalWrapper::getPrimitiveDelayMaxInternal() {
+ ALOGV("Skipped getPrimitiveDelayMaxInternal because it's not available in Vibrator HAL");
+ return HalResult<milliseconds>::unsupported();
+}
+
+HalResult<milliseconds> HalWrapper::getPrimitiveDurationMaxInternal() {
+ ALOGV("Skipped getPrimitiveDurationMaxInternal because it's not available in Vibrator HAL");
+ return HalResult<milliseconds>::unsupported();
+}
+
+HalResult<int32_t> HalWrapper::getCompositionSizeMaxInternal() {
+ ALOGV("Skipped getCompositionSizeMaxInternal because it's not available in Vibrator HAL");
+ return HalResult<int32_t>::unsupported();
+}
+
+HalResult<int32_t> HalWrapper::getPwleSizeMaxInternal() {
+ ALOGV("Skipped getPwleSizeMaxInternal because it's not available in Vibrator HAL");
+ return HalResult<int32_t>::unsupported();
+}
+
HalResult<float> HalWrapper::getMinFrequencyInternal() {
ALOGV("Skipped getMinFrequency because it's not available in Vibrator HAL");
return HalResult<float>::unsupported();
@@ -383,6 +415,30 @@
return HalResult<std::vector<milliseconds>>::ok(durations);
}
+HalResult<milliseconds> AidlHalWrapper::getPrimitiveDelayMaxInternal() {
+ int32_t delay = 0;
+ auto result = getHal()->getCompositionDelayMax(&delay);
+ return HalResult<milliseconds>::fromStatus(result, milliseconds(delay));
+}
+
+HalResult<milliseconds> AidlHalWrapper::getPrimitiveDurationMaxInternal() {
+ int32_t delay = 0;
+ auto result = getHal()->getPwlePrimitiveDurationMax(&delay);
+ return HalResult<milliseconds>::fromStatus(result, milliseconds(delay));
+}
+
+HalResult<int32_t> AidlHalWrapper::getCompositionSizeMaxInternal() {
+ int32_t size = 0;
+ auto result = getHal()->getCompositionSizeMax(&size);
+ return HalResult<int32_t>::fromStatus(result, size);
+}
+
+HalResult<int32_t> AidlHalWrapper::getPwleSizeMaxInternal() {
+ int32_t size = 0;
+ auto result = getHal()->getPwleCompositionSizeMax(&size);
+ return HalResult<int32_t>::fromStatus(result, size);
+}
+
HalResult<float> AidlHalWrapper::getMinFrequencyInternal() {
float minFrequency = 0;
auto result = getHal()->getFrequencyMinimum(&minFrequency);
diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
index 87bc34e..68d6647 100644
--- a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
+++ b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h
@@ -182,6 +182,10 @@
const HalResult<std::vector<hardware::vibrator::Braking>> supportedBraking;
const HalResult<std::vector<hardware::vibrator::CompositePrimitive>> supportedPrimitives;
const HalResult<std::vector<std::chrono::milliseconds>> primitiveDurations;
+ const HalResult<std::chrono::milliseconds> primitiveDelayMax;
+ const HalResult<std::chrono::milliseconds> pwlePrimitiveDurationMax;
+ const HalResult<int32_t> compositionSizeMax;
+ const HalResult<int32_t> pwleSizeMax;
const HalResult<float> minFrequency;
const HalResult<float> resonantFrequency;
const HalResult<float> frequencyResolution;
@@ -194,6 +198,10 @@
supportedBraking.checkAndLogFailure("getSupportedBraking") ||
supportedPrimitives.checkAndLogFailure("getSupportedPrimitives") ||
primitiveDurations.checkAndLogFailure("getPrimitiveDuration") ||
+ primitiveDelayMax.checkAndLogFailure("getPrimitiveDelayMax") ||
+ pwlePrimitiveDurationMax.checkAndLogFailure("getPwlePrimitiveDurationMax") ||
+ compositionSizeMax.checkAndLogFailure("getCompositionSizeMax") ||
+ pwleSizeMax.checkAndLogFailure("getPwleSizeMax") ||
minFrequency.checkAndLogFailure("getMinFrequency") ||
resonantFrequency.checkAndLogFailure("getResonantFrequency") ||
frequencyResolution.checkAndLogFailure("getFrequencyResolution") ||
@@ -205,9 +213,19 @@
class InfoCache {
public:
Info get() {
- return {mCapabilities, mSupportedEffects, mSupportedBraking,
- mSupportedPrimitives, mPrimitiveDurations, mMinFrequency,
- mResonantFrequency, mFrequencyResolution, mQFactor,
+ return {mCapabilities,
+ mSupportedEffects,
+ mSupportedBraking,
+ mSupportedPrimitives,
+ mPrimitiveDurations,
+ mPrimitiveDelayMax,
+ mPwlePrimitiveDurationMax,
+ mCompositionSizeMax,
+ mPwleSizeMax,
+ mMinFrequency,
+ mResonantFrequency,
+ mFrequencyResolution,
+ mQFactor,
mMaxAmplitudes};
}
@@ -222,6 +240,12 @@
HalResult<std::vector<hardware::vibrator::CompositePrimitive>>::failed(MSG);
HalResult<std::vector<std::chrono::milliseconds>> mPrimitiveDurations =
HalResult<std::vector<std::chrono::milliseconds>>::failed(MSG);
+ HalResult<std::chrono::milliseconds> mPrimitiveDelayMax =
+ HalResult<std::chrono::milliseconds>::failed(MSG);
+ HalResult<std::chrono::milliseconds> mPwlePrimitiveDurationMax =
+ HalResult<std::chrono::milliseconds>::failed(MSG);
+ HalResult<int32_t> mCompositionSizeMax = HalResult<int>::failed(MSG);
+ HalResult<int32_t> mPwleSizeMax = HalResult<int>::failed(MSG);
HalResult<float> mMinFrequency = HalResult<float>::failed(MSG);
HalResult<float> mResonantFrequency = HalResult<float>::failed(MSG);
HalResult<float> mFrequencyResolution = HalResult<float>::failed(MSG);
@@ -285,6 +309,10 @@
getSupportedPrimitivesInternal();
virtual HalResult<std::vector<std::chrono::milliseconds>> getPrimitiveDurationsInternal(
const std::vector<hardware::vibrator::CompositePrimitive>& supportedPrimitives);
+ virtual HalResult<std::chrono::milliseconds> getPrimitiveDelayMaxInternal();
+ virtual HalResult<std::chrono::milliseconds> getPrimitiveDurationMaxInternal();
+ virtual HalResult<int32_t> getCompositionSizeMaxInternal();
+ virtual HalResult<int32_t> getPwleSizeMaxInternal();
virtual HalResult<float> getMinFrequencyInternal();
virtual HalResult<float> getResonantFrequencyInternal();
virtual HalResult<float> getFrequencyResolutionInternal();
@@ -347,6 +375,10 @@
HalResult<std::vector<std::chrono::milliseconds>> getPrimitiveDurationsInternal(
const std::vector<hardware::vibrator::CompositePrimitive>& supportedPrimitives)
override final;
+ HalResult<std::chrono::milliseconds> getPrimitiveDelayMaxInternal() override final;
+ HalResult<std::chrono::milliseconds> getPrimitiveDurationMaxInternal() override final;
+ HalResult<int32_t> getCompositionSizeMaxInternal() override final;
+ HalResult<int32_t> getPwleSizeMaxInternal() override final;
HalResult<float> getMinFrequencyInternal() override final;
HalResult<float> getResonantFrequencyInternal() override final;
HalResult<float> getFrequencyResolutionInternal() override final;
diff --git a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
index 7813303..03c9e77 100644
--- a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
+++ b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp
@@ -301,6 +301,10 @@
constexpr float F0 = 123.f;
constexpr float F_RESOLUTION = 0.5f;
constexpr float Q_FACTOR = 123.f;
+ constexpr int32_t COMPOSITION_SIZE_MAX = 10;
+ constexpr int32_t PWLE_SIZE_MAX = 20;
+ constexpr int32_t PRIMITIVE_DELAY_MAX = 100;
+ constexpr int32_t PWLE_DURATION_MAX = 200;
std::vector<Effect> supportedEffects = {Effect::CLICK, Effect::TICK};
std::vector<CompositePrimitive> supportedPrimitives = {CompositePrimitive::CLICK};
std::vector<Braking> supportedBraking = {Braking::CLAB};
@@ -331,6 +335,22 @@
EXPECT_CALL(*mMockHal.get(), getPrimitiveDuration(Eq(CompositePrimitive::CLICK), _))
.Times(Exactly(1))
.WillRepeatedly(DoAll(SetArgPointee<1>(10), Return(Status())));
+ EXPECT_CALL(*mMockHal.get(), getCompositionSizeMax(_))
+ .Times(Exactly(2))
+ .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(COMPOSITION_SIZE_MAX), Return(Status())));
+ EXPECT_CALL(*mMockHal.get(), getCompositionDelayMax(_))
+ .Times(Exactly(2))
+ .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(PRIMITIVE_DELAY_MAX), Return(Status())));
+ EXPECT_CALL(*mMockHal.get(), getPwlePrimitiveDurationMax(_))
+ .Times(Exactly(2))
+ .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(PWLE_DURATION_MAX), Return(Status())));
+ EXPECT_CALL(*mMockHal.get(), getPwleCompositionSizeMax(_))
+ .Times(Exactly(2))
+ .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(PWLE_SIZE_MAX), Return(Status())));
EXPECT_CALL(*mMockHal.get(), getFrequencyMinimum(_))
.Times(Exactly(2))
.WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
@@ -358,6 +378,10 @@
ASSERT_TRUE(failed.supportedBraking.isFailed());
ASSERT_TRUE(failed.supportedPrimitives.isFailed());
ASSERT_TRUE(failed.primitiveDurations.isFailed());
+ ASSERT_TRUE(failed.primitiveDelayMax.isFailed());
+ ASSERT_TRUE(failed.pwlePrimitiveDurationMax.isFailed());
+ ASSERT_TRUE(failed.compositionSizeMax.isFailed());
+ ASSERT_TRUE(failed.pwleSizeMax.isFailed());
ASSERT_TRUE(failed.minFrequency.isFailed());
ASSERT_TRUE(failed.resonantFrequency.isFailed());
ASSERT_TRUE(failed.frequencyResolution.isFailed());
@@ -370,6 +394,11 @@
ASSERT_EQ(supportedBraking, successful.supportedBraking.value());
ASSERT_EQ(supportedPrimitives, successful.supportedPrimitives.value());
ASSERT_EQ(primitiveDurations, successful.primitiveDurations.value());
+ ASSERT_EQ(std::chrono::milliseconds(PRIMITIVE_DELAY_MAX), successful.primitiveDelayMax.value());
+ ASSERT_EQ(std::chrono::milliseconds(PWLE_DURATION_MAX),
+ successful.pwlePrimitiveDurationMax.value());
+ ASSERT_EQ(COMPOSITION_SIZE_MAX, successful.compositionSizeMax.value());
+ ASSERT_EQ(PWLE_SIZE_MAX, successful.pwleSizeMax.value());
ASSERT_EQ(F_MIN, successful.minFrequency.value());
ASSERT_EQ(F0, successful.resonantFrequency.value());
ASSERT_EQ(F_RESOLUTION, successful.frequencyResolution.value());
@@ -380,6 +409,10 @@
TEST_F(VibratorHalWrapperAidlTest, TestGetInfoCachesResult) {
constexpr float F_MIN = 100.f;
constexpr float F0 = 123.f;
+ constexpr int32_t COMPOSITION_SIZE_MAX = 10;
+ constexpr int32_t PWLE_SIZE_MAX = 20;
+ constexpr int32_t PRIMITIVE_DELAY_MAX = 100;
+ constexpr int32_t PWLE_DURATION_MAX = 200;
std::vector<Effect> supportedEffects = {Effect::CLICK, Effect::TICK};
EXPECT_CALL(*mMockHal.get(), getCapabilities(_))
@@ -395,6 +428,18 @@
EXPECT_CALL(*mMockHal.get(), getSupportedPrimitives(_))
.Times(Exactly(1))
.WillRepeatedly(Return(Status::fromStatusT(UNKNOWN_TRANSACTION)));
+ EXPECT_CALL(*mMockHal.get(), getCompositionSizeMax(_))
+ .Times(Exactly(1))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(COMPOSITION_SIZE_MAX), Return(Status())));
+ EXPECT_CALL(*mMockHal.get(), getCompositionDelayMax(_))
+ .Times(Exactly(1))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(PRIMITIVE_DELAY_MAX), Return(Status())));
+ EXPECT_CALL(*mMockHal.get(), getPwlePrimitiveDurationMax(_))
+ .Times(Exactly(1))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(PWLE_DURATION_MAX), Return(Status())));
+ EXPECT_CALL(*mMockHal.get(), getPwleCompositionSizeMax(_))
+ .Times(Exactly(1))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(PWLE_SIZE_MAX), Return(Status())));
EXPECT_CALL(*mMockHal.get(), getFrequencyMinimum(_))
.Times(Exactly(1))
.WillRepeatedly(DoAll(SetArgPointee<0>(F_MIN), Return(Status())));
@@ -426,6 +471,10 @@
ASSERT_TRUE(info.supportedBraking.isUnsupported());
ASSERT_TRUE(info.supportedPrimitives.isUnsupported());
ASSERT_TRUE(info.primitiveDurations.isUnsupported());
+ ASSERT_EQ(std::chrono::milliseconds(PRIMITIVE_DELAY_MAX), info.primitiveDelayMax.value());
+ ASSERT_EQ(std::chrono::milliseconds(PWLE_DURATION_MAX), info.pwlePrimitiveDurationMax.value());
+ ASSERT_EQ(COMPOSITION_SIZE_MAX, info.compositionSizeMax.value());
+ ASSERT_EQ(PWLE_SIZE_MAX, info.pwleSizeMax.value());
ASSERT_EQ(F_MIN, info.minFrequency.value());
ASSERT_EQ(F0, info.resonantFrequency.value());
ASSERT_TRUE(info.frequencyResolution.isUnsupported());
diff --git a/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp b/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp
index 96b2582..0c27fc7 100644
--- a/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp
+++ b/services/vibratorservice/test/VibratorHalWrapperHidlV1_0Test.cpp
@@ -206,6 +206,10 @@
ASSERT_TRUE(info.supportedBraking.isUnsupported());
ASSERT_TRUE(info.supportedPrimitives.isUnsupported());
ASSERT_TRUE(info.primitiveDurations.isUnsupported());
+ ASSERT_TRUE(info.primitiveDelayMax.isUnsupported());
+ ASSERT_TRUE(info.pwlePrimitiveDurationMax.isUnsupported());
+ ASSERT_TRUE(info.compositionSizeMax.isUnsupported());
+ ASSERT_TRUE(info.pwleSizeMax.isUnsupported());
ASSERT_TRUE(info.minFrequency.isUnsupported());
ASSERT_TRUE(info.resonantFrequency.isUnsupported());
ASSERT_TRUE(info.frequencyResolution.isUnsupported());
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 8d6681c..2715587 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -537,6 +537,30 @@
}
}
+int get_min_buffer_count(ANativeWindow* window,
+ uint32_t* out_min_buffer_count) {
+ constexpr int kExtraBuffers = 2;
+
+ int err;
+ int min_undequeued_buffers;
+ err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+ &min_undequeued_buffers);
+ if (err != android::OK || min_undequeued_buffers < 0) {
+ ALOGE(
+ "NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d) "
+ "value=%d",
+ strerror(-err), err, min_undequeued_buffers);
+ if (err == android::OK) {
+ err = android::UNKNOWN_ERROR;
+ }
+ return err;
+ }
+
+ *out_min_buffer_count =
+ static_cast<uint32_t>(min_undequeued_buffers + kExtraBuffers);
+ return android::OK;
+}
+
} // anonymous namespace
VKAPI_ATTR
@@ -848,15 +872,13 @@
int err;
int query_value;
+ uint32_t min_buffer_count;
ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
- err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &query_value);
- if (err != android::OK || query_value < 0) {
- ALOGE("NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS query failed: %s (%d) value=%d",
- strerror(-err), err, query_value);
+ err = get_min_buffer_count(window, &min_buffer_count);
+ if (err != android::OK) {
return VK_ERROR_SURFACE_LOST_KHR;
}
- uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &query_value);
if (err != android::OK || query_value < 0) {
@@ -867,7 +889,7 @@
uint32_t max_buffer_count = static_cast<uint32_t>(query_value);
std::vector<VkPresentModeKHR> present_modes;
- if (min_undequeued_buffers + 1 < max_buffer_count)
+ if (min_buffer_count < max_buffer_count)
present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR);
present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR);
@@ -1188,19 +1210,14 @@
}
}
- int query_value;
- err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
- &query_value);
- if (err != android::OK || query_value < 0) {
- ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err,
- query_value);
+ uint32_t min_buffer_count;
+ err = get_min_buffer_count(window, &min_buffer_count);
+ if (err != android::OK) {
return VK_ERROR_SURFACE_LOST_KHR;
}
- uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
+
uint32_t num_images =
- (swap_interval ? create_info->minImageCount
- : std::max(3u, create_info->minImageCount)) -
- 1 + min_undequeued_buffers;
+ std::max(min_buffer_count, create_info->minImageCount);
// Lower layer insists that we have at least two buffers. This is wasteful
// and we'd like to relax it in the shared case, but not all the pieces are