Merge "FocusRequest token can be nullable" into tm-dev
diff --git a/data/etc/android.hardware.telephony.euicc.mep.xml b/data/etc/android.hardware.telephony.euicc.mep.xml
new file mode 100644
index 0000000..f958e4b
--- /dev/null
+++ b/data/etc/android.hardware.telephony.euicc.mep.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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 an eUICC supporting MEP(Multiple enabled profiles) -->
+<permissions>
+ <feature name="android.hardware.telephony.euicc" />
+ <feature name="android.hardware.telephony.euicc.mep" />
+</permissions>
\ No newline at end of file
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs
index 1d7de98..dbfb1c2 100644
--- a/libs/binder/rust/src/lib.rs
+++ b/libs/binder/rust/src/lib.rs
@@ -114,8 +114,8 @@
};
pub use parcel::{ParcelFileDescriptor, Parcelable, ParcelableHolder};
pub use proxy::{
- get_interface, get_service, wait_for_interface, wait_for_service, DeathRecipient, SpIBinder,
- WpIBinder,
+ get_declared_instances, get_interface, get_service, is_declared, wait_for_interface,
+ wait_for_service, DeathRecipient, SpIBinder, WpIBinder,
};
pub use state::{ProcessState, ThreadState};
diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs
index 12bfde7..e3e4730 100644
--- a/libs/binder/rust/src/proxy.rs
+++ b/libs/binder/rust/src/proxy.rs
@@ -28,9 +28,10 @@
use std::cmp::Ordering;
use std::convert::TryInto;
-use std::ffi::{c_void, CString};
+use std::ffi::{c_void, CStr, CString};
use std::fmt;
use std::mem;
+use std::os::raw::c_char;
use std::os::unix::io::AsRawFd;
use std::ptr;
use std::sync::Arc;
@@ -778,6 +779,61 @@
}
}
+/// Check if a service is declared (e.g. in a VINTF manifest)
+pub fn is_declared(interface: &str) -> Result<bool> {
+ let interface = CString::new(interface).or(Err(StatusCode::UNEXPECTED_NULL))?;
+
+ unsafe {
+ // Safety: `interface` is a valid null-terminated C-style string and is
+ // only borrowed for the lifetime of the call. The `interface` local
+ // outlives this call as it lives for the function scope.
+ Ok(sys::AServiceManager_isDeclared(interface.as_ptr()))
+ }
+}
+
+/// Retrieve all declared instances for a particular interface
+///
+/// For instance, if 'android.foo.IFoo/foo' is declared, and 'android.foo.IFoo'
+/// is passed here, then ["foo"] would be returned.
+pub fn get_declared_instances(interface: &str) -> Result<Vec<String>> {
+ unsafe extern "C" fn callback(instance: *const c_char, opaque: *mut c_void) {
+ // Safety: opaque was a mutable pointer created below from a Vec of
+ // CString, and outlives this callback. The null handling here is just
+ // to avoid the possibility of unwinding across C code if this crate is
+ // ever compiled with panic=unwind.
+ if let Some(instances) = opaque.cast::<Vec<CString>>().as_mut() {
+ // Safety: instance is a valid null-terminated C string with a
+ // lifetime at least as long as this function, and we immediately
+ // copy it into an owned CString.
+ instances.push(CStr::from_ptr(instance).to_owned());
+ } else {
+ eprintln!("Opaque pointer was null in get_declared_instances callback!");
+ }
+ }
+
+ let interface = CString::new(interface).or(Err(StatusCode::UNEXPECTED_NULL))?;
+ let mut instances: Vec<CString> = vec![];
+ unsafe {
+ // Safety: `interface` and `instances` are borrowed for the length of
+ // this call and both outlive the call. `interface` is guaranteed to be
+ // a valid null-terminated C-style string.
+ sys::AServiceManager_forEachDeclaredInstance(
+ interface.as_ptr(),
+ &mut instances as *mut _ as *mut c_void,
+ Some(callback),
+ );
+ }
+
+ instances
+ .into_iter()
+ .map(CString::into_string)
+ .collect::<std::result::Result<Vec<String>, _>>()
+ .map_err(|e| {
+ eprintln!("An interface instance name was not a valid UTF-8 string: {}", e);
+ StatusCode::BAD_VALUE
+ })
+}
+
/// # Safety
///
/// `SpIBinder` guarantees that `binder` always contains a valid pointer to an
diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs
index 50daf1c..7c5afde 100644
--- a/libs/binder/rust/tests/integration.rs
+++ b/libs/binder/rust/tests/integration.rs
@@ -484,6 +484,21 @@
}
#[test]
+ fn get_declared_instances() {
+ // At the time of writing this test, there is no good VINTF interface
+ // guaranteed to be on all devices. Cuttlefish has light, so this will
+ // generally test things.
+ let has_lights = binder::is_declared("android.hardware.light.ILights/default")
+ .expect("Could not check for declared interface");
+
+ let instances = binder::get_declared_instances("android.hardware.light.ILights")
+ .expect("Could not get declared instances");
+
+ let expected_defaults = if has_lights { 1 } else { 0 };
+ assert_eq!(expected_defaults, instances.iter().filter(|i| i.as_str() == "default").count());
+ }
+
+ #[test]
fn trivial_client() {
let service_name = "trivial_client_test";
let _process = ScopedServiceProcess::new(service_name);
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
index ebe112b..c7984bd 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
@@ -78,7 +78,7 @@
virtual void applyChangedTypesToLayers(const ChangedTypes&);
virtual void applyDisplayRequests(const DisplayRequests&);
virtual void applyLayerRequestsToLayers(const LayerRequests&);
- virtual void applyClientTargetRequests(const ClientTargetProperty&, float whitePointNits);
+ virtual void applyClientTargetRequests(const ClientTargetProperty&, float brightness);
// Internal
virtual void setConfiguration(const compositionengine::DisplayCreationArgs&);
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DumpHelpers.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DumpHelpers.h
index 7521324..196af70 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DumpHelpers.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DumpHelpers.h
@@ -17,6 +17,7 @@
#pragma once
#include <cstdint>
+#include <optional>
#include <string>
#include <type_traits>
@@ -63,4 +64,13 @@
void dumpVal(std::string& out, const char* name, const mat4&);
void dumpVal(std::string& out, const char* name, const StretchEffect&);
+template <typename T>
+void dumpVal(std::string& out, const char* name, std::optional<T> value) {
+ if (value.has_value()) {
+ return dumpVal(out, name, *value);
+ } else {
+ return dumpVal(out, name, "nullopt");
+ }
+}
+
} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
index cc7c257..66dd825 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
@@ -130,8 +130,8 @@
// SDR white point
float sdrWhitePointNits{-1.f};
- // White point of the client target
- float clientTargetWhitePointNits{-1.f};
+ // Brightness of the client target, normalized to display brightness
+ float clientTargetBrightness{1.f};
// Display brightness that will take effect this frame.
// This is slightly distinct from nits, in that nits cannot be passed to hw composer.
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index a3188f3..6390025 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -266,8 +266,7 @@
applyChangedTypesToLayers(changes->changedTypes);
applyDisplayRequests(changes->displayRequests);
applyLayerRequestsToLayers(changes->layerRequests);
- applyClientTargetRequests(changes->clientTargetProperty,
- changes->clientTargetWhitePointNits);
+ applyClientTargetRequests(changes->clientTargetProperty, changes->clientTargetBrightness);
}
// Determine what type of composition we are doing from the final state
@@ -343,13 +342,13 @@
}
void Display::applyClientTargetRequests(const ClientTargetProperty& clientTargetProperty,
- float whitePointNits) {
+ float brightness) {
if (clientTargetProperty.dataspace == ui::Dataspace::UNKNOWN) {
return;
}
editState().dataspace = clientTargetProperty.dataspace;
- editState().clientTargetWhitePointNits = whitePointNits;
+ editState().clientTargetBrightness = brightness;
getRenderSurface()->setBufferDataspace(clientTargetProperty.dataspace);
getRenderSurface()->setBufferPixelFormat(clientTargetProperty.pixelFormat);
}
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index e036252..ff332eb 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -1076,7 +1076,8 @@
: mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
clientCompositionDisplay.maxLuminance =
mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance();
- clientCompositionDisplay.targetLuminanceNits = outputState.clientTargetWhitePointNits;
+ clientCompositionDisplay.targetLuminanceNits =
+ outputState.clientTargetBrightness * outputState.displayBrightnessNits;
// Compute the global color transform matrix.
clientCompositionDisplay.colorTransform = outputState.colorTransformMatrix;
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp
index acc9216..482250a 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp
@@ -52,6 +52,10 @@
dumpVal(out, "dataspace", toString(dataspace), dataspace);
dumpVal(out, "colorTransformMatrix", colorTransformMatrix);
dumpVal(out, "target dataspace", toString(targetDataspace), targetDataspace);
+ dumpVal(out, "displayBrightnessNits", displayBrightnessNits);
+ dumpVal(out, "sdrWhitePointNits", sdrWhitePointNits);
+ dumpVal(out, "clientTargetBrightness", clientTargetBrightness);
+ dumpVal(out, "displayBrightness", displayBrightness);
out.append("\n");
}
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp
index cfa740e..6749427 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp
@@ -67,6 +67,8 @@
dumpVal(out, "sourceCrop", sourceCrop);
dumpVal(out, "bufferTransform", toString(bufferTransform), bufferTransform);
dumpVal(out, "dataspace", toString(dataspace), dataspace);
+ dumpVal(out, "whitePointNits", whitePointNits);
+ dumpVal(out, "dimmingRatio", dimmingRatio);
dumpVal(out, "override buffer", overrideInfo.buffer.get());
dumpVal(out, "override acquire fence", overrideInfo.acquireFence.get());
dumpVal(out, "override display frame", overrideInfo.displayFrame);
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index 44d34a3..cd03235 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -839,7 +839,7 @@
auto& state = mDisplay->getState();
EXPECT_EQ(clientTargetProperty.dataspace, state.dataspace);
- EXPECT_EQ(kWhitePointNits, state.clientTargetWhitePointNits);
+ EXPECT_EQ(kWhitePointNits, state.clientTargetBrightness);
}
/*
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index cab4b8d..c2521b2 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -3067,7 +3067,7 @@
mOutput.mState.usesDeviceComposition = false;
mOutput.mState.reusedClientComposition = false;
mOutput.mState.flipClientTarget = false;
- mOutput.mState.clientTargetWhitePointNits = kClientTargetLuminanceNits;
+ mOutput.mState.clientTargetBrightness = kClientTargetBrightness;
EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
@@ -3103,8 +3103,9 @@
static constexpr float kDefaultAvgLuminance = 0.7f;
static constexpr float kDefaultMinLuminance = 0.1f;
static constexpr float kUnknownLuminance = -1.f;
- static constexpr float kDisplayLuminance = 80.f;
+ static constexpr float kDisplayLuminance = 400.f;
static constexpr float kClientTargetLuminanceNits = 200.f;
+ static constexpr float kClientTargetBrightness = 0.5f;
static const Rect kDefaultOutputFrame;
static const Rect kDefaultOutputViewport;
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
index 8d67954..80e2d99 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
@@ -20,6 +20,7 @@
#include "AidlComposerHal.h"
+#include <android-base/file.h>
#include <android/binder_ibinder_platform.h>
#include <android/binder_manager.h>
#include <log/log.h>
@@ -115,7 +116,7 @@
AidlPerFrameMetadataBlob translate(IComposerClient::PerFrameMetadataBlob x) {
AidlPerFrameMetadataBlob blob;
blob.key = translate<AidlPerFrameMetadataKey>(x.key),
- std::copy(blob.blob.begin(), blob.blob.end(), x.blob.begin());
+ std::copy(x.blob.begin(), x.blob.end(), std::inserter(blob.blob, blob.blob.end()));
return blob;
}
@@ -262,13 +263,27 @@
}
std::string AidlComposer::dumpDebugInfo() {
- std::string info;
- const auto status = mAidlComposer->dumpDebugInfo(&info);
- if (!status.isOk()) {
- ALOGE("dumpDebugInfo failed %s", status.getDescription().c_str());
+ int pipefds[2];
+ int result = pipe(pipefds);
+ if (result < 0) {
+ ALOGE("dumpDebugInfo: pipe failed: %s", strerror(errno));
return {};
}
- return info;
+
+ std::string str;
+ const auto status = mAidlComposer->dump(pipefds[1], /*args*/ nullptr, /*numArgs*/ 0);
+ // Close the write-end of the pipe to make sure that when reading from the
+ // read-end we will get eof instead of blocking forever
+ close(pipefds[1]);
+
+ if (status == STATUS_OK) {
+ base::ReadFdToString(pipefds[0], &str);
+ } else {
+ ALOGE("dumpDebugInfo: dump failed: %d", status);
+ }
+
+ close(pipefds[0]);
+ return str;
}
void AidlComposer::registerCallback(HWC2::ComposerCallback& callback) {
@@ -1054,11 +1069,11 @@
Error AidlComposer::getClientTargetProperty(
Display display, IComposerClient::ClientTargetProperty* outClientTargetProperty,
- float* whitePointNits) {
+ float* outBrightness) {
const auto property = mReader.takeClientTargetProperty(translate<int64_t>(display));
*outClientTargetProperty =
translate<IComposerClient::ClientTargetProperty>(property.clientTargetProperty);
- *whitePointNits = property.whitePointNits;
+ *outBrightness = property.brightness;
return Error::NONE;
}
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
index 724c6c9..80ca8da 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
@@ -209,7 +209,7 @@
std::vector<IComposerClient::LayerGenericMetadataKey>* outKeys) override;
Error getClientTargetProperty(Display display,
IComposerClient::ClientTargetProperty* outClientTargetProperty,
- float* outClientTargetWhitePointNits) override;
+ float* outBrightness) override;
// AIDL Composer HAL
Error setLayerBrightness(Display display, Layer layer, float brightness) override;
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 06aaa11..23886d4 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -261,7 +261,7 @@
virtual Error getClientTargetProperty(
Display display, IComposerClient::ClientTargetProperty* outClientTargetProperty,
- float* outWhitePointNits) = 0;
+ float* outBrightness) = 0;
// AIDL Composer
virtual Error setLayerBrightness(Display display, Layer layer, float brightness) = 0;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 6a3162e..ed6e4b0 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -479,13 +479,12 @@
RETURN_IF_HWC_ERROR_FOR("getRequests", error, displayId, BAD_INDEX);
DeviceRequestedChanges::ClientTargetProperty clientTargetProperty;
- float clientTargetWhitePointNits;
- error = hwcDisplay->getClientTargetProperty(&clientTargetProperty, &clientTargetWhitePointNits);
+ float brightness = 1.f;
+ error = hwcDisplay->getClientTargetProperty(&clientTargetProperty, &brightness);
outChanges->emplace(DeviceRequestedChanges{std::move(changedTypes), std::move(displayRequests),
std::move(layerRequests),
- std::move(clientTargetProperty),
- clientTargetWhitePointNits});
+ std::move(clientTargetProperty), brightness});
error = hwcDisplay->acceptChanges();
RETURN_IF_HWC_ERROR_FOR("acceptChanges", error, displayId, BAD_INDEX);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 916c4b7..5b2e265 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -86,7 +86,7 @@
DisplayRequests displayRequests;
LayerRequests layerRequests;
ClientTargetProperty clientTargetProperty;
- float clientTargetWhitePointNits;
+ float clientTargetBrightness;
};
struct HWCDisplayMode {
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
index 95d7b58..f735bba 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
@@ -1297,9 +1297,9 @@
Error HidlComposer::getClientTargetProperty(
Display display, IComposerClient::ClientTargetProperty* outClientTargetProperty,
- float* outWhitePointNits) {
+ float* outBrightness) {
mReader.takeClientTargetProperty(display, outClientTargetProperty);
- *outWhitePointNits = -1.f;
+ *outBrightness = 1.f;
return Error::NONE;
}
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
index 71ae8b4..c2b60cb 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
@@ -318,7 +318,7 @@
std::vector<IComposerClient::LayerGenericMetadataKey>* outKeys) override;
Error getClientTargetProperty(Display display,
IComposerClient::ClientTargetProperty* outClientTargetProperty,
- float* outWhitePointNits) override;
+ float* outBrightness) override;
// AIDL Composer HAL
Error setLayerBrightness(Display display, Layer layer, float brightness) override;
diff --git a/services/surfaceflinger/FlagManager.cpp b/services/surfaceflinger/FlagManager.cpp
index e09a192..bd3cf74 100644
--- a/services/surfaceflinger/FlagManager.cpp
+++ b/services/surfaceflinger/FlagManager.cpp
@@ -101,7 +101,6 @@
}
bool FlagManager::use_skia_tracing() const {
- ALOGD("use_skia_tracing ?");
std::optional<bool> sysPropVal =
doParse<bool>(base::GetProperty(PROPERTY_SKIA_ATRACE_ENABLED, "").c_str());
return getValue("SkiaTracingFeature__use_skia_tracing", sysPropVal, false);
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index eeeaac1..15e30b3 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -202,24 +202,24 @@
}
if (layer.vote == LayerVoteType::ExplicitExact) {
- const int divider = getFrameRateDivider(refreshRate.getFps(), layer.desiredRefreshRate);
+ const int divisor = getFrameRateDivisor(refreshRate.getFps(), layer.desiredRefreshRate);
if (mSupportsFrameRateOverrideByContent) {
// Since we support frame rate override, allow refresh rates which are
// multiples of the layer's request, as those apps would be throttled
// down to run at the desired refresh rate.
- return divider > 0;
+ return divisor > 0;
}
- return divider == 1;
+ return divisor == 1;
}
- // If the layer frame rate is a divider of the refresh rate it should score
+ // If the layer frame rate is a divisor of the refresh rate it should score
// the highest score.
- if (getFrameRateDivider(refreshRate.getFps(), layer.desiredRefreshRate) > 0) {
+ if (getFrameRateDivisor(refreshRate.getFps(), layer.desiredRefreshRate) > 0) {
return 1.0f * seamlessness;
}
- // The layer frame rate is not a divider of the refresh rate,
+ // The layer frame rate is not a divisor of the refresh rate,
// there is a small penalty attached to the score to favor the frame rates
// the exactly matches the display refresh rate or a multiple.
constexpr float kNonExactMatchingPenalty = 0.95f;
@@ -543,11 +543,11 @@
}
}
- // We just care about the refresh rates which are a divider of the
+ // We just care about the refresh rates which are a divisor of the
// display refresh rate
auto iter =
std::remove_if(scores.begin(), scores.end(), [&](const RefreshRateScore& score) {
- return getFrameRateDivider(displayFrameRate, score.refreshRate->getFps()) == 0;
+ return getFrameRateDivisor(displayFrameRate, score.refreshRate->getFps()) == 0;
});
scores.erase(iter, scores.end());
@@ -723,7 +723,7 @@
if (mConfig.enableFrameRateOverride) {
for (const auto& mode1 : sortedModes) {
for (const auto& mode2 : sortedModes) {
- if (getFrameRateDivider(mode1->getFps(), mode2->getFps()) >= 2) {
+ if (getFrameRateDivisor(mode1->getFps(), mode2->getFps()) >= 2) {
mSupportsFrameRateOverrideByContent = true;
break;
}
@@ -915,7 +915,7 @@
return RefreshRateConfigs::KernelIdleTimerAction::TurnOn;
}
-int RefreshRateConfigs::getFrameRateDivider(Fps displayFrameRate, Fps layerFrameRate) {
+int RefreshRateConfigs::getFrameRateDivisor(Fps displayFrameRate, Fps layerFrameRate) {
// This calculation needs to be in sync with the java code
// in DisplayManagerService.getDisplayInfoForFrameRateOverride
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index f5b97c2..14583e3 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -316,10 +316,10 @@
bool supportsFrameRateOverrideByContent() const { return mSupportsFrameRateOverrideByContent; }
- // Return the display refresh rate divider to match the layer
+ // Return the display refresh rate divisor to match the layer
// frame rate, or 0 if the display refresh rate is not a multiple of the
// layer refresh rate.
- static int getFrameRateDivider(Fps displayFrameRate, Fps layerFrameRate);
+ static int getFrameRateDivisor(Fps displayFrameRate, Fps layerFrameRate);
// Returns if the provided frame rates have a ratio t*1000/1001 or t*1001/1000
// for an integer t.
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 82ff2fa..1fa455a 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -173,15 +173,15 @@
return basePeriod;
}
- const auto divider =
- scheduler::RefreshRateConfigs::getFrameRateDivider(refreshRateConfigs
+ const auto divisor =
+ scheduler::RefreshRateConfigs::getFrameRateDivisor(refreshRateConfigs
->getCurrentRefreshRate()
.getFps(),
*frameRate);
- if (divider <= 1) {
+ if (divisor <= 1) {
return basePeriod;
}
- return basePeriod * divider;
+ return basePeriod * divisor;
};
}
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index 61d2fb7..77782e9 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -256,7 +256,7 @@
/*
* Returns whether a given vsync timestamp is in phase with a frame rate.
- * If the frame rate is not a divider of the refresh rate, it is always considered in phase.
+ * If the frame rate is not a divisor of the refresh rate, it is always considered in phase.
* For example, if the vsync timestamps are (16.6,33.3,50.0,66.6):
* isVSyncInPhase(16.6, 30) = true
* isVSyncInPhase(33.3, 30) = false
@@ -271,42 +271,42 @@
};
std::lock_guard lock(mMutex);
- const auto divider =
- RefreshRateConfigs::getFrameRateDivider(Fps::fromPeriodNsecs(mIdealPeriod), frameRate);
- if (divider <= 1 || timePoint == 0) {
+ const auto divisor =
+ RefreshRateConfigs::getFrameRateDivisor(Fps::fromPeriodNsecs(mIdealPeriod), frameRate);
+ if (divisor <= 1 || timePoint == 0) {
return true;
}
const nsecs_t period = mRateMap[mIdealPeriod].slope;
const nsecs_t justBeforeTimePoint = timePoint - period / 2;
- const nsecs_t dividedPeriod = mIdealPeriod / divider;
+ const nsecs_t dividedPeriod = mIdealPeriod / divisor;
- // If this is the first time we have asked about this divider with the
+ // If this is the first time we have asked about this divisor with the
// current vsync period, it is considered in phase and we store the closest
// vsync timestamp
- const auto knownTimestampIter = mRateDividerKnownTimestampMap.find(dividedPeriod);
- if (knownTimestampIter == mRateDividerKnownTimestampMap.end()) {
+ const auto knownTimestampIter = mRateDivisorKnownTimestampMap.find(dividedPeriod);
+ if (knownTimestampIter == mRateDivisorKnownTimestampMap.end()) {
const auto vsync = nextAnticipatedVSyncTimeFromLocked(justBeforeTimePoint);
- mRateDividerKnownTimestampMap[dividedPeriod] = vsync;
+ mRateDivisorKnownTimestampMap[dividedPeriod] = vsync;
return true;
}
- // Find the next N vsync timestamp where N is the divider.
+ // Find the next N vsync timestamp where N is the divisor.
// One of these vsyncs will be in phase. We return the one which is
// the most aligned with the last known in phase vsync
- std::vector<VsyncError> vsyncs(static_cast<size_t>(divider));
+ std::vector<VsyncError> vsyncs(static_cast<size_t>(divisor));
const nsecs_t knownVsync = knownTimestampIter->second;
nsecs_t point = justBeforeTimePoint;
- for (size_t i = 0; i < divider; i++) {
+ for (size_t i = 0; i < divisor; i++) {
const nsecs_t vsync = nextAnticipatedVSyncTimeFromLocked(point);
- const auto numPeriods = static_cast<float>(vsync - knownVsync) / (period * divider);
+ const auto numPeriods = static_cast<float>(vsync - knownVsync) / (period * divisor);
const auto error = std::abs(std::round(numPeriods) - numPeriods);
vsyncs[i] = {vsync, error};
point = vsync + 1;
}
const auto minVsyncError = std::min_element(vsyncs.begin(), vsyncs.end());
- mRateDividerKnownTimestampMap[dividedPeriod] = minVsyncError->vsyncTimestamp;
+ mRateDivisorKnownTimestampMap[dividedPeriod] = minVsyncError->vsyncTimestamp;
return std::abs(minVsyncError->vsyncTimestamp - timePoint) < period / 2;
}
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.h b/services/surfaceflinger/Scheduler/VSyncPredictor.h
index cfaf7d6..3181102 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.h
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.h
@@ -96,7 +96,7 @@
std::unordered_map<nsecs_t, Model> mutable mRateMap GUARDED_BY(mMutex);
// Map between the divided vsync period and the last known vsync timestamp
- std::unordered_map<nsecs_t, nsecs_t> mutable mRateDividerKnownTimestampMap GUARDED_BY(mMutex);
+ std::unordered_map<nsecs_t, nsecs_t> mutable mRateDivisorKnownTimestampMap GUARDED_BY(mMutex);
size_t mLastTimestampIndex GUARDED_BY(mMutex) = 0;
std::vector<nsecs_t> mTimestamps GUARDED_BY(mMutex);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 59c07b6..2cd34e9 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -507,7 +507,7 @@
return LatchUnsignaledConfig::Always;
}
- if (base::GetBoolProperty("debug.sf.auto_latch_unsignaled"s, true)) {
+ if (base::GetBoolProperty("debug.sf.auto_latch_unsignaled"s, false)) {
return LatchUnsignaledConfig::AutoSingleLayer;
}
@@ -2344,16 +2344,19 @@
void SurfaceFlinger::setCompositorTimingSnapped(const DisplayStatInfo& stats,
nsecs_t compositeToPresentLatency) {
+ // Avoid division by 0 by defaulting to 60Hz
+ const auto vsyncPeriod = stats.vsyncPeriod ?: (60_Hz).getPeriodNsecs();
+
// Integer division and modulo round toward 0 not -inf, so we need to
// treat negative and positive offsets differently.
nsecs_t idealLatency = (mVsyncConfiguration->getCurrentConfigs().late.sfOffset > 0)
- ? (stats.vsyncPeriod -
- (mVsyncConfiguration->getCurrentConfigs().late.sfOffset % stats.vsyncPeriod))
- : ((-mVsyncConfiguration->getCurrentConfigs().late.sfOffset) % stats.vsyncPeriod);
+ ? (vsyncPeriod -
+ (mVsyncConfiguration->getCurrentConfigs().late.sfOffset % vsyncPeriod))
+ : ((-mVsyncConfiguration->getCurrentConfigs().late.sfOffset) % vsyncPeriod);
// Just in case mVsyncConfiguration->getCurrentConfigs().late.sf == -vsyncInterval.
if (idealLatency <= 0) {
- idealLatency = stats.vsyncPeriod;
+ idealLatency = vsyncPeriod;
}
// Snap the latency to a value that removes scheduling jitter from the
@@ -2362,16 +2365,14 @@
// something (such as user input) to an accurate diasplay time.
// Snapping also allows an app to precisely calculate
// mVsyncConfiguration->getCurrentConfigs().late.sf with (presentLatency % interval).
- const nsecs_t bias = stats.vsyncPeriod / 2;
- const int64_t extraVsyncs = (stats.vsyncPeriod) > 0 ?
- ((compositeToPresentLatency - idealLatency + bias) / stats.vsyncPeriod) :
- 0;
+ const nsecs_t bias = vsyncPeriod / 2;
+ const int64_t extraVsyncs = ((compositeToPresentLatency - idealLatency + bias) / vsyncPeriod);
const nsecs_t snappedCompositeToPresentLatency =
- (extraVsyncs > 0) ? idealLatency + (extraVsyncs * stats.vsyncPeriod) : idealLatency;
+ (extraVsyncs > 0) ? idealLatency + (extraVsyncs * vsyncPeriod) : idealLatency;
std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock);
getBE().mCompositorTiming.deadline = stats.vsyncTime - idealLatency;
- getBE().mCompositorTiming.interval = stats.vsyncPeriod;
+ getBE().mCompositorTiming.interval = vsyncPeriod;
getBE().mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
}
@@ -5341,7 +5342,7 @@
colorizer.reset(result);
const bool hwcDisabled = mDebugDisableHWC || mDebugFlashDelay;
StringAppendF(&result, " h/w composer %s\n", hwcDisabled ? "disabled" : "enabled");
- getHwComposer().dump(result);
+ dumpHwc(result);
/*
* Dump gralloc state
diff --git a/services/surfaceflinger/Tracing/tools/Android.bp b/services/surfaceflinger/Tracing/tools/Android.bp
new file mode 100644
index 0000000..114f1eb
--- /dev/null
+++ b/services/surfaceflinger/Tracing/tools/Android.bp
@@ -0,0 +1,46 @@
+// Copyright (C) 2022 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.
+
+cc_binary {
+ name: "layertracegenerator",
+ defaults: [
+ "libsurfaceflinger_mocks_defaults",
+ "surfaceflinger_defaults",
+ "skia_renderengine_deps",
+ ],
+ srcs: [
+ ":libsurfaceflinger_sources",
+ ":libsurfaceflinger_mock_sources",
+ ":layertracegenerator_sources",
+ "main.cpp",
+ ],
+ static_libs: [
+ "libgtest",
+ ],
+ header_libs: [
+ "libsurfaceflinger_mocks_headers",
+ ],
+}
+
+filegroup {
+ name: "layertracegenerator_sources",
+ srcs: [
+ "LayerTraceGenerator.cpp",
+ ],
+}
+
+cc_library_headers {
+ name: "layertracegenerator_headers",
+ export_include_dirs: ["."],
+}
diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
new file mode 100644
index 0000000..947fdce
--- /dev/null
+++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "LayerTraceGenerator"
+
+#include <TestableSurfaceFlinger.h>
+#include <Tracing/TransactionProtoParser.h>
+#include <binder/IPCThreadState.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <gui/LayerState.h>
+#include <log/log.h>
+#include <mock/MockEventThread.h>
+#include <renderengine/ExternalTexture.h>
+#include <renderengine/mock/FakeExternalTexture.h>
+#include <renderengine/mock/RenderEngine.h>
+#include <utils/String16.h>
+#include <string>
+
+#include "LayerTraceGenerator.h"
+
+namespace android {
+
+class Factory final : public surfaceflinger::Factory {
+public:
+ ~Factory() = default;
+
+ std::unique_ptr<HWComposer> createHWComposer(const std::string&) override { return nullptr; }
+
+ std::unique_ptr<scheduler::VsyncConfiguration> createVsyncConfiguration(
+ Fps /*currentRefreshRate*/) override {
+ return std::make_unique<scheduler::FakePhaseOffsets>();
+ }
+
+ sp<SurfaceInterceptor> createSurfaceInterceptor() override {
+ return new android::impl::SurfaceInterceptor();
+ }
+
+ sp<StartPropertySetThread> createStartPropertySetThread(
+ bool /* timestampPropertyValue */) override {
+ return nullptr;
+ }
+
+ sp<DisplayDevice> createDisplayDevice(DisplayDeviceCreationArgs& /* creationArgs */) override {
+ return nullptr;
+ }
+
+ sp<GraphicBuffer> createGraphicBuffer(uint32_t /* width */, uint32_t /* height */,
+ PixelFormat /* format */, uint32_t /* layerCount */,
+ uint64_t /* usage */,
+ std::string /* requestorName */) override {
+ return nullptr;
+ }
+
+ void createBufferQueue(sp<IGraphicBufferProducer>* /* outProducer */,
+ sp<IGraphicBufferConsumer>* /* outConsumer */,
+ bool /* consumerIsSurfaceFlinger */) override {}
+
+ sp<IGraphicBufferProducer> createMonitoredProducer(
+ const sp<IGraphicBufferProducer>& /* producer */,
+ const sp<SurfaceFlinger>& /* flinger */, const wp<Layer>& /* layer */) override {
+ return nullptr;
+ }
+
+ sp<BufferLayerConsumer> createBufferLayerConsumer(
+ const sp<IGraphicBufferConsumer>& /* consumer */,
+ renderengine::RenderEngine& /* renderEngine */, uint32_t /* textureName */,
+ Layer* /* layer */) override {
+ return nullptr;
+ }
+
+ std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface(
+ const sp<IGraphicBufferProducer>& /* producer */) override {
+ return nullptr;
+ }
+
+ std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() override {
+ return compositionengine::impl::createCompositionEngine();
+ }
+
+ sp<ContainerLayer> createContainerLayer(const LayerCreationArgs& args) {
+ return sp<ContainerLayer>::make(args);
+ }
+
+ sp<BufferStateLayer> createBufferStateLayer(const LayerCreationArgs& args) {
+ return new BufferStateLayer(args);
+ }
+
+ sp<EffectLayer> createEffectLayer(const LayerCreationArgs& args) {
+ return new EffectLayer(args);
+ }
+
+ sp<BufferQueueLayer> createBufferQueueLayer(const LayerCreationArgs&) override {
+ return nullptr;
+ }
+
+ std::unique_ptr<FrameTracer> createFrameTracer() override {
+ return std::make_unique<testing::NiceMock<mock::FrameTracer>>();
+ }
+
+ std::unique_ptr<frametimeline::FrameTimeline> createFrameTimeline(
+ std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid = 0) override {
+ return std::make_unique<testing::NiceMock<mock::FrameTimeline>>(timeStats,
+ surfaceFlingerPid);
+ }
+};
+
+class MockSurfaceFlinger : public SurfaceFlinger {
+public:
+ MockSurfaceFlinger(Factory& factory)
+ : SurfaceFlinger(factory, SurfaceFlinger::SkipInitialization) {}
+ std::shared_ptr<renderengine::ExternalTexture> getExternalTextureFromBufferData(
+ const BufferData& bufferData, const char* /* layerName */) const override {
+ return std::make_shared<renderengine::mock::FakeExternalTexture>(bufferData.getWidth(),
+ bufferData.getHeight(),
+ bufferData.getId(),
+ bufferData
+ .getPixelFormat(),
+ bufferData.getUsage());
+ };
+
+ // b/220017192 migrate from transact codes to ISurfaceComposer apis
+ void setLayerTracingFlags(int32_t flags) {
+ Parcel data;
+ Parcel reply;
+ data.writeInterfaceToken(String16("android.ui.ISurfaceComposer"));
+ data.writeInt32(flags);
+ transact(1033, data, &reply, 0 /* flags */);
+ }
+
+ void startLayerTracing(int64_t traceStartTime) {
+ Parcel data;
+ Parcel reply;
+ data.writeInterfaceToken(String16("android.ui.ISurfaceComposer"));
+ data.writeInt32(1);
+ data.writeInt64(traceStartTime);
+ transact(1025, data, &reply, 0 /* flags */);
+ }
+
+ void stopLayerTracing(const char* tracePath) {
+ Parcel data;
+ Parcel reply;
+ data.writeInterfaceToken(String16("android.ui.ISurfaceComposer"));
+ data.writeInt32(2);
+ data.writeCString(tracePath);
+ transact(1025, data, &reply, 0 /* flags */);
+ }
+};
+
+class TraceGenFlingerDataMapper : public TransactionProtoParser::FlingerDataMapper {
+public:
+ std::unordered_map<int32_t /*layerId*/, sp<IBinder> /* handle */> mLayerHandles;
+ sp<IBinder> getLayerHandle(int32_t layerId) const override {
+ if (layerId == -1) {
+ ALOGE("Error: Called with layer=%d", layerId);
+ return nullptr;
+ }
+ auto it = mLayerHandles.find(layerId);
+ if (it == mLayerHandles.end()) {
+ ALOGE("Error: Could not find handle for layer=%d", layerId);
+ return nullptr;
+ }
+ return it->second;
+ }
+};
+
+bool LayerTraceGenerator::generate(const proto::TransactionTraceFile& traceFile,
+ const char* outputLayersTracePath) {
+ if (traceFile.entry_size() == 0) {
+ return false;
+ }
+
+ Factory mFactory;
+ sp<MockSurfaceFlinger> flinger = new MockSurfaceFlinger(mFactory);
+ TestableSurfaceFlinger mFlinger(flinger);
+ mFlinger.setupRenderEngine(
+ std::make_unique<testing::NiceMock<renderengine::mock::RenderEngine>>());
+ mock::VsyncController* mVsyncController = new testing::NiceMock<mock::VsyncController>();
+ mock::VSyncTracker* mVSyncTracker = new testing::NiceMock<mock::VSyncTracker>();
+ mock::EventThread* mEventThread = new testing::NiceMock<mock::EventThread>();
+ mock::EventThread* mSFEventThread = new testing::NiceMock<mock::EventThread>();
+ mFlinger.setupScheduler(std::unique_ptr<scheduler::VsyncController>(mVsyncController),
+ std::unique_ptr<scheduler::VSyncTracker>(mVSyncTracker),
+ std::unique_ptr<EventThread>(mEventThread),
+ std::unique_ptr<EventThread>(mSFEventThread),
+ TestableSurfaceFlinger::SchedulerCallbackImpl::kNoOp,
+ TestableSurfaceFlinger::kOneDisplayMode, true /* useNiceMock */);
+
+ Hwc2::mock::Composer* mComposer = new testing::NiceMock<Hwc2::mock::Composer>();
+ mFlinger.setupComposer(std::unique_ptr<Hwc2::Composer>(mComposer));
+ mFlinger.mutableMaxRenderTargetSize() = 16384;
+
+ flinger->setLayerTracingFlags(LayerTracing::TRACE_BUFFERS | LayerTracing::TRACE_INPUT |
+ LayerTracing::TRACE_BUFFERS);
+ flinger->startLayerTracing(traceFile.entry(0).elapsed_realtime_nanos());
+ std::unique_ptr<TraceGenFlingerDataMapper> mapper =
+ std::make_unique<TraceGenFlingerDataMapper>();
+ TraceGenFlingerDataMapper* dataMapper = mapper.get();
+ TransactionProtoParser parser(std::move(mapper));
+
+ nsecs_t frameTime;
+ int64_t vsyncId;
+ ALOGD("Generating %d transactions...", traceFile.entry_size());
+ for (int i = 0; i < traceFile.entry_size(); i++) {
+ proto::TransactionTraceEntry entry = traceFile.entry(i);
+ ALOGV(" Entry %04d/%04d for time=%" PRId64 " vsyncid=%" PRId64
+ " layers +%d -%d transactions=%d",
+ i, traceFile.entry_size(), entry.elapsed_realtime_nanos(), entry.vsync_id(),
+ entry.added_layers_size(), entry.removed_layers_size(), entry.transactions_size());
+
+ for (int j = 0; j < entry.added_layers_size(); j++) {
+ // create layers
+ TracingLayerCreationArgs tracingArgs;
+ parser.fromProto(entry.added_layers(j), tracingArgs);
+
+ sp<IBinder> outHandle;
+ int32_t outLayerId;
+ LayerCreationArgs args(mFlinger.flinger(), nullptr /* client */, tracingArgs.name,
+ tracingArgs.flags, LayerMetadata());
+ args.sequence = std::make_optional<int32_t>(tracingArgs.layerId);
+
+ if (tracingArgs.mirrorFromId == -1) {
+ sp<IBinder> parentHandle = nullptr;
+ if ((tracingArgs.parentId != -1) &&
+ (dataMapper->mLayerHandles.find(tracingArgs.parentId) ==
+ dataMapper->mLayerHandles.end())) {
+ args.addToRoot = false;
+ } else {
+ parentHandle = dataMapper->getLayerHandle(tracingArgs.parentId);
+ }
+ mFlinger.createLayer(args, &outHandle, parentHandle, &outLayerId,
+ nullptr /* parentLayer */, nullptr /* outTransformHint */);
+ } else {
+ sp<IBinder> mirrorFromHandle = dataMapper->getLayerHandle(tracingArgs.mirrorFromId);
+ mFlinger.mirrorLayer(args, mirrorFromHandle, &outHandle, &outLayerId);
+ }
+ LOG_ALWAYS_FATAL_IF(outLayerId != tracingArgs.layerId,
+ "Could not create layer expected:%d actual:%d", tracingArgs.layerId,
+ outLayerId);
+ dataMapper->mLayerHandles[tracingArgs.layerId] = outHandle;
+ }
+
+ for (int j = 0; j < entry.transactions_size(); j++) {
+ // apply transactions
+ TransactionState transaction = parser.fromProto(entry.transactions(j));
+ mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states,
+ transaction.displays, transaction.flags,
+ transaction.applyToken, transaction.inputWindowCommands,
+ transaction.desiredPresentTime,
+ transaction.isAutoTimestamp, {},
+ transaction.hasListenerCallbacks,
+ transaction.listenerCallbacks, transaction.id);
+ }
+
+ for (int j = 0; j < entry.removed_layer_handles_size(); j++) {
+ dataMapper->mLayerHandles.erase(entry.removed_layer_handles(j));
+ }
+
+ frameTime = entry.elapsed_realtime_nanos();
+ vsyncId = entry.vsync_id();
+ mFlinger.commit(frameTime, vsyncId);
+ }
+
+ flinger->stopLayerTracing(outputLayersTracePath);
+ ALOGD("End of generating trace file. File written to %s", outputLayersTracePath);
+ dataMapper->mLayerHandles.clear();
+ return true;
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h
new file mode 100644
index 0000000..ee1ea6c
--- /dev/null
+++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#pragma once
+
+#include <Tracing/TransactionTracing.h>
+
+namespace android {
+class LayerTraceGenerator {
+public:
+ bool generate(const proto::TransactionTraceFile&, const char* outputLayersTracePath);
+};
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/Tracing/tools/main.cpp b/services/surfaceflinger/Tracing/tools/main.cpp
new file mode 100644
index 0000000..f3cf42d
--- /dev/null
+++ b/services/surfaceflinger/Tracing/tools/main.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "LayerTraceGenerator"
+
+#include <fstream>
+#include <iostream>
+#include <string>
+
+#include "LayerTraceGenerator.h"
+
+using namespace android;
+
+int main(int argc, char** argv) {
+ if (argc > 3) {
+ std::cout << "Usage: " << argv[0]
+ << " [transaction-trace-path] [output-layers-trace-path]\n";
+ return -1;
+ }
+
+ const char* transactionTracePath =
+ (argc > 1) ? argv[1] : "/data/misc/wmtrace/transactions_trace.winscope";
+ std::cout << "Parsing " << transactionTracePath << "\n";
+ std::fstream input(transactionTracePath, std::ios::in | std::ios::binary);
+ if (!input) {
+ std::cout << "Error: Could not open " << transactionTracePath;
+ return -1;
+ }
+
+ proto::TransactionTraceFile transactionTraceFile;
+ if (!transactionTraceFile.ParseFromIstream(&input)) {
+ std::cout << "Error: Failed to parse " << transactionTracePath;
+ return -1;
+ }
+
+ const char* outputLayersTracePath =
+ (argc == 3) ? argv[2] : "/data/misc/wmtrace/layers_trace.winscope";
+ ;
+ ALOGD("Generating %s...", outputLayersTracePath);
+ std::cout << "Generating " << outputLayersTracePath << "\n";
+ if (!LayerTraceGenerator().generate(transactionTraceFile, outputLayersTracePath)) {
+ std::cout << "Error: Failed to generate layers trace " << outputLayersTracePath;
+ return -1;
+ }
+ return 0;
+}
\ No newline at end of file
diff --git a/services/surfaceflinger/Tracing/tools/readme.md b/services/surfaceflinger/Tracing/tools/readme.md
new file mode 100644
index 0000000..143c14f
--- /dev/null
+++ b/services/surfaceflinger/Tracing/tools/readme.md
@@ -0,0 +1,13 @@
+### LayerTraceGenerator ###
+
+Generates layer traces from transaction traces. The tool is a custom
+surface flinger build that mocks out everything else apart from the
+front end logic. Transaction traces are written when the transaction
+is applied, along wth a timestamp and vsync id. The transactions
+are parsed from proto and applied to recreate the layer state. The
+result is then written as a layer trace.
+
+Usage:
+1. build and push to device
+2. run ./layertracegenerator [transaction-trace-path] [output-layers-trace-path]
+
diff --git a/services/surfaceflinger/Tracing/tools/run.sh b/services/surfaceflinger/Tracing/tools/run.sh
new file mode 100644
index 0000000..baa93f1
--- /dev/null
+++ b/services/surfaceflinger/Tracing/tools/run.sh
@@ -0,0 +1,11 @@
+#!/usr/bin/env bash
+
+set -ex
+
+# Build, push and run layertracegenerator
+$ANDROID_BUILD_TOP/build/soong/soong_ui.bash --make-mode layertracegenerator
+adb wait-for-device && adb push $OUT/system/bin/layertracegenerator /data/layertracegenerator
+echo "Writing transaction trace to file"
+adb shell service call SurfaceFlinger 1041 i32 0
+adb shell /data/layertracegenerator
+adb pull /data/misc/wmtrace/layers_trace.winscope
\ No newline at end of file
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
index 09ffb02..d504155 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
@@ -357,7 +357,7 @@
mFdp.ConsumeFloatingPoint<float>()),
Fps::fromValue(
mFdp.ConsumeFloatingPoint<float>()));
- RefreshRateConfigs::getFrameRateDivider(Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()),
+ RefreshRateConfigs::getFrameRateDivisor(Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()),
Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()));
android::mock::TimeStats timeStats;
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 1db5e61..58cd7ba 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -42,6 +42,7 @@
cc_test {
name: "libsurfaceflinger_unittest",
defaults: [
+ "libsurfaceflinger_mocks_defaults",
"skia_renderengine_deps",
"surfaceflinger_defaults",
],
@@ -122,6 +123,10 @@
"VSyncReactorTest.cpp",
"VsyncConfigurationTest.cpp",
],
+}
+
+cc_defaults {
+ name: "libsurfaceflinger_mocks_defaults",
static_libs: [
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
@@ -193,3 +198,8 @@
"libsurfaceflinger_headers",
],
}
+
+cc_library_headers {
+ name: "libsurfaceflinger_mocks_headers",
+ export_include_dirs: ["."],
+}
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index 9143d61..97f3747 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -1873,37 +1873,37 @@
EXPECT_EQ(KernelIdleTimerAction::TurnOff, configs.getIdleTimerAction());
}
-TEST_F(RefreshRateConfigsTest, getFrameRateDivider) {
+TEST_F(RefreshRateConfigsTest, getFrameRateDivisor) {
RefreshRateConfigs configs(kModes_30_60_72_90_120, kModeId30);
const auto frameRate = 30_Hz;
Fps displayRefreshRate = configs.getCurrentRefreshRate().getFps();
- EXPECT_EQ(1, RefreshRateConfigs::getFrameRateDivider(displayRefreshRate, frameRate));
+ EXPECT_EQ(1, RefreshRateConfigs::getFrameRateDivisor(displayRefreshRate, frameRate));
configs.setCurrentModeId(kModeId60);
displayRefreshRate = configs.getCurrentRefreshRate().getFps();
- EXPECT_EQ(2, RefreshRateConfigs::getFrameRateDivider(displayRefreshRate, frameRate));
+ EXPECT_EQ(2, RefreshRateConfigs::getFrameRateDivisor(displayRefreshRate, frameRate));
configs.setCurrentModeId(kModeId72);
displayRefreshRate = configs.getCurrentRefreshRate().getFps();
- EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivider(displayRefreshRate, frameRate));
+ EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivisor(displayRefreshRate, frameRate));
configs.setCurrentModeId(kModeId90);
displayRefreshRate = configs.getCurrentRefreshRate().getFps();
- EXPECT_EQ(3, RefreshRateConfigs::getFrameRateDivider(displayRefreshRate, frameRate));
+ EXPECT_EQ(3, RefreshRateConfigs::getFrameRateDivisor(displayRefreshRate, frameRate));
configs.setCurrentModeId(kModeId120);
displayRefreshRate = configs.getCurrentRefreshRate().getFps();
- EXPECT_EQ(4, RefreshRateConfigs::getFrameRateDivider(displayRefreshRate, frameRate));
+ EXPECT_EQ(4, RefreshRateConfigs::getFrameRateDivisor(displayRefreshRate, frameRate));
configs.setCurrentModeId(kModeId90);
displayRefreshRate = configs.getCurrentRefreshRate().getFps();
- EXPECT_EQ(4, RefreshRateConfigs::getFrameRateDivider(displayRefreshRate, 22.5_Hz));
+ EXPECT_EQ(4, RefreshRateConfigs::getFrameRateDivisor(displayRefreshRate, 22.5_Hz));
- EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivider(24_Hz, 25_Hz));
- EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivider(24_Hz, 23.976_Hz));
- EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivider(30_Hz, 29.97_Hz));
- EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivider(60_Hz, 59.94_Hz));
+ EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivisor(24_Hz, 25_Hz));
+ EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivisor(24_Hz, 23.976_Hz));
+ EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivisor(30_Hz, 29.97_Hz));
+ EXPECT_EQ(0, RefreshRateConfigs::getFrameRateDivisor(60_Hz, 59.94_Hz));
}
TEST_F(RefreshRateConfigsTest, isFractionalPairOrMultiple) {
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 67e47e7..d83b9bb 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -177,8 +177,10 @@
public:
using HotplugEvent = SurfaceFlinger::HotplugEvent;
- TestableSurfaceFlinger()
- : mFlinger(sp<SurfaceFlinger>::make(mFactory, SurfaceFlinger::SkipInitialization)) {
+ TestableSurfaceFlinger(sp<SurfaceFlinger> flinger = nullptr) : mFlinger(flinger) {
+ if (!mFlinger) {
+ mFlinger = sp<SurfaceFlinger>::make(mFactory, SurfaceFlinger::SkipInitialization);
+ }
mFlinger->mAnimationTransactionTimeout = ms2ns(10);
}
@@ -219,7 +221,8 @@
std::unique_ptr<EventThread> appEventThread,
std::unique_ptr<EventThread> sfEventThread,
SchedulerCallbackImpl callbackImpl = SchedulerCallbackImpl::kNoOp,
- DisplayModesVariant modesVariant = kOneDisplayMode) {
+ DisplayModesVariant modesVariant = kOneDisplayMode,
+ bool useNiceMock = false) {
RefreshRateConfigsPtr configs;
if (std::holds_alternative<RefreshRateConfigsPtr>(modesVariant)) {
configs = std::move(std::get<RefreshRateConfigsPtr>(modesVariant));
@@ -256,9 +259,17 @@
? static_cast<Callback&>(mNoOpSchedulerCallback)
: static_cast<Callback&>(mSchedulerCallback);
- mScheduler = new scheduler::TestableScheduler(std::move(vsyncController),
- std::move(vsyncTracker), std::move(configs),
- callback);
+ if (useNiceMock) {
+ mScheduler =
+ new testing::NiceMock<scheduler::TestableScheduler>(std::move(vsyncController),
+ std::move(vsyncTracker),
+ std::move(configs),
+ callback);
+ } else {
+ mScheduler = new scheduler::TestableScheduler(std::move(vsyncController),
+ std::move(vsyncTracker),
+ std::move(configs), callback);
+ }
mFlinger->mAppConnectionHandle = mScheduler->createConnection(std::move(appEventThread));
mFlinger->mSfConnectionHandle = mScheduler->createConnection(std::move(sfEventThread));
@@ -455,6 +466,23 @@
mFlinger->onActiveDisplayChangedLocked(activeDisplay);
}
+ auto commit(nsecs_t frameTime, int64_t vsyncId) {
+ const nsecs_t expectedVsyncTime = frameTime + 10'000'000;
+ mFlinger->commit(frameTime, vsyncId, expectedVsyncTime);
+ }
+
+ auto createLayer(LayerCreationArgs& args, sp<IBinder>* outHandle,
+ const sp<IBinder>& parentHandle, int32_t* outLayerId,
+ const sp<Layer>& parentLayer, uint32_t* outTransformHint) {
+ return mFlinger->createLayer(args, outHandle, parentHandle, outLayerId, parentLayer,
+ outTransformHint);
+ }
+
+ auto mirrorLayer(const LayerCreationArgs& args, const sp<IBinder>& mirrorFromHandle,
+ sp<IBinder>* outHandle, int32_t* outLayerId) {
+ return mFlinger->mirrorLayer(args, mirrorFromHandle, outHandle, outLayerId);
+ }
+
/* ------------------------------------------------------------------------
* Read-only access to private data to assert post-conditions.
*/
@@ -850,8 +878,7 @@
private:
surfaceflinger::test::Factory mFactory;
- sp<SurfaceFlinger> mFlinger = new SurfaceFlinger(mFactory, SurfaceFlinger::SkipInitialization);
-
+ sp<SurfaceFlinger> mFlinger;
scheduler::mock::SchedulerCallback mSchedulerCallback;
scheduler::mock::NoOpSchedulerCallback mNoOpSchedulerCallback;
scheduler::TestableScheduler* mScheduler = nullptr;
diff --git a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
index 37ecd7c..74d2b7d 100644
--- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
@@ -464,16 +464,16 @@
EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 100), Eq(mNow + mPeriod - bias));
EXPECT_THAT(tracker.nextAnticipatedVSyncTimeFrom(mNow + 990), Eq(mNow + 2 * mPeriod - bias));
- const auto maxDivider = 5;
+ const auto maxDivisor = 5;
const auto maxPeriods = 15;
- for (int divider = 1; divider < maxDivider; divider++) {
+ for (int divisor = 1; divisor < maxDivisor; divisor++) {
for (int i = 0; i < maxPeriods; i++) {
- const bool expectedInPhase = (i % divider) == 0;
+ const bool expectedInPhase = (i % divisor) == 0;
EXPECT_THAT(expectedInPhase,
tracker.isVSyncInPhase(mNow + i * mPeriod - bias,
- Fps::fromPeriodNsecs(divider * mPeriod)))
+ Fps::fromPeriodNsecs(divisor * mPeriod)))
<< "vsync at " << mNow + (i + 1) * mPeriod - bias << " is "
- << (expectedInPhase ? "not " : "") << "in phase for divider " << divider;
+ << (expectedInPhase ? "not " : "") << "in phase for divisor " << divisor;
}
}
}