Resize object capacity when shrinking Parcel am: d9d10dbdf2 am: 7bd9c861ce am: 0546a8e7eb am: 8d93919318 am: 0f32f9296b am: 90c968f6e9
Change-Id: If221560ce978745f35de4b2f99976a25432bf421
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index a4b00f8..1429bc8 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -171,6 +171,7 @@
{ OPT, "events/clk/clk_disable/enable" },
{ OPT, "events/clk/clk_enable/enable" },
{ OPT, "events/power/cpu_frequency_limits/enable" },
+ { OPT, "events/power/suspend_resume/enable" },
} },
{ "membus", "Memory Bus Utilization", 0, {
{ REQ, "events/memory_bus/enable" },
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index f1426b6..6e460a0 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -49,6 +49,8 @@
chmod 0666 /sys/kernel/tracing/events/power/cpu_frequency_limits/enable
chmod 0666 /sys/kernel/debug/tracing/events/power/gpu_frequency/enable
chmod 0666 /sys/kernel/tracing/events/power/gpu_frequency/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/power/suspend_resume/enable
+ chmod 0666 /sys/kernel/tracing/events/power/suspend_resume/enable
chmod 0666 /sys/kernel/debug/tracing/events/cpufreq_interactive/enable
chmod 0666 /sys/kernel/tracing/events/cpufreq_interactive/enable
chmod 0666 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin/enable
diff --git a/data/etc/car_core_hardware.xml b/data/etc/car_core_hardware.xml
index ad7791e..50f117d 100644
--- a/data/etc/car_core_hardware.xml
+++ b/data/etc/car_core_hardware.xml
@@ -40,7 +40,6 @@
<feature name="android.software.voice_recognizers" notLowRam="true" />
<feature name="android.software.backup" />
<feature name="android.software.home_screen" />
- <feature name="android.software.print" />
<feature name="android.software.companion_device_setup" />
<feature name="android.software.autofill" />
<feature name="android.software.cant_save_state" />
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 8e762f1..0477801 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -16,7 +16,9 @@
#include <set>
#include <android-base/file.h>
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
#include <dumputils/dump_utils.h>
#include <log/log.h>
@@ -46,6 +48,7 @@
static const char* hal_interfaces_to_dump[] {
"android.hardware.audio@2.0::IDevicesFactory",
"android.hardware.audio@4.0::IDevicesFactory",
+ "android.hardware.audio@5.0::IDevicesFactory",
"android.hardware.biometrics.face@1.0::IBiometricsFace",
"android.hardware.bluetooth@1.0::IBluetoothHci",
"android.hardware.camera.provider@2.4::ICameraProvider",
@@ -61,16 +64,40 @@
"android.hardware.sensors@1.0::ISensors",
"android.hardware.thermal@2.0::IThermal",
"android.hardware.vr@1.0::IVr",
+ "android.hardware.automotive.audiocontrol@1.0::IAudioControl",
+ "android.hardware.automotive.vehicle@2.0::IVehicle",
+ "android.hardware.automotive.evs@1.0::IEvsCamera",
NULL,
};
-bool should_dump_hal_interface(const char* interface) {
+/* list of extra hal interfaces to dump containing process during native dumps */
+// This is filled when dumpstate is called.
+static std::set<const std::string> extra_hal_interfaces_to_dump;
+
+static void read_extra_hals_to_dump_from_property() {
+ // extra hals to dump are already filled
+ if (extra_hal_interfaces_to_dump.size() > 0) {
+ return;
+ }
+ std::string value = android::base::GetProperty("ro.dump.hals.extra", "");
+ std::vector<std::string> tokens = android::base::Split(value, ",");
+ for (const auto &token : tokens) {
+ std::string trimmed_token = android::base::Trim(token);
+ if (trimmed_token.length() == 0) {
+ continue;
+ }
+ extra_hal_interfaces_to_dump.insert(trimmed_token);
+ }
+}
+
+// check if interface is included in either default hal list or extra hal list
+bool should_dump_hal_interface(const std::string& interface) {
for (const char** i = hal_interfaces_to_dump; *i; i++) {
- if (!strcmp(*i, interface)) {
+ if (interface == *i) {
return true;
}
}
- return false;
+ return extra_hal_interfaces_to_dump.find(interface) != extra_hal_interfaces_to_dump.end();
}
bool should_dump_native_traces(const char* path) {
@@ -90,13 +117,15 @@
sp<IServiceManager> manager = IServiceManager::getService();
std::set<int> pids;
+ read_extra_hals_to_dump_from_property();
+
Return<void> ret = manager->debugDump([&](auto& hals) {
for (const auto &info : hals) {
if (info.pid == static_cast<int>(IServiceManager::PidConstant::NO_PID)) {
continue;
}
- if (!should_dump_hal_interface(info.interfaceName.c_str())) {
+ if (!should_dump_hal_interface(info.interfaceName)) {
continue;
}
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index ff1ba0a..05a9bb5 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -422,9 +422,11 @@
surface->expectTap(1, 1);
}
-// Ensure we send the input to the right surface when the surface visibility changes due to the
-// first buffer being submitted. ref: b/120839715
-TEST_F(InputSurfacesTest, input_respects_buffer_layer_buffer) {
+// TODO(b/139494112) update tests once we define expected behavior
+// Ensure we still send input to the surface regardless of surface visibility changes due to the
+// first buffer being submitted or alpha changes.
+// Original bug ref: b/120839715
+TEST_F(InputSurfacesTest, input_ignores_buffer_layer_buffer) {
std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
std::unique_ptr<InputSurface> bufferSurface =
InputSurface::makeBufferInputSurface(mComposerClient, 100, 100);
@@ -433,14 +435,14 @@
bufferSurface->showAt(10, 10);
injectTap(11, 11);
- bgSurface->expectTap(1, 1);
+ bufferSurface->expectTap(1, 1);
postBuffer(bufferSurface->mSurfaceControl);
injectTap(11, 11);
bufferSurface->expectTap(1, 1);
}
-TEST_F(InputSurfacesTest, input_respects_buffer_layer_alpha) {
+TEST_F(InputSurfacesTest, input_ignores_buffer_layer_alpha) {
std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
std::unique_ptr<InputSurface> bufferSurface =
InputSurface::makeBufferInputSurface(mComposerClient, 100, 100);
@@ -455,10 +457,10 @@
bufferSurface->doTransaction([](auto &t, auto &sc) { t.setAlpha(sc, 0.0); });
injectTap(11, 11);
- bgSurface->expectTap(1, 1);
+ bufferSurface->expectTap(1, 1);
}
-TEST_F(InputSurfacesTest, input_respects_color_layer_alpha) {
+TEST_F(InputSurfacesTest, input_ignores_color_layer_alpha) {
std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
@@ -471,7 +473,7 @@
fgSurface->doTransaction([](auto &t, auto &sc) { t.setAlpha(sc, 0.0); });
injectTap(11, 11);
- bgSurface->expectTap(1, 1);
+ fgSurface->expectTap(1, 1);
}
TEST_F(InputSurfacesTest, input_respects_container_layer_visiblity) {
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index 9c7d1fd..d588346 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -132,6 +132,17 @@
status_t error =
mAllocator->allocate(width, height, format, layerCount, usage, 1, stride, handle);
+ size_t bufSize;
+
+ // if stride has no meaning or is too large,
+ // approximate size with the input width instead
+ if ((*stride) != 0 &&
+ std::numeric_limits<size_t>::max() / height / (*stride) < static_cast<size_t>(bpp)) {
+ bufSize = static_cast<size_t>(width) * height * bpp;
+ } else {
+ bufSize = static_cast<size_t>((*stride)) * height * bpp;
+ }
+
if (error == NO_ERROR) {
Mutex::Autolock _l(sLock);
KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
@@ -142,7 +153,7 @@
rec.format = format;
rec.layerCount = layerCount;
rec.usage = usage;
- rec.size = static_cast<size_t>(height * (*stride) * bpp);
+ rec.size = bufSize;
rec.requestorName = std::move(requestorName);
list.add(*handle, rec);
diff --git a/libs/ui/include/ui/GraphicBufferAllocator.h b/libs/ui/include/ui/GraphicBufferAllocator.h
index 25d4512..324d9e1 100644
--- a/libs/ui/include/ui/GraphicBufferAllocator.h
+++ b/libs/ui/include/ui/GraphicBufferAllocator.h
@@ -54,7 +54,7 @@
void dump(std::string& res) const;
static void dumpToSystemLog();
-private:
+protected:
struct alloc_rec_t {
uint32_t width;
uint32_t height;
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index 373fa4f..15f4b64 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -29,6 +29,26 @@
}
cc_test {
+ name: "GraphicBufferAllocator_test",
+ header_libs: [
+ "libdvr_headers",
+ "libnativewindow_headers",
+ ],
+ static_libs: [
+ "libgmock",
+ ],
+ shared_libs: [
+ "liblog",
+ "libui",
+ ],
+ srcs: [
+ "GraphicBufferAllocator_test.cpp",
+ "mock/MockGrallocAllocator.cpp",
+ ],
+ cflags: ["-Wall", "-Werror"],
+}
+
+cc_test {
name: "GraphicBuffer_test",
header_libs: [
"libdvr_headers",
diff --git a/libs/ui/tests/GraphicBufferAllocator_test.cpp b/libs/ui/tests/GraphicBufferAllocator_test.cpp
new file mode 100644
index 0000000..efca083
--- /dev/null
+++ b/libs/ui/tests/GraphicBufferAllocator_test.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GraphicBufferAllocatorTest"
+
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferAllocator.h>
+#include <ui/PixelFormat.h>
+
+#include <gtest/gtest.h>
+
+#include "mock/MockGrallocAllocator.h"
+
+#include <algorithm>
+#include <limits>
+
+namespace android {
+
+namespace {
+
+constexpr uint32_t kTestWidth = 1024;
+constexpr uint32_t kTestHeight = 1;
+constexpr uint32_t kTestLayerCount = 1;
+constexpr uint64_t kTestUsage = GraphicBuffer::USAGE_SW_WRITE_OFTEN;
+
+} // namespace
+
+using ::testing::DoAll;
+using ::testing::Return;
+using ::testing::SetArgPointee;
+
+class TestableGraphicBufferAllocator : public GraphicBufferAllocator {
+public:
+ TestableGraphicBufferAllocator() {
+ mAllocator = std::make_unique<const mock::MockGrallocAllocator>();
+ }
+ void setUpAllocateExpectations(status_t err, uint32_t stride) {
+ std::cout << "Setting expected stride to " << stride << std::endl;
+ EXPECT_CALL(*(reinterpret_cast<const mock::MockGrallocAllocator*>(mAllocator.get())),
+ allocate)
+ .WillOnce(DoAll(SetArgPointee<6>(stride), Return(err)));
+ }
+ std::unique_ptr<const GrallocAllocator>& getAllocator() { return mAllocator; }
+};
+
+class GraphicBufferAllocatorTest : public testing::Test {
+public:
+ GraphicBufferAllocatorTest() : mAllocator() {}
+ const TestableGraphicBufferAllocator& getAllocator() { return mAllocator; }
+
+protected:
+ TestableGraphicBufferAllocator mAllocator;
+};
+
+TEST_F(GraphicBufferAllocatorTest, AllocateNoError) {
+ mAllocator.setUpAllocateExpectations(NO_ERROR, kTestWidth);
+ android::PixelFormat format = PIXEL_FORMAT_RGBA_8888;
+ uint32_t stride = 0;
+ buffer_handle_t handle;
+ status_t err = mAllocator.allocate(kTestWidth, kTestHeight, format, kTestLayerCount, kTestUsage,
+ &handle, &stride, 0, "GraphicBufferAllocatorTest");
+ ASSERT_EQ(NO_ERROR, err);
+ ASSERT_EQ(kTestWidth, stride);
+}
+
+TEST_F(GraphicBufferAllocatorTest, AllocateZeroStride) {
+ android::PixelFormat format = PIXEL_FORMAT_RGBA_8888;
+ uint32_t expectedStride = 0;
+
+ mAllocator.setUpAllocateExpectations(NO_ERROR, expectedStride);
+ uint32_t stride = 0;
+ buffer_handle_t handle;
+ // a divide by zero would cause a crash
+ status_t err = mAllocator.allocate(kTestWidth, kTestHeight, format, kTestLayerCount, kTestUsage,
+ &handle, &stride, 0, "GraphicBufferAllocatorTest");
+ ASSERT_EQ(NO_ERROR, err);
+ ASSERT_EQ(expectedStride, stride);
+}
+
+TEST_F(GraphicBufferAllocatorTest, AllocateLargeStride) {
+ uint32_t height = std::numeric_limits<uint32_t>::max();
+ uint32_t bpp = 4;
+ android::PixelFormat format = PIXEL_FORMAT_RGBA_8888;
+
+ if (std::numeric_limits<size_t>::max() / height / bpp >= std::numeric_limits<uint32_t>::max()) {
+ std::cout << "stride cannot cause overflow" << std::endl;
+ GTEST_SUCCEED() << "stride cannot cause overflow";
+ return;
+ }
+ uint32_t width = std::numeric_limits<size_t>::max() / height / bpp;
+
+ uint32_t expectedStride = std::numeric_limits<uint32_t>::max();
+
+ mAllocator.setUpAllocateExpectations(NO_ERROR, expectedStride);
+ uint32_t stride = 0;
+ buffer_handle_t handle;
+ // an overflow would cause a crash
+ status_t err = mAllocator.allocate(width, height, format, kTestLayerCount, kTestUsage, &handle,
+ &stride, 0, "GraphicBufferAllocatorTest");
+ ASSERT_EQ(NO_ERROR, err);
+ ASSERT_EQ(expectedStride, stride);
+}
+} // namespace android
diff --git a/libs/ui/tests/mock/MockGrallocAllocator.cpp b/libs/ui/tests/mock/MockGrallocAllocator.cpp
new file mode 100644
index 0000000..d71e25f
--- /dev/null
+++ b/libs/ui/tests/mock/MockGrallocAllocator.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MockGrallocAllocator.h"
+
+namespace android {
+
+namespace mock {
+
+MockGrallocAllocator::MockGrallocAllocator() = default;
+MockGrallocAllocator::~MockGrallocAllocator() = default;
+
+} // namespace mock
+} // namespace android
diff --git a/libs/ui/tests/mock/MockGrallocAllocator.h b/libs/ui/tests/mock/MockGrallocAllocator.h
new file mode 100644
index 0000000..22c80a4
--- /dev/null
+++ b/libs/ui/tests/mock/MockGrallocAllocator.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+
+#include <ui/Gralloc.h>
+
+namespace android {
+
+class GraphicBuffer;
+
+namespace mock {
+
+class MockGrallocAllocator : public GrallocAllocator {
+public:
+ MockGrallocAllocator();
+ ~MockGrallocAllocator() override;
+
+ MOCK_METHOD(bool, isLoaded, (), (const, override));
+ MOCK_METHOD(std::string, dumpDebugInfo, (), (const, override));
+ MOCK_METHOD(status_t, allocate,
+ (uint32_t width, uint32_t height, PixelFormat format, uint32_t layerCount,
+ uint64_t usage, uint32_t bufferCount, uint32_t* outStride,
+ buffer_handle_t* outBufferHandles),
+ (const, override));
+};
+
+} // namespace mock
+} // namespace android
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index e996be6..a3bb6de 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -61,7 +61,7 @@
using nsecs_t = int64_t;
-struct extention_map_t {
+struct extension_map_t {
const char* name;
__eglMustCastToProperFunctionPointerType address;
};
@@ -154,7 +154,7 @@
* (keep in sync with gExtensionString above)
*
*/
-static const extention_map_t sExtensionMap[] = {
+static const extension_map_t sExtensionMap[] = {
// EGL_KHR_lock_surface
{ "eglLockSurfaceKHR",
(__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
@@ -257,13 +257,14 @@
!strcmp((procname), "eglAwakenProcessIMG"))
// accesses protected by sExtensionMapMutex
-static std::unordered_map<std::string, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
+static std::unordered_map<std::string, __eglMustCastToProperFunctionPointerType> sGLExtensionMap;
+static std::unordered_map<std::string, int> sGLExtensionSlotMap;
-static int sGLExtentionSlot = 0;
+static int sGLExtensionSlot = 0;
static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
static void(*findProcAddress(const char* name,
- const extention_map_t* map, size_t n))() {
+ const extension_map_t* map, size_t n))() {
for (uint32_t i=0 ; i<n ; i++) {
if (!strcmp(name, map[i].name)) {
return map[i].address;
@@ -1223,7 +1224,7 @@
addr = findBuiltinWrapper(procname);
if (addr) return addr;
- // this protects accesses to sGLExtentionMap and sGLExtentionSlot
+ // this protects accesses to sGLExtensionMap, sGLExtensionSlot, and sGLExtensionSlotMap
pthread_mutex_lock(&sExtensionMapMutex);
/*
@@ -1244,51 +1245,69 @@
*/
const std::string name(procname);
-
- auto& extentionMap = sGLExtentionMap;
- auto pos = extentionMap.find(name);
- addr = (pos != extentionMap.end()) ? pos->second : nullptr;
- const int slot = sGLExtentionSlot;
-
- ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
- "no more slots for eglGetProcAddress(\"%s\")",
- procname);
-
+ auto& extensionMap = sGLExtensionMap;
+ auto& extensionSlotMap = sGLExtensionSlotMap;
egl_connection_t* const cnx = &gEGLImpl;
LayerLoader& layer_loader(LayerLoader::getInstance());
- if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
+ // See if we've already looked up this extension
+ auto pos = extensionMap.find(name);
+ addr = (pos != extensionMap.end()) ? pos->second : nullptr;
- if (cnx->dso && cnx->egl.eglGetProcAddress) {
+ if (!addr) {
+ // This is the first time we've looked this function up
+ // Ensure we have room to track it
+ const int slot = sGLExtensionSlot;
+ if (slot < MAX_NUMBER_OF_GL_EXTENSIONS) {
- // Extensions are independent of the bound context
- addr = cnx->egl.eglGetProcAddress(procname);
- if (addr) {
+ if (cnx->dso && cnx->egl.eglGetProcAddress) {
- // purposefully track the bottom of the stack in extensionMap
- extentionMap[name] = addr;
+ // Extensions are independent of the bound context
+ addr = cnx->egl.eglGetProcAddress(procname);
+ if (addr) {
- // Apply layers
- addr = layer_loader.ApplyLayers(procname, addr);
+ // purposefully track the bottom of the stack in extensionMap
+ extensionMap[name] = addr;
- // Track the top most entry point
- cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
- cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = addr;
- addr = gExtensionForwarders[slot];
- sGLExtentionSlot++;
+ // Apply layers
+ addr = layer_loader.ApplyLayers(procname, addr);
+
+ // Track the top most entry point return the extension forwarder
+ cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
+ cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = addr;
+ addr = gExtensionForwarders[slot];
+
+ // Remember the slot for this extension
+ extensionSlotMap[name] = slot;
+
+ // Increment the global extension index
+ sGLExtensionSlot++;
+ }
}
+ } else {
+ // The extension forwarder has a fixed number of slots
+ ALOGE("no more slots for eglGetProcAddress(\"%s\")", procname);
}
- } else if (slot < MAX_NUMBER_OF_GL_EXTENSIONS) {
+ } else {
+ // We tracked an address, so we've seen this func before
+ // Look up the slot for this extension
+ auto slot_pos = extensionSlotMap.find(name);
+ int ext_slot = (slot_pos != extensionSlotMap.end()) ? slot_pos->second : -1;
+ if (ext_slot < 0) {
+ // Something has gone wrong, this should not happen
+ ALOGE("No extension slot found for %s", procname);
+ return nullptr;
+ }
- // We've seen this func before, but we tracked the bottom, so re-apply layers
- // More layers might have been enabled
+ // We tracked the bottom of the stack, so re-apply layers since
+ // more layers might have been enabled
addr = layer_loader.ApplyLayers(procname, addr);
- // Track the top most entry point
- cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
- cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = addr;
- addr = gExtensionForwarders[slot];
+ // Track the top most entry point and return the extension forwarder
+ cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[ext_slot] =
+ cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[ext_slot] = addr;
+ addr = gExtensionForwarders[ext_slot];
}
pthread_mutex_unlock(&sExtensionMapMutex);
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index c11b88e..14ed73d 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -299,14 +299,10 @@
}
void SensorService::setSensorAccess(uid_t uid, bool hasAccess) {
- SortedVector< sp<SensorEventConnection> > activeConnections;
- populateActiveConnections(&activeConnections);
- {
- Mutex::Autolock _l(mLock);
- for (size_t i = 0 ; i < activeConnections.size(); i++) {
- if (activeConnections[i] != nullptr && activeConnections[i]->getUid() == uid) {
- activeConnections[i]->setSensorAccess(hasAccess);
- }
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
+ for (const sp<SensorEventConnection>& conn : connLock.getActiveConnections()) {
+ if (conn->getUid() == uid) {
+ conn->setSensorAccess(hasAccess);
}
}
}
@@ -360,7 +356,7 @@
if (args.size() > 2) {
return INVALID_OPERATION;
}
- Mutex::Autolock _l(mLock);
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
SensorDevice& dev(SensorDevice::getInstance());
if (args.size() == 2 && args[0] == String16("restrict")) {
// If already in restricted mode. Ignore.
@@ -374,7 +370,7 @@
mCurrentOperatingMode = RESTRICTED;
// temporarily stop all sensor direct report and disable sensors
- disableAllSensorsLocked();
+ disableAllSensorsLocked(&connLock);
mWhiteListedPackage.setTo(String8(args[1]));
return status_t(NO_ERROR);
} else if (args.size() == 1 && args[0] == String16("enable")) {
@@ -382,7 +378,7 @@
if (mCurrentOperatingMode == RESTRICTED) {
mCurrentOperatingMode = NORMAL;
// enable sensors and recover all sensor direct report
- enableAllSensorsLocked();
+ enableAllSensorsLocked(&connLock);
}
if (mCurrentOperatingMode == DATA_INJECTION) {
resetToNormalModeLocked();
@@ -473,22 +469,18 @@
result.appendFormat("Sensor Privacy: %s\n",
mSensorPrivacyPolicy->isSensorPrivacyEnabled() ? "enabled" : "disabled");
- result.appendFormat("%zd active connections\n", mActiveConnections.size());
- for (size_t i=0 ; i < mActiveConnections.size() ; i++) {
- sp<SensorEventConnection> connection(mActiveConnections[i].promote());
- if (connection != nullptr) {
- result.appendFormat("Connection Number: %zu \n", i);
- connection->dump(result);
- }
+ const auto& activeConnections = connLock.getActiveConnections();
+ result.appendFormat("%zd active connections\n", activeConnections.size());
+ for (size_t i=0 ; i < activeConnections.size() ; i++) {
+ result.appendFormat("Connection Number: %zu \n", i);
+ activeConnections[i]->dump(result);
}
- result.appendFormat("%zd direct connections\n", mDirectConnections.size());
- for (size_t i = 0 ; i < mDirectConnections.size() ; i++) {
- sp<SensorDirectConnection> connection(mDirectConnections[i].promote());
- if (connection != nullptr) {
- result.appendFormat("Direct connection %zu:\n", i);
- connection->dump(result);
- }
+ const auto& directConnections = connLock.getDirectConnections();
+ result.appendFormat("%zd direct connections\n", directConnections.size());
+ for (size_t i = 0 ; i < directConnections.size() ; i++) {
+ result.appendFormat("Direct connection %zu:\n", i);
+ directConnections[i]->dump(result);
}
result.appendFormat("Previous Registrations:\n");
@@ -515,17 +507,14 @@
}
void SensorService::disableAllSensors() {
- Mutex::Autolock _l(mLock);
- disableAllSensorsLocked();
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
+ disableAllSensorsLocked(&connLock);
}
-void SensorService::disableAllSensorsLocked() {
+void SensorService::disableAllSensorsLocked(ConnectionSafeAutolock* connLock) {
SensorDevice& dev(SensorDevice::getInstance());
- for (auto &i : mDirectConnections) {
- sp<SensorDirectConnection> connection(i.promote());
- if (connection != nullptr) {
- connection->stopAll(true /* backupRecord */);
- }
+ for (const sp<SensorDirectConnection>& connection : connLock->getDirectConnections()) {
+ connection->stopAll(true /* backupRecord */);
}
dev.disableAllSensors();
// Clear all pending flush connections for all active sensors. If one of the active
@@ -537,11 +526,11 @@
}
void SensorService::enableAllSensors() {
- Mutex::Autolock _l(mLock);
- enableAllSensorsLocked();
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
+ enableAllSensorsLocked(&connLock);
}
-void SensorService::enableAllSensorsLocked() {
+void SensorService::enableAllSensorsLocked(ConnectionSafeAutolock* connLock) {
// sensors should only be enabled if the operating state is not restricted and sensor
// privacy is not enabled.
if (mCurrentOperatingMode == RESTRICTED || mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
@@ -552,14 +541,12 @@
}
SensorDevice& dev(SensorDevice::getInstance());
dev.enableAllSensors();
- for (auto &i : mDirectConnections) {
- sp<SensorDirectConnection> connection(i.promote());
- if (connection != nullptr) {
- connection->recoverAll();
- }
+ for (const sp<SensorDirectConnection>& connection : connLock->getDirectConnections()) {
+ connection->recoverAll();
}
}
+
// NOTE: This is a remote API - make sure all args are validated
status_t SensorService::shellCommand(int in, int out, int err, Vector<String16>& args) {
if (!checkCallingPermission(sManageSensorsPermission, nullptr, nullptr)) {
@@ -734,17 +721,8 @@
for (int i = 0; i < count; i++) {
mSensorEventBuffer[i].flags = 0;
}
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
- // Make a copy of the connection vector as some connections may be removed during the course
- // of this loop (especially when one-shot sensor events are present in the sensor_event
- // buffer). Promote all connections to StrongPointers before the lock is acquired. If the
- // destructor of the sp gets called when the lock is acquired, it may result in a deadlock
- // as ~SensorEventConnection() needs to acquire mLock again for cleanup. So copy all the
- // strongPointers to a vector before the lock is acquired.
- SortedVector< sp<SensorEventConnection> > activeConnections;
- populateActiveConnections(&activeConnections);
-
- Mutex::Autolock _l(mLock);
// Poll has returned. Hold a wakelock if one of the events is from a wake up sensor. The
// rest of this loop is under a critical section protected by mLock. Acquiring a wakeLock,
// sending events to clients (incrementing SensorEventConnection::mWakeLockRefCount) should
@@ -818,6 +796,10 @@
}
}
+ // Cache the list of active connections, since we use it in multiple places below but won't
+ // modify it here
+ const std::vector<sp<SensorEventConnection>> activeConnections = connLock.getActiveConnections();
+
for (int i = 0; i < count; ++i) {
// Map flush_complete_events in the buffer to SensorEventConnections which called flush
// on the hardware sensor. mapFlushEventsToConnections[i] will be the
@@ -869,11 +851,8 @@
ALOGE("Dynamic sensor release error.");
}
- size_t numConnections = activeConnections.size();
- for (size_t i=0 ; i < numConnections; ++i) {
- if (activeConnections[i] != nullptr) {
- activeConnections[i]->removeSensor(handle);
- }
+ for (const sp<SensorEventConnection>& connection : activeConnections) {
+ connection->removeSensor(handle);
}
}
}
@@ -882,18 +861,14 @@
// Send our events to clients. Check the state of wake lock for each client and release the
// lock if none of the clients need it.
bool needsWakeLock = false;
- size_t numConnections = activeConnections.size();
- for (size_t i=0 ; i < numConnections; ++i) {
- if (activeConnections[i] != nullptr) {
- activeConnections[i]->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,
- mMapFlushEventsToConnections);
- needsWakeLock |= activeConnections[i]->needsWakeLock();
- // If the connection has one-shot sensors, it may be cleaned up after first trigger.
- // Early check for one-shot sensors.
- if (activeConnections[i]->hasOneShotSensors()) {
- cleanupAutoDisabledSensorLocked(activeConnections[i], mSensorEventBuffer,
- count);
- }
+ for (const sp<SensorEventConnection>& connection : activeConnections) {
+ connection->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,
+ mMapFlushEventsToConnections);
+ needsWakeLock |= connection->needsWakeLock();
+ // If the connection has one-shot sensors, it may be cleaned up after first trigger.
+ // Early check for one-shot sensors.
+ if (connection->hasOneShotSensors()) {
+ cleanupAutoDisabledSensorLocked(connection, mSensorEventBuffer, count);
}
}
@@ -912,17 +887,11 @@
}
void SensorService::resetAllWakeLockRefCounts() {
- SortedVector< sp<SensorEventConnection> > activeConnections;
- populateActiveConnections(&activeConnections);
- {
- Mutex::Autolock _l(mLock);
- for (size_t i=0 ; i < activeConnections.size(); ++i) {
- if (activeConnections[i] != nullptr) {
- activeConnections[i]->resetWakeLockRefCount();
- }
- }
- setWakeLockAcquiredLocked(false);
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
+ for (const sp<SensorEventConnection>& connection : connLock.getActiveConnections()) {
+ connection->resetWakeLockRefCount();
}
+ setWakeLockAcquiredLocked(false);
}
void SensorService::setWakeLockAcquiredLocked(bool acquire) {
@@ -1144,9 +1113,7 @@
sp<SensorEventConnection> result(new SensorEventConnection(this, uid, connPackageName,
requestedMode == DATA_INJECTION, connOpPackageName, hasSensorAccess));
if (requestedMode == DATA_INJECTION) {
- if (mActiveConnections.indexOf(result) < 0) {
- mActiveConnections.add(result);
- }
+ mConnectionHolder.addEventConnectionIfNotPresent(result);
// Add the associated file descriptor to the Looper for polling whenever there is data to
// be injected.
result->updateLooperRegistration(mLooper);
@@ -1162,7 +1129,7 @@
sp<ISensorEventConnection> SensorService::createSensorDirectConnection(
const String16& opPackageName, uint32_t size, int32_t type, int32_t format,
const native_handle *resource) {
- Mutex::Autolock _l(mLock);
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
// No new direct connections are allowed when sensor privacy is enabled
if (mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
@@ -1190,9 +1157,8 @@
}
// check for duplication
- for (auto &i : mDirectConnections) {
- sp<SensorDirectConnection> connection(i.promote());
- if (connection != nullptr && connection->isEquivalent(&mem)) {
+ for (const sp<SensorDirectConnection>& connection : connLock.getDirectConnections()) {
+ if (connection->isEquivalent(&mem)) {
ALOGE("Duplicate create channel request for the same share memory");
return nullptr;
}
@@ -1229,7 +1195,7 @@
return nullptr;
}
- SensorDirectConnection* conn = nullptr;
+ sp<SensorDirectConnection> conn;
SensorDevice& dev(SensorDevice::getInstance());
int channelHandle = dev.registerDirectChannel(&mem);
@@ -1246,7 +1212,7 @@
} else {
// add to list of direct connections
// sensor service should never hold pointer or sp of SensorDirectConnection object.
- mDirectConnections.add(wp<SensorDirectConnection>(conn));
+ mConnectionHolder.addDirectConnection(conn);
}
return conn;
}
@@ -1358,7 +1324,7 @@
}
void SensorService::cleanupConnection(SensorEventConnection* c) {
- Mutex::Autolock _l(mLock);
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
const wp<SensorEventConnection> connection(c);
size_t size = mActiveSensors.size();
ALOGD_IF(DEBUG_CONNECTIONS, "%zu active sensors", size);
@@ -1391,10 +1357,10 @@
}
}
c->updateLooperRegistration(mLooper);
- mActiveConnections.remove(connection);
+ mConnectionHolder.removeEventConnection(connection);
BatteryService::cleanup(c->getUid());
if (c->needsWakeLock()) {
- checkWakeLockStateLocked();
+ checkWakeLockStateLocked(&connLock);
}
{
@@ -1414,7 +1380,7 @@
SensorDevice& dev(SensorDevice::getInstance());
dev.unregisterDirectChannel(c->getHalChannelHandle());
- mDirectConnections.remove(c);
+ mConnectionHolder.removeDirectConnection(c);
}
sp<SensorInterface> SensorService::getSensorInterfaceFromHandle(int handle) const {
@@ -1433,7 +1399,7 @@
return BAD_VALUE;
}
- Mutex::Autolock _l(mLock);
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
if (mCurrentOperatingMode != NORMAL
&& !isWhiteListedPackage(connection->getPackageName())) {
return INVALID_OPERATION;
@@ -1484,7 +1450,7 @@
}
connection->sendEvents(&event, 1, nullptr);
if (!connection->needsWakeLock() && mWakeLockAcquired) {
- checkWakeLockStateLocked();
+ checkWakeLockStateLocked(&connLock);
}
}
}
@@ -1497,9 +1463,7 @@
BatteryService::enableSensor(connection->getUid(), handle);
// the sensor was added (which means it wasn't already there)
// so, see if this connection becomes active
- if (mActiveConnections.indexOf(connection) < 0) {
- mActiveConnections.add(connection);
- }
+ mConnectionHolder.addEventConnectionIfNotPresent(connection);
} else {
ALOGW("sensor %08x already enabled in connection %p (ignoring)",
handle, connection.get());
@@ -1603,7 +1567,7 @@
}
if (connection->hasAnySensor() == false) {
connection->updateLooperRegistration(mLooper);
- mActiveConnections.remove(connection);
+ mConnectionHolder.removeEventConnection(connection);
}
// see if this sensor becomes inactive
if (rec->removeConnection(connection)) {
@@ -1762,22 +1726,19 @@
}
void SensorService::checkWakeLockState() {
- Mutex::Autolock _l(mLock);
- checkWakeLockStateLocked();
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
+ checkWakeLockStateLocked(&connLock);
}
-void SensorService::checkWakeLockStateLocked() {
+void SensorService::checkWakeLockStateLocked(ConnectionSafeAutolock* connLock) {
if (!mWakeLockAcquired) {
return;
}
bool releaseLock = true;
- for (size_t i=0 ; i<mActiveConnections.size() ; i++) {
- sp<SensorEventConnection> connection(mActiveConnections[i].promote());
- if (connection != nullptr) {
- if (connection->needsWakeLock()) {
- releaseLock = false;
- break;
- }
+ for (const sp<SensorEventConnection>& connection : connLock->getActiveConnections()) {
+ if (connection->needsWakeLock()) {
+ releaseLock = false;
+ break;
}
}
if (releaseLock) {
@@ -1793,17 +1754,6 @@
}
}
-void SensorService::populateActiveConnections(
- SortedVector< sp<SensorEventConnection> >* activeConnections) {
- Mutex::Autolock _l(mLock);
- for (size_t i=0 ; i < mActiveConnections.size(); ++i) {
- sp<SensorEventConnection> connection(mActiveConnections[i].promote());
- if (connection != nullptr) {
- activeConnections->add(connection);
- }
- }
-}
-
bool SensorService::isWhiteListedPackage(const String8& packageName) {
return (packageName.contains(mWhiteListedPackage.string()));
}
@@ -1938,4 +1888,62 @@
}
return binder::Status::ok();
}
-}; // namespace android
+
+SensorService::ConnectionSafeAutolock::ConnectionSafeAutolock(
+ SensorService::SensorConnectionHolder& holder, Mutex& mutex)
+ : mConnectionHolder(holder), mAutolock(mutex) {}
+
+template<typename ConnectionType>
+const std::vector<sp<ConnectionType>>& SensorService::ConnectionSafeAutolock::getConnectionsHelper(
+ const SortedVector<wp<ConnectionType>>& connectionList,
+ std::vector<std::vector<sp<ConnectionType>>>* referenceHolder) {
+ referenceHolder->emplace_back();
+ std::vector<sp<ConnectionType>>& connections = referenceHolder->back();
+ for (const wp<ConnectionType>& weakConnection : connectionList){
+ sp<ConnectionType> connection = weakConnection.promote();
+ if (connection != nullptr) {
+ connections.push_back(std::move(connection));
+ }
+ }
+ return connections;
+}
+
+const std::vector<sp<SensorService::SensorEventConnection>>&
+ SensorService::ConnectionSafeAutolock::getActiveConnections() {
+ return getConnectionsHelper(mConnectionHolder.mActiveConnections,
+ &mReferencedActiveConnections);
+}
+
+const std::vector<sp<SensorService::SensorDirectConnection>>&
+ SensorService::ConnectionSafeAutolock::getDirectConnections() {
+ return getConnectionsHelper(mConnectionHolder.mDirectConnections,
+ &mReferencedDirectConnections);
+}
+
+void SensorService::SensorConnectionHolder::addEventConnectionIfNotPresent(
+ const sp<SensorService::SensorEventConnection>& connection) {
+ if (mActiveConnections.indexOf(connection) < 0) {
+ mActiveConnections.add(connection);
+ }
+}
+
+void SensorService::SensorConnectionHolder::removeEventConnection(
+ const wp<SensorService::SensorEventConnection>& connection) {
+ mActiveConnections.remove(connection);
+}
+
+void SensorService::SensorConnectionHolder::addDirectConnection(
+ const sp<SensorService::SensorDirectConnection>& connection) {
+ mDirectConnections.add(connection);
+}
+
+void SensorService::SensorConnectionHolder::removeDirectConnection(
+ const wp<SensorService::SensorDirectConnection>& connection) {
+ mDirectConnections.remove(connection);
+}
+
+SensorService::ConnectionSafeAutolock SensorService::SensorConnectionHolder::lock(Mutex& mutex) {
+ return ConnectionSafeAutolock(*this, mutex);
+}
+
+} // namespace android
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index e6ec96d..060b5eb 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -20,6 +20,7 @@
#include "SensorList.h"
#include "RecentEventLogger.h"
+#include <android-base/macros.h>
#include <binder/AppOpsManager.h>
#include <binder/BinderService.h>
#include <binder/IUidObserver.h>
@@ -42,6 +43,7 @@
#include <sys/types.h>
#include <unordered_map>
#include <unordered_set>
+#include <vector>
#if __clang__
// Clang warns about SensorEventConnection::dump hiding BBinder::dump. The cause isn't fixable
@@ -95,10 +97,67 @@
friend class BinderService<SensorService>;
// nested class/struct for internal use
- class SensorRecord;
+ class ConnectionSafeAutolock;
+ class SensorConnectionHolder;
class SensorEventAckReceiver;
+ class SensorRecord;
class SensorRegistrationInfo;
+ // Promoting a SensorEventConnection or SensorDirectConnection from wp to sp must be done with
+ // mLock held, but destroying that sp must be done unlocked to avoid a race condition that
+ // causes a deadlock (remote dies while we hold a local sp, then our decStrong() call invokes
+ // the dtor -> cleanupConnection() tries to re-lock the mutex). This class ensures safe usage
+ // by wrapping a Mutex::Autolock on SensorService's mLock, plus vectors that hold promoted sp<>
+ // references until the lock is released, when they are safely destroyed.
+ // All read accesses to the connection lists in mConnectionHolder must be done via this class.
+ class ConnectionSafeAutolock final {
+ public:
+ // Returns a list of non-null promoted connection references
+ const std::vector<sp<SensorEventConnection>>& getActiveConnections();
+ const std::vector<sp<SensorDirectConnection>>& getDirectConnections();
+
+ private:
+ // Constructed via SensorConnectionHolder::lock()
+ friend class SensorConnectionHolder;
+ explicit ConnectionSafeAutolock(SensorConnectionHolder& holder, Mutex& mutex);
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ConnectionSafeAutolock);
+
+ // NOTE: Order of these members is important, as the destructor for non-static members
+ // get invoked in the reverse order of their declaration. Here we are relying on the
+ // Autolock to be destroyed *before* the vectors, so the sp<> objects are destroyed without
+ // the lock held, which avoids the deadlock.
+ SensorConnectionHolder& mConnectionHolder;
+ std::vector<std::vector<sp<SensorEventConnection>>> mReferencedActiveConnections;
+ std::vector<std::vector<sp<SensorDirectConnection>>> mReferencedDirectConnections;
+ Mutex::Autolock mAutolock;
+
+ template<typename ConnectionType>
+ const std::vector<sp<ConnectionType>>& getConnectionsHelper(
+ const SortedVector<wp<ConnectionType>>& connectionList,
+ std::vector<std::vector<sp<ConnectionType>>>* referenceHolder);
+ };
+
+ // Encapsulates the collection of active SensorEventConection and SensorDirectConnection
+ // references. Write access is done through this class with mLock held, but all read access
+ // must be routed through ConnectionSafeAutolock.
+ class SensorConnectionHolder {
+ public:
+ void addEventConnectionIfNotPresent(const sp<SensorEventConnection>& connection);
+ void removeEventConnection(const wp<SensorEventConnection>& connection);
+
+ void addDirectConnection(const sp<SensorDirectConnection>& connection);
+ void removeDirectConnection(const wp<SensorDirectConnection>& connection);
+
+ // Pass in the mutex that protects this connection holder; acquires the lock and returns an
+ // object that can be used to safely read the lists of connections
+ ConnectionSafeAutolock lock(Mutex& mutex);
+
+ private:
+ friend class ConnectionSafeAutolock;
+ SortedVector< wp<SensorEventConnection> > mActiveConnections;
+ SortedVector< wp<SensorDirectConnection> > mDirectConnections;
+ };
+
// If accessing a sensor we need to make sure the UID has access to it. If
// the app UID is idle then it cannot access sensors and gets no trigger
// events, no on-change events, flush event behavior does not change, and
@@ -250,7 +309,7 @@
// method checks whether all the events from these wake up sensors have been delivered to the
// corresponding applications, if yes the wakelock is released.
void checkWakeLockState();
- void checkWakeLockStateLocked();
+ void checkWakeLockStateLocked(ConnectionSafeAutolock* connLock);
bool isWakeLockAcquired();
bool isWakeUpSensorEvent(const sensors_event_t& event) const;
@@ -268,10 +327,6 @@
// Send events from the event cache for this particular connection.
void sendEventsFromCache(const sp<SensorEventConnection>& connection);
- // Promote all weak referecences in mActiveConnections vector to strong references and add them
- // to the output vector.
- void populateActiveConnections( SortedVector< sp<SensorEventConnection> >* activeConnections);
-
// If SensorService is operating in RESTRICTED mode, only select whitelisted packages are
// allowed to register for or call flush on sensors. Typically only cts test packages are
// allowed.
@@ -306,10 +361,10 @@
// temporarily stops all active direct connections and disables all sensors
void disableAllSensors();
- void disableAllSensorsLocked();
+ void disableAllSensorsLocked(ConnectionSafeAutolock* connLock);
// restarts the previously stopped direct connections and enables all sensors
void enableAllSensors();
- void enableAllSensorsLocked();
+ void enableAllSensorsLocked(ConnectionSafeAutolock* connLock);
static uint8_t sHmacGlobalKey[128];
static bool sHmacGlobalKeyIsValid;
@@ -327,12 +382,13 @@
mutable Mutex mLock;
DefaultKeyedVector<int, SensorRecord*> mActiveSensors;
std::unordered_set<int> mActiveVirtualSensors;
- SortedVector< wp<SensorEventConnection> > mActiveConnections;
+ SensorConnectionHolder mConnectionHolder;
bool mWakeLockAcquired;
sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
+ // WARNING: these SensorEventConnection instances must not be promoted to sp, except via
+ // modification to add support for them in ConnectionSafeAutolock
wp<const SensorEventConnection> * mMapFlushEventsToConnections;
std::unordered_map<int, SensorServiceUtil::RecentEventLogger*> mRecentEvent;
- SortedVector< wp<SensorDirectConnection> > mDirectConnections;
Mode mCurrentOperatingMode;
// This packagaName is set when SensorService is in RESTRICTED or DATA_INJECTION mode. Only
diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp
index 7927fa9..e33bedb 100644
--- a/services/surfaceflinger/ContainerLayer.cpp
+++ b/services/surfaceflinger/ContainerLayer.cpp
@@ -35,11 +35,7 @@
return false;
}
-bool ContainerLayer::canReceiveInput() const {
- return !isHiddenByPolicy();
-}
void ContainerLayer::setPerFrameData(const sp<const DisplayDevice>&, const ui::Transform&,
const Rect&, int32_t, const ui::Dataspace) {}
-
} // namespace android
diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h
index 7222a3e..e6dbfcc 100644
--- a/services/surfaceflinger/ContainerLayer.h
+++ b/services/surfaceflinger/ContainerLayer.h
@@ -31,8 +31,6 @@
const char* getTypeId() const override { return "ContainerLayer"; }
bool isVisible() const override;
- bool canReceiveInput() const override;
-
void setPerFrameData(const sp<const DisplayDevice>& display, const ui::Transform& transform,
const Rect& viewport, int32_t supportedPerFrameMetadata,
const ui::Dataspace targetDataspace) override;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index d6e86eb..44f3eae 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2048,7 +2048,7 @@
InputWindowInfo info = mDrawingState.inputInfo;
if (info.displayId == ADISPLAY_ID_NONE) {
- info.displayId = mDrawingState.layerStack;
+ info.displayId = getLayerStack();
}
ui::Transform t = getTransform();
@@ -2129,7 +2129,7 @@
}
bool Layer::canReceiveInput() const {
- return isVisible();
+ return !isHiddenByPolicy();
}
compositionengine::OutputLayer* Layer::findOutputLayerForDisplay(
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h
index a733781..17afdda 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.h
+++ b/services/surfaceflinger/Scheduler/LayerInfo.h
@@ -109,7 +109,7 @@
bool isLowActivityLayer() const {
// We want to make sure that we received more than two frames from the layer
// in order to check low activity.
- if (mElements.size() < 2) {
+ if (mElements.size() < scheduler::LOW_ACTIVITY_BUFFERS + 1) {
return false;
}
@@ -118,7 +118,8 @@
// Check the frame before last to determine whether there is low activity.
// If that frame is older than LOW_ACTIVITY_EPSILON_NS, the layer is sending
// infrequent updates.
- if (mElements.at(mElements.size() - 2) < obsoleteEpsilon) {
+ if (mElements.at(mElements.size() - (scheduler::LOW_ACTIVITY_BUFFERS + 1)) <
+ obsoleteEpsilon) {
return true;
}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 5a98232..f8bd958 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -567,9 +567,13 @@
}
// Content detection is on, find the appropriate refresh rate with minimal error
- // TODO(b/139751853): Scan allowed refresh rates only (SurfaceFlinger::mAllowedDisplayConfigs)
- auto iter = min_element(mRefreshRateConfigs.getRefreshRates().cbegin(),
- mRefreshRateConfigs.getRefreshRates().cend(),
+ auto begin = mRefreshRateConfigs.getRefreshRates().cbegin();
+
+ // Skip POWER_SAVING config as it is not a real config
+ if (begin->first == RefreshRateType::POWER_SAVING) {
+ ++begin;
+ }
+ auto iter = min_element(begin, mRefreshRateConfigs.getRefreshRates().cend(),
[rate = mContentRefreshRate](const auto& l, const auto& r) -> bool {
return std::abs(l.second->fps - static_cast<float>(rate)) <
std::abs(r.second->fps - static_cast<float>(rate));
diff --git a/services/surfaceflinger/Scheduler/SchedulerUtils.h b/services/surfaceflinger/Scheduler/SchedulerUtils.h
index ced1899..ac10f83 100644
--- a/services/surfaceflinger/Scheduler/SchedulerUtils.h
+++ b/services/surfaceflinger/Scheduler/SchedulerUtils.h
@@ -42,9 +42,11 @@
// or waiting idle in messaging app, when cursor is blinking.
static constexpr std::chrono::nanoseconds OBSOLETE_TIME_EPSILON_NS = 1200ms;
-// Layer is considered low activity if the buffers come more than LOW_ACTIVITY_EPSILON_NS
-// apart. This is helping SF to vote for lower refresh rates when there is not activity
+// Layer is considered low activity if the LOW_ACTIVITY_BUFFERS buffers come more than
+// LOW_ACTIVITY_EPSILON_NS apart.
+// This is helping SF to vote for lower refresh rates when there is not activity
// in screen.
+static constexpr int LOW_ACTIVITY_BUFFERS = 2;
static constexpr std::chrono::nanoseconds LOW_ACTIVITY_EPSILON_NS = 250ms;
// Calculates the statistical mean (average) in the data structure (array, vector). The
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ffb7012..9efa63c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1681,7 +1681,8 @@
setTransactionFlags(eDisplayTransactionNeeded);
}
-bool SurfaceFlinger::previousFrameMissed() NO_THREAD_SAFETY_ANALYSIS {
+bool SurfaceFlinger::previousFrameMissed(int graceTimeMs) NO_THREAD_SAFETY_ANALYSIS {
+ ATRACE_CALL();
// We are storing the last 2 present fences. If sf's phase offset is to be
// woken up before the actual vsync but targeting the next vsync, we need to check
// fence N-2
@@ -1690,7 +1691,15 @@
? mPreviousPresentFences[0]
: mPreviousPresentFences[1];
- return fence != Fence::NO_FENCE && (fence->getStatus() == Fence::Status::Unsignaled);
+ if (fence == Fence::NO_FENCE) {
+ return false;
+ }
+
+ if (graceTimeMs > 0 && fence->getStatus() == Fence::Status::Unsignaled) {
+ fence->wait(graceTimeMs);
+ }
+
+ return (fence->getStatus() == Fence::Status::Unsignaled);
}
void SurfaceFlinger::populateExpectedPresentTime() NO_THREAD_SAFETY_ANALYSIS {
@@ -1713,7 +1722,15 @@
// seeing this same value.
populateExpectedPresentTime();
- bool frameMissed = previousFrameMissed();
+ // When Backpressure propagation is enabled we want to give a small grace period
+ // for the present fence to fire instead of just giving up on this frame to handle cases
+ // where present fence is just about to get signaled.
+ const int graceTimeForPresentFenceMs =
+ (mPropagateBackpressure &&
+ (mPropagateBackpressureClientComposition || !mHadClientComposition))
+ ? 1
+ : 0;
+ bool frameMissed = previousFrameMissed(graceTimeForPresentFenceMs);
bool hwcFrameMissed = mHadDeviceComposition && frameMissed;
bool gpuFrameMissed = mHadClientComposition && frameMissed;
ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
@@ -6225,7 +6242,7 @@
return NO_ERROR;
}
- postMessageSync(new LambdaMessage([&]() NO_THREAD_SAFETY_ANALYSIS {
+ postMessageSync(new LambdaMessage([&]() {
const auto display = getDisplayDeviceLocked(displayToken);
if (!display) {
ALOGE("Attempt to set allowed display configs for invalid display token %p",
@@ -6233,6 +6250,7 @@
} else if (display->isVirtual()) {
ALOGW("Attempt to set allowed display configs for virtual display");
} else {
+ Mutex::Autolock lock(mStateLock);
setAllowedDisplayConfigsInternal(display, allowedConfigs);
}
}));
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index a59a1e0..2718e0e 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -851,7 +851,7 @@
return hwcDisplayId ? getHwComposer().toPhysicalDisplayId(*hwcDisplayId) : std::nullopt;
}
- bool previousFrameMissed();
+ bool previousFrameMissed(int graceTimeMs = 0);
void setVsyncEnabledInHWC(DisplayId displayId, HWC2::Vsync enabled);
/*