Merge "Plumb through Output::getSkipColorTransform() into CachedSet, to match the behavior in Output::composeSurfaces()."
diff --git a/cmds/atrace/atrace_userdebug.rc b/cmds/atrace/atrace_userdebug.rc
index 9186514..fa7be18 100644
--- a/cmds/atrace/atrace_userdebug.rc
+++ b/cmds/atrace/atrace_userdebug.rc
@@ -18,3 +18,9 @@
chmod 0666 /sys/kernel/tracing/events/filemap/enable
chmod 0666 /sys/kernel/debug/tracing/events/filemap/enable
+ # Allow traced_probes to use the raw_syscall filters to trace only a subset
+ # of syscalls.
+ chmod 0666 /sys/kernel/tracing/events/raw_syscalls/sys_enter/filter
+ chmod 0666 /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/filter
+ chmod 0666 /sys/kernel/tracing/events/raw_syscalls/sys_exit/filter
+ chmod 0666 /sys/kernel/debug/tracing/events/raw_syscalls/sys_exit/filter
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index edeb2a4..fd879c6 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -90,27 +90,11 @@
cc_fuzz {
name: "servicemanager_fuzzer",
- defaults: ["servicemanager_defaults"],
- host_supported: true,
- static_libs: [
- "libbase",
- "libbinder_random_parcel",
- "libcutils",
+ defaults: [
+ "servicemanager_defaults",
+ "service_fuzzer_defaults",
],
- target: {
- android: {
- shared_libs: [
- "libbinder_ndk",
- "libbinder",
- ],
- },
- host: {
- static_libs: [
- "libbinder_ndk",
- "libbinder",
- ],
- },
- },
+ host_supported: true,
srcs: ["ServiceManagerFuzzer.cpp"],
fuzz_config: {
libfuzzer_options: [
diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp
index 3f7c7d6..44235cc 100644
--- a/cmds/surfacereplayer/replayer/Replayer.cpp
+++ b/cmds/surfacereplayer/replayer/Replayer.cpp
@@ -464,7 +464,6 @@
void Replayer::setSize(SurfaceComposerClient::Transaction& t,
layer_id id, const SizeChange& sc) {
ALOGV("Layer %d: Setting Size -- w=%u, h=%u", id, sc.w(), sc.h());
- t.setSize(mLayers[id], sc.w(), sc.h());
}
void Replayer::setLayer(SurfaceComposerClient::Transaction& t,
diff --git a/include/ftl/small_map.h b/include/ftl/small_map.h
index 5217e76..49cde7f 100644
--- a/include/ftl/small_map.h
+++ b/include/ftl/small_map.h
@@ -17,11 +17,11 @@
#pragma once
#include <ftl/initializer_list.h>
+#include <ftl/optional.h>
#include <ftl/small_vector.h>
#include <algorithm>
#include <functional>
-#include <optional>
#include <type_traits>
#include <utility>
@@ -47,7 +47,7 @@
// assert(!map.dynamic());
//
// assert(map.contains(123));
-// assert(map.get(42, [](const std::string& s) { return s.size(); }) == 3u);
+// assert(map.get(42).transform([](const std::string& s) { return s.size(); }) == 3u);
//
// const auto opt = map.get(-1);
// assert(opt);
@@ -59,7 +59,7 @@
// map.emplace_or_replace(0, "vanilla", 2u, 3u);
// assert(map.dynamic());
//
-// assert(map == SmallMap(ftl::init::map(-1, "xyz")(0, "nil")(42, "???")(123, "abc")));
+// assert(map == SmallMap(ftl::init::map(-1, "xyz"sv)(0, "nil"sv)(42, "???"sv)(123, "abc"sv)));
//
template <typename K, typename V, std::size_t N, typename KeyEqual = std::equal_to<K>>
class SmallMap final {
@@ -123,9 +123,7 @@
const_iterator cend() const { return map_.cend(); }
// Returns whether a mapping exists for the given key.
- bool contains(const key_type& key) const {
- return get(key, [](const mapped_type&) {});
- }
+ bool contains(const key_type& key) const { return get(key).has_value(); }
// Returns a reference to the value for the given key, or std::nullopt if the key was not found.
//
@@ -139,44 +137,22 @@
// ref.get() = 'D';
// assert(d == 'D');
//
- auto get(const key_type& key) const -> std::optional<std::reference_wrapper<const mapped_type>> {
- return get(key, [](const mapped_type& v) { return std::cref(v); });
- }
-
- auto get(const key_type& key) -> std::optional<std::reference_wrapper<mapped_type>> {
- return get(key, [](mapped_type& v) { return std::ref(v); });
- }
-
- // Returns the result R of a unary operation F on (a constant or mutable reference to) the value
- // for the given key, or std::nullopt if the key was not found. If F has a return type of void,
- // then the Boolean result indicates whether the key was found.
- //
- // ftl::SmallMap map = ftl::init::map('a', 'x')('b', 'y')('c', 'z');
- //
- // assert(map.get('c', [](char c) { return std::toupper(c); }) == 'Z');
- // assert(map.get('c', [](char& c) { c = std::toupper(c); }));
- //
- template <typename F, typename R = std::invoke_result_t<F, const mapped_type&>>
- auto get(const key_type& key, F f) const
- -> std::conditional_t<std::is_void_v<R>, bool, std::optional<R>> {
- for (auto& [k, v] : *this) {
+ auto get(const key_type& key) const -> Optional<std::reference_wrapper<const mapped_type>> {
+ for (const auto& [k, v] : *this) {
if (KeyEqual{}(k, key)) {
- if constexpr (std::is_void_v<R>) {
- f(v);
- return true;
- } else {
- return f(v);
- }
+ return std::cref(v);
}
}
-
return {};
}
- template <typename F>
- auto get(const key_type& key, F f) {
- return std::as_const(*this).get(
- key, [&f](const mapped_type& v) { return f(const_cast<mapped_type&>(v)); });
+ auto get(const key_type& key) -> Optional<std::reference_wrapper<mapped_type>> {
+ for (auto& [k, v] : *this) {
+ if (KeyEqual{}(k, key)) {
+ return std::ref(v);
+ }
+ }
+ return {};
}
// Returns an iterator to an existing mapping for the given key, or the end() iterator otherwise.
@@ -286,7 +262,7 @@
for (const auto& [k, v] : lhs) {
const auto& lv = v;
- if (!rhs.get(k, [&lv](const auto& rv) { return lv == rv; }).value_or(false)) {
+ if (!rhs.get(k).transform([&lv](const W& rv) { return lv == rv; }).value_or(false)) {
return false;
}
}
diff --git a/include/ftl/unit.h b/include/ftl/unit.h
new file mode 100644
index 0000000..e38230b
--- /dev/null
+++ b/include/ftl/unit.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 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 <type_traits>
+#include <utility>
+
+namespace android::ftl {
+
+// The unit type, and its only value.
+constexpr struct Unit {
+} unit;
+
+constexpr bool operator==(Unit, Unit) {
+ return true;
+}
+
+constexpr bool operator!=(Unit, Unit) {
+ return false;
+}
+
+// Adapts a function object F to return Unit. The return value of F is ignored.
+//
+// As a practical use, the function passed to ftl::Optional<T>::transform is not allowed to return
+// void (cf. https://wg21.link/P0798R8#mapping-functions-returning-void), but may return Unit if
+// only its side effects are meaningful:
+//
+// ftl::Optional opt = "food"s;
+// opt.transform(ftl::unit_fn([](std::string& str) { str.pop_back(); }));
+// assert(opt == "foo"s);
+//
+template <typename F>
+struct UnitFn {
+ F f;
+
+ template <typename... Args>
+ Unit operator()(Args&&... args) {
+ return f(std::forward<Args>(args)...), unit;
+ }
+};
+
+template <typename F>
+constexpr auto unit_fn(F&& f) -> UnitFn<std::decay_t<F>> {
+ return {std::forward<F>(f)};
+}
+
+} // namespace android::ftl
diff --git a/include/input/KeyLayoutMap.h b/include/input/KeyLayoutMap.h
index 1da78aa..a6c696d 100644
--- a/include/input/KeyLayoutMap.h
+++ b/include/input/KeyLayoutMap.h
@@ -78,7 +78,7 @@
std::optional<AxisInfo> mapAxis(int32_t scanCode) const;
const std::string getLoadFileName() const;
// Return pair of sensor type and sensor data index, for the input device abs code
- base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(int32_t absCode);
+ base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(int32_t absCode) const;
virtual ~KeyLayoutMap();
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 6f505b4..66b03b0 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -440,6 +440,7 @@
// This library is intentionally limited to these targets, and it will be removed later.
// Do not expand the visibility.
visibility: [
+ ":__subpackages__",
"//packages/modules/Virtualization:__subpackages__",
],
}
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index b5ea60f..1dc6233 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -202,6 +202,17 @@
proxy->withLock(doWithLock);
}
+sp<IBinder> IBinder::lookupOrCreateWeak(const void* objectID, object_make_func make,
+ const void* makeArgs) {
+ BBinder* local = localBinder();
+ if (local) {
+ return local->lookupOrCreateWeak(objectID, make, makeArgs);
+ }
+ BpBinder* proxy = this->remoteBinder();
+ LOG_ALWAYS_FATAL_IF(proxy == nullptr, "binder object must be either local or remote");
+ return proxy->lookupOrCreateWeak(objectID, make, makeArgs);
+}
+
// ---------------------------------------------------------------------------
class BBinder::RpcServerLink : public IBinder::DeathRecipient {
@@ -378,6 +389,14 @@
doWithLock();
}
+sp<IBinder> BBinder::lookupOrCreateWeak(const void* objectID, object_make_func make,
+ const void* makeArgs) {
+ Extras* e = getOrCreateExtras();
+ LOG_ALWAYS_FATAL_IF(!e, "no memory");
+ AutoMutex _l(e->mLock);
+ return e->mObjects.lookupOrCreateWeak(objectID, make, makeArgs);
+}
+
BBinder* BBinder::localBinder()
{
return this;
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index b6d35ef..d9b7231 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -100,6 +100,36 @@
return value;
}
+namespace {
+struct Tag {
+ wp<IBinder> binder;
+};
+} // namespace
+
+static void cleanWeak(const void* /* id */, void* obj, void* /* cookie */) {
+ delete static_cast<Tag*>(obj);
+}
+
+sp<IBinder> BpBinder::ObjectManager::lookupOrCreateWeak(const void* objectID, object_make_func make,
+ const void* makeArgs) {
+ entry_t& e = mObjects[objectID];
+ if (e.object != nullptr) {
+ if (auto attached = static_cast<Tag*>(e.object)->binder.promote()) {
+ return attached;
+ }
+ } else {
+ e.object = new Tag;
+ LOG_ALWAYS_FATAL_IF(!e.object, "no more memory");
+ }
+ sp<IBinder> newObj = make(makeArgs);
+
+ static_cast<Tag*>(e.object)->binder = newObj;
+ e.cleanupCookie = nullptr;
+ e.func = cleanWeak;
+
+ return newObj;
+}
+
void BpBinder::ObjectManager::kill()
{
const size_t N = mObjects.size();
@@ -516,6 +546,12 @@
doWithLock();
}
+sp<IBinder> BpBinder::lookupOrCreateWeak(const void* objectID, object_make_func make,
+ const void* makeArgs) {
+ AutoMutex _l(mLock);
+ return mObjects.lookupOrCreateWeak(objectID, make, makeArgs);
+}
+
BpBinder* BpBinder::remoteBinder()
{
return this;
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index d347262..8ddfa93 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -484,6 +484,9 @@
mProtocolVersion = oldProtocolVersion;
mConnections = {};
+
+ // clear mStartedSetup so that we can reuse this RpcSession
+ mStartedSetup = false;
});
if (status_t status = connectAndInit({}, false /*incoming*/); status != OK) return status;
diff --git a/libs/binder/RpcTransportTipcAndroid.cpp b/libs/binder/RpcTransportTipcAndroid.cpp
index 79983f4..c82201b 100644
--- a/libs/binder/RpcTransportTipcAndroid.cpp
+++ b/libs/binder/RpcTransportTipcAndroid.cpp
@@ -103,7 +103,10 @@
// read and call readFn as many times as needed to get all the data
status_t ret = fillReadBuffer();
if (ret != OK) {
- return ret;
+ // We need to emulate a Linux read call, which sets errno on
+ // error and returns -1
+ errno = -ret;
+ return -1;
}
ssize_t processSize = 0;
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 46223bb..88d9ca1 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -59,6 +59,8 @@
virtual void* findObject(const void* objectID) const final;
virtual void* detachObject(const void* objectID) final;
void withLock(const std::function<void()>& doWithLock);
+ sp<IBinder> lookupOrCreateWeak(const void* objectID, IBinder::object_make_func make,
+ const void* makeArgs);
virtual BBinder* localBinder();
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 19ad5e6..4172cc5 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -72,6 +72,8 @@
virtual void* findObject(const void* objectID) const final;
virtual void* detachObject(const void* objectID) final;
void withLock(const std::function<void()>& doWithLock);
+ sp<IBinder> lookupOrCreateWeak(const void* objectID, IBinder::object_make_func make,
+ const void* makeArgs);
virtual BpBinder* remoteBinder();
@@ -96,6 +98,8 @@
IBinder::object_cleanup_func func);
void* find(const void* objectID) const;
void* detach(const void* objectID);
+ sp<IBinder> lookupOrCreateWeak(const void* objectID, IBinder::object_make_func make,
+ const void* makeArgs);
void kill();
@@ -104,9 +108,9 @@
ObjectManager& operator=(const ObjectManager&);
struct entry_t {
- void* object;
- void* cleanupCookie;
- IBinder::object_cleanup_func func;
+ void* object = nullptr;
+ void* cleanupCookie = nullptr;
+ IBinder::object_cleanup_func func = nullptr;
};
std::map<const void*, entry_t> mObjects;
diff --git a/libs/binder/include/binder/Delegate.h b/libs/binder/include/binder/Delegate.h
new file mode 100644
index 0000000..8b3fc1c
--- /dev/null
+++ b/libs/binder/include/binder/Delegate.h
@@ -0,0 +1,93 @@
+/*
+ * 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 <binder/IBinder.h>
+
+#ifndef __BIONIC__
+#ifndef __assert
+
+// defined differently by liblog
+#pragma push_macro("LOG_PRI")
+#ifdef LOG_PRI
+#undef LOG_PRI
+#endif
+#include <syslog.h>
+#pragma pop_macro("LOG_PRI")
+
+#define __assert(a, b, c) \
+ do { \
+ syslog(LOG_ERR, a ": " c); \
+ abort(); \
+ } while (false)
+#endif // __assert
+#endif // __BIONIC__
+
+namespace android {
+
+/*
+ * Used to manage AIDL's *Delegator types.
+ * This is used to:
+ * - create a new *Delegator object that delegates to the binder argument.
+ * - or return an existing *Delegator object that already delegates to the
+ * binder argument.
+ * - or return the underlying delegate binder if the binder argument is a
+ * *Delegator itself.
+ *
+ * @param binder - the binder to delegate to or unwrap
+ *
+ * @return pointer to the *Delegator object or the unwrapped binder object
+ */
+template <typename T>
+sp<T> delegate(const sp<T>& binder) {
+ const void* isDelegatorId = &T::descriptor;
+ const void* hasDelegatorId = &T::descriptor + 1;
+ // is binder itself a delegator?
+ if (T::asBinder(binder)->findObject(isDelegatorId)) {
+ if (T::asBinder(binder)->findObject(hasDelegatorId)) {
+ __assert(__FILE__, __LINE__,
+ "This binder has a delegator and is also delegator itself! This is "
+ "likely an unintended mixing of binders.");
+ return nullptr;
+ }
+ // unwrap the delegator
+ return static_cast<typename T::DefaultDelegator*>(binder.get())->getImpl();
+ }
+
+ struct MakeArgs {
+ const sp<T>* binder;
+ const void* id;
+ } makeArgs;
+ makeArgs.binder = &binder;
+ makeArgs.id = isDelegatorId;
+
+ // the binder is not a delegator, so construct one
+ sp<IBinder> newDelegator = T::asBinder(binder)->lookupOrCreateWeak(
+ hasDelegatorId,
+ [](const void* args) -> sp<IBinder> {
+ auto delegator = sp<typename T::DefaultDelegator>::make(
+ *static_cast<const MakeArgs*>(args)->binder);
+ // make sure we know this binder is a delegator by attaching a unique ID
+ (void)delegator->attachObject(static_cast<const MakeArgs*>(args)->id,
+ reinterpret_cast<void*>(0x1), nullptr, nullptr);
+ return delegator;
+ },
+ static_cast<const void*>(&makeArgs));
+ return sp<typename T::DefaultDelegator>::cast(newDelegator);
+}
+
+} // namespace android
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index 43fc5ff..83aaca7 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -284,6 +284,9 @@
virtual BBinder* localBinder();
virtual BpBinder* remoteBinder();
+ typedef sp<IBinder> (*object_make_func)(const void* makeArgs);
+ sp<IBinder> lookupOrCreateWeak(const void* objectID, object_make_func make,
+ const void* makeArgs);
protected:
virtual ~IBinder();
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index c0d4487..0ec6183 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -144,24 +144,6 @@
min_sdk_version: "Tiramisu",
}
-// TODO(b/184872979): remove once the Rust API is created.
-rust_bindgen {
- name: "libbinder_rpc_unstable_bindgen",
- wrapper_src: ":libbinder_rpc_unstable_header",
- crate_name: "binder_rpc_unstable_bindgen",
- visibility: ["//packages/modules/Virtualization:__subpackages__"],
- source_stem: "bindings",
- shared_libs: [
- "libutils",
- ],
- apex_available: [
- "com.android.compos",
- "com.android.uwb",
- "com.android.virt",
- ],
- min_sdk_version: "Tiramisu",
-}
-
rust_test {
name: "libbinder_rs-internal_test",
crate_name: "binder",
@@ -188,13 +170,3 @@
clippy_lints: "none",
lints: "none",
}
-
-rust_test {
- name: "libbinder_rpc_unstable_bindgen_test",
- srcs: [":libbinder_rpc_unstable_bindgen"],
- crate_name: "binder_rpc_unstable_bindgen",
- test_suites: ["general-tests"],
- auto_gen_config: true,
- clippy_lints: "none",
- lints: "none",
-}
diff --git a/libs/binder/rust/rpcbinder/Android.bp b/libs/binder/rust/rpcbinder/Android.bp
new file mode 100644
index 0000000..067ca0d
--- /dev/null
+++ b/libs/binder/rust/rpcbinder/Android.bp
@@ -0,0 +1,50 @@
+rust_library {
+ name: "librpcbinder_rs",
+ crate_name: "rpcbinder",
+ srcs: ["src/lib.rs"],
+ shared_libs: [
+ "libutils",
+ ],
+ rustlibs: [
+ "libbinder_ndk_sys",
+ "libbinder_rpc_unstable_bindgen",
+ "libbinder_rs",
+ "libdowncast_rs",
+ "liblibc",
+ ],
+ apex_available: [
+ "com.android.compos",
+ "com.android.uwb",
+ "com.android.virt",
+ ],
+ min_sdk_version: "Tiramisu",
+}
+
+// TODO(b/184872979): remove once the RPC Binder API is stabilised.
+rust_bindgen {
+ name: "libbinder_rpc_unstable_bindgen",
+ wrapper_src: ":libbinder_rpc_unstable_header",
+ crate_name: "binder_rpc_unstable_bindgen",
+ visibility: [":__subpackages__"],
+ source_stem: "bindings",
+ shared_libs: [
+ "libbinder_rpc_unstable",
+ "libutils",
+ ],
+ apex_available: [
+ "com.android.compos",
+ "com.android.uwb",
+ "com.android.virt",
+ ],
+ min_sdk_version: "Tiramisu",
+}
+
+rust_test {
+ name: "libbinder_rpc_unstable_bindgen_test",
+ srcs: [":libbinder_rpc_unstable_bindgen"],
+ crate_name: "binder_rpc_unstable_bindgen",
+ test_suites: ["general-tests"],
+ auto_gen_config: true,
+ clippy_lints: "none",
+ lints: "none",
+}
diff --git a/libs/binder/rust/rpcbinder/src/client.rs b/libs/binder/rust/rpcbinder/src/client.rs
new file mode 100644
index 0000000..dfc6f06
--- /dev/null
+++ b/libs/binder/rust/rpcbinder/src/client.rs
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+use binder::{
+ unstable_api::{new_spibinder, AIBinder},
+ FromIBinder, SpIBinder, StatusCode, Strong,
+};
+use std::os::{
+ raw::{c_int, c_void},
+ unix::io::RawFd,
+};
+
+/// Connects to an RPC Binder server over vsock.
+pub fn get_vsock_rpc_service(cid: u32, port: u32) -> Option<SpIBinder> {
+ // SAFETY: AIBinder returned by RpcClient has correct reference count, and the ownership can
+ // safely be taken by new_spibinder.
+ unsafe { new_spibinder(binder_rpc_unstable_bindgen::RpcClient(cid, port) as *mut AIBinder) }
+}
+
+/// Connects to an RPC Binder server for a particular interface over vsock.
+pub fn get_vsock_rpc_interface<T: FromIBinder + ?Sized>(
+ cid: u32,
+ port: u32,
+) -> Result<Strong<T>, StatusCode> {
+ interface_cast(get_vsock_rpc_service(cid, port))
+}
+
+/// Connects to an RPC Binder server, using the given callback to get (and take ownership of)
+/// file descriptors already connected to it.
+pub fn get_preconnected_rpc_service(
+ mut request_fd: impl FnMut() -> Option<RawFd>,
+) -> Option<SpIBinder> {
+ // Double reference the factory because trait objects aren't FFI safe.
+ let mut request_fd_ref: RequestFd = &mut request_fd;
+ let param = &mut request_fd_ref as *mut RequestFd as *mut c_void;
+
+ // SAFETY: AIBinder returned by RpcPreconnectedClient has correct reference count, and the
+ // ownership can be safely taken by new_spibinder. RpcPreconnectedClient does not take ownership
+ // of param, only passing it to request_fd_wrapper.
+ unsafe {
+ new_spibinder(binder_rpc_unstable_bindgen::RpcPreconnectedClient(
+ Some(request_fd_wrapper),
+ param,
+ ) as *mut AIBinder)
+ }
+}
+
+type RequestFd<'a> = &'a mut dyn FnMut() -> Option<RawFd>;
+
+unsafe extern "C" fn request_fd_wrapper(param: *mut c_void) -> c_int {
+ // SAFETY: This is only ever called by RpcPreconnectedClient, within the lifetime of the
+ // BinderFdFactory reference, with param being a properly aligned non-null pointer to an
+ // initialized instance.
+ let request_fd_ptr = param as *mut RequestFd;
+ let request_fd = request_fd_ptr.as_mut().unwrap();
+ if let Some(fd) = request_fd() {
+ fd
+ } else {
+ -1
+ }
+}
+
+/// Connects to an RPC Binder server for a particular interface, using the given callback to get
+/// (and take ownership of) file descriptors already connected to it.
+pub fn get_preconnected_rpc_interface<T: FromIBinder + ?Sized>(
+ request_fd: impl FnMut() -> Option<RawFd>,
+) -> Result<Strong<T>, StatusCode> {
+ interface_cast(get_preconnected_rpc_service(request_fd))
+}
+
+fn interface_cast<T: FromIBinder + ?Sized>(
+ service: Option<SpIBinder>,
+) -> Result<Strong<T>, StatusCode> {
+ if let Some(service) = service {
+ FromIBinder::try_from(service)
+ } else {
+ Err(StatusCode::NAME_NOT_FOUND)
+ }
+}
diff --git a/libs/binder/rust/rpcbinder/src/lib.rs b/libs/binder/rust/rpcbinder/src/lib.rs
new file mode 100644
index 0000000..a5eea61
--- /dev/null
+++ b/libs/binder/rust/rpcbinder/src/lib.rs
@@ -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.
+ */
+
+//! API for RPC Binder services.
+
+mod client;
+mod server;
+
+pub use client::{
+ get_preconnected_rpc_interface, get_preconnected_rpc_service, get_vsock_rpc_interface,
+ get_vsock_rpc_service,
+};
+pub use server::{run_rpc_server, run_rpc_server_with_factory};
diff --git a/libs/binder/rust/rpcbinder/src/server.rs b/libs/binder/rust/rpcbinder/src/server.rs
new file mode 100644
index 0000000..d98a439
--- /dev/null
+++ b/libs/binder/rust/rpcbinder/src/server.rs
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+use binder::{unstable_api::AsNative, SpIBinder};
+use std::{os::raw, ptr::null_mut};
+
+/// Runs a binder RPC server, serving the supplied binder service implementation on the given vsock
+/// port.
+///
+/// If and when the server is ready for connections (it is listening on the port), `on_ready` is
+/// called to allow appropriate action to be taken - e.g. to notify clients that they may now
+/// attempt to connect.
+///
+/// The current thread is joined to the binder thread pool to handle incoming messages.
+///
+/// Returns true if the server has shutdown normally, false if it failed in some way.
+pub fn run_rpc_server<F>(service: SpIBinder, port: u32, on_ready: F) -> bool
+where
+ F: FnOnce(),
+{
+ let mut ready_notifier = ReadyNotifier(Some(on_ready));
+ ready_notifier.run_server(service, port)
+}
+
+struct ReadyNotifier<F>(Option<F>)
+where
+ F: FnOnce();
+
+impl<F> ReadyNotifier<F>
+where
+ F: FnOnce(),
+{
+ fn run_server(&mut self, mut service: SpIBinder, port: u32) -> bool {
+ let service = service.as_native_mut() as *mut binder_rpc_unstable_bindgen::AIBinder;
+ let param = self.as_void_ptr();
+
+ // SAFETY: Service ownership is transferring to the server and won't be valid afterward.
+ // Plus the binder objects are threadsafe.
+ // RunRpcServerCallback does not retain a reference to `ready_callback` or `param`; it only
+ // uses them before it returns, which is during the lifetime of `self`.
+ unsafe {
+ binder_rpc_unstable_bindgen::RunRpcServerCallback(
+ service,
+ port,
+ Some(Self::ready_callback),
+ param,
+ )
+ }
+ }
+
+ fn as_void_ptr(&mut self) -> *mut raw::c_void {
+ self as *mut _ as *mut raw::c_void
+ }
+
+ unsafe extern "C" fn ready_callback(param: *mut raw::c_void) {
+ // SAFETY: This is only ever called by `RunRpcServerCallback`, within the lifetime of the
+ // `ReadyNotifier`, with `param` taking the value returned by `as_void_ptr` (so a properly
+ // aligned non-null pointer to an initialized instance).
+ let ready_notifier = param as *mut Self;
+ ready_notifier.as_mut().unwrap().notify()
+ }
+
+ fn notify(&mut self) {
+ if let Some(on_ready) = self.0.take() {
+ on_ready();
+ }
+ }
+}
+
+type RpcServerFactoryRef<'a> = &'a mut (dyn FnMut(u32) -> Option<SpIBinder> + Send + Sync);
+
+/// Runs a binder RPC server, using the given factory function to construct a binder service
+/// implementation for each connection.
+///
+/// The current thread is joined to the binder thread pool to handle incoming messages.
+///
+/// Returns true if the server has shutdown normally, false if it failed in some way.
+pub fn run_rpc_server_with_factory(
+ port: u32,
+ mut factory: impl FnMut(u32) -> Option<SpIBinder> + Send + Sync,
+) -> bool {
+ // Double reference the factory because trait objects aren't FFI safe.
+ // NB: The type annotation is necessary to ensure that we have a `dyn` rather than an `impl`.
+ let mut factory_ref: RpcServerFactoryRef = &mut factory;
+ let context = &mut factory_ref as *mut RpcServerFactoryRef as *mut raw::c_void;
+
+ // SAFETY: `factory_wrapper` is only ever called by `RunRpcServerWithFactory`, with context
+ // taking the pointer value above (so a properly aligned non-null pointer to an initialized
+ // `RpcServerFactoryRef`), within the lifetime of `factory_ref` (i.e. no more calls will be made
+ // after `RunRpcServerWithFactory` returns).
+ unsafe {
+ binder_rpc_unstable_bindgen::RunRpcServerWithFactory(Some(factory_wrapper), context, port)
+ }
+}
+
+unsafe extern "C" fn factory_wrapper(
+ cid: u32,
+ context: *mut raw::c_void,
+) -> *mut binder_rpc_unstable_bindgen::AIBinder {
+ // SAFETY: `context` was created from an `&mut RpcServerFactoryRef` by
+ // `run_rpc_server_with_factory`, and we are still within the lifetime of the value it is
+ // pointing to.
+ let factory_ptr = context as *mut RpcServerFactoryRef;
+ let factory = factory_ptr.as_mut().unwrap();
+
+ if let Some(mut service) = factory(cid) {
+ service.as_native_mut() as *mut binder_rpc_unstable_bindgen::AIBinder
+ } else {
+ null_mut()
+ }
+}
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index d7c6d49..1babfd5 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -684,3 +684,37 @@
],
test_suites: ["general-tests"],
}
+
+cc_defaults {
+ name: "service_fuzzer_defaults",
+ static_libs: [
+ "libbase",
+ "libbinder_random_parcel",
+ "libcutils",
+ ],
+ target: {
+ android: {
+ shared_libs: [
+ "libbinder_ndk",
+ "libbinder",
+ "libutils",
+ ],
+ },
+ host: {
+ static_libs: [
+ "libbinder_ndk",
+ "libbinder",
+ "libutils",
+ ],
+ },
+ darwin: {
+ enabled: false,
+ },
+ },
+ fuzz_config: {
+ cc: [
+ "smoreland@google.com",
+ "waghpawan@google.com",
+ ],
+ },
+}
diff --git a/libs/binder/tests/binderBinderUnitTest.cpp b/libs/binder/tests/binderBinderUnitTest.cpp
index ce2770f..b6aed0d 100644
--- a/libs/binder/tests/binderBinderUnitTest.cpp
+++ b/libs/binder/tests/binderBinderUnitTest.cpp
@@ -15,10 +15,11 @@
*/
#include <binder/Binder.h>
-#include <binder/IBinder.h>
+#include <binder/IInterface.h>
#include <gtest/gtest.h>
using android::BBinder;
+using android::IBinder;
using android::OK;
using android::sp;
@@ -48,3 +49,49 @@
binder->setExtension(ext);
EXPECT_EQ(ext, binder->getExtension());
}
+
+struct MyCookie {
+ bool* deleted;
+};
+
+class UniqueBinder : public BBinder {
+public:
+ UniqueBinder(const void* c) : cookie(reinterpret_cast<const MyCookie*>(c)) {
+ *cookie->deleted = false;
+ }
+ ~UniqueBinder() { *cookie->deleted = true; }
+ const MyCookie* cookie;
+};
+
+static sp<IBinder> make(const void* arg) {
+ return sp<UniqueBinder>::make(arg);
+}
+
+TEST(Binder, LookupOrCreateWeak) {
+ auto binder = sp<BBinder>::make();
+ bool deleted;
+ MyCookie cookie = {&deleted};
+ sp<IBinder> createdBinder = binder->lookupOrCreateWeak(kObjectId1, make, &cookie);
+ EXPECT_NE(binder, createdBinder);
+
+ sp<IBinder> lookedUpBinder = binder->lookupOrCreateWeak(kObjectId1, make, &cookie);
+ EXPECT_EQ(createdBinder, lookedUpBinder);
+ EXPECT_FALSE(deleted);
+}
+
+TEST(Binder, LookupOrCreateWeakDropSp) {
+ auto binder = sp<BBinder>::make();
+ bool deleted1 = false;
+ bool deleted2 = false;
+ MyCookie cookie1 = {&deleted1};
+ MyCookie cookie2 = {&deleted2};
+ sp<IBinder> createdBinder = binder->lookupOrCreateWeak(kObjectId1, make, &cookie1);
+ EXPECT_NE(binder, createdBinder);
+
+ createdBinder.clear();
+ EXPECT_TRUE(deleted1);
+
+ sp<IBinder> lookedUpBinder = binder->lookupOrCreateWeak(kObjectId1, make, &cookie2);
+ EXPECT_EQ(&cookie2, sp<UniqueBinder>::cast(lookedUpBinder)->cookie);
+ EXPECT_FALSE(deleted2);
+}
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 501a604..b59308c 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -264,9 +264,13 @@
RpcSecurity rpcSecurity() const { return std::get<1>(GetParam()); }
uint32_t clientVersion() const { return std::get<2>(GetParam()); }
uint32_t serverVersion() const { return std::get<3>(GetParam()); }
- bool singleThreaded() const { return std::get<4>(GetParam()); }
+ bool serverSingleThreaded() const { return std::get<4>(GetParam()); }
bool noKernel() const { return std::get<5>(GetParam()); }
+ bool clientOrServerSingleThreaded() const {
+ return !kEnableRpcThreads || serverSingleThreaded();
+ }
+
// Whether the test params support sending FDs in parcels.
bool supportsFdTransport() const {
return clientVersion() >= 1 && serverVersion() >= 1 && rpcSecurity() != RpcSecurity::TLS &&
@@ -404,18 +408,6 @@
size_t sleepMs = 500);
};
-// Test fixture for tests that start multiple threads.
-// This includes tests with one thread but multiple sessions,
-// since a server uses one thread per session.
-class BinderRpcThreads : public BinderRpc {
-public:
- void SetUp() override {
- if constexpr (!kEnableRpcThreads) {
- GTEST_SKIP() << "Test skipped because threads were disabled at build time";
- }
- }
-};
-
TEST_P(BinderRpc, Ping) {
auto proc = createRpcTestSocketServerProcess({});
ASSERT_NE(proc.rootBinder, nullptr);
@@ -428,7 +420,13 @@
EXPECT_EQ(IBinderRpcTest::descriptor, proc.rootBinder->getInterfaceDescriptor());
}
-TEST_P(BinderRpcThreads, MultipleSessions) {
+TEST_P(BinderRpc, MultipleSessions) {
+ if (serverSingleThreaded()) {
+ // Tests with multiple sessions require a multi-threaded service,
+ // but work fine on a single-threaded client
+ GTEST_SKIP() << "This test requires a multi-threaded service";
+ }
+
auto proc = createRpcTestSocketServerProcess({.numThreads = 1, .numSessions = 5});
for (auto session : proc.proc.sessions) {
ASSERT_NE(nullptr, session.root);
@@ -436,7 +434,11 @@
}
}
-TEST_P(BinderRpcThreads, SeparateRootObject) {
+TEST_P(BinderRpc, SeparateRootObject) {
+ if (serverSingleThreaded()) {
+ GTEST_SKIP() << "This test requires a multi-threaded service";
+ }
+
SocketType type = std::get<0>(GetParam());
if (type == SocketType::PRECONNECTED || type == SocketType::UNIX) {
// we can't get port numbers for unix sockets
@@ -619,7 +621,11 @@
proc1.rootIface->repeatBinder(proc2.rootBinder, &outBinder).transactionError());
}
-TEST_P(BinderRpcThreads, CannotMixBindersBetweenTwoSessionsToTheSameServer) {
+TEST_P(BinderRpc, CannotMixBindersBetweenTwoSessionsToTheSameServer) {
+ if (serverSingleThreaded()) {
+ GTEST_SKIP() << "This test requires a multi-threaded service";
+ }
+
auto proc = createRpcTestSocketServerProcess({.numThreads = 1, .numSessions = 2});
sp<IBinder> outBinder;
@@ -775,7 +781,11 @@
return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
}
-TEST_P(BinderRpcThreads, ThreadPoolGreaterThanEqualRequested) {
+TEST_P(BinderRpc, ThreadPoolGreaterThanEqualRequested) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
constexpr size_t kNumThreads = 10;
auto proc = createRpcTestSocketServerProcess({.numThreads = kNumThreads});
@@ -826,14 +836,22 @@
EXPECT_LE(epochMsAfter, epochMsBefore + 3 * sleepMs);
}
-TEST_P(BinderRpcThreads, ThreadPoolOverSaturated) {
+TEST_P(BinderRpc, ThreadPoolOverSaturated) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
constexpr size_t kNumThreads = 10;
constexpr size_t kNumCalls = kNumThreads + 3;
auto proc = createRpcTestSocketServerProcess({.numThreads = kNumThreads});
testThreadPoolOverSaturated(proc.rootIface, kNumCalls);
}
-TEST_P(BinderRpcThreads, ThreadPoolLimitOutgoing) {
+TEST_P(BinderRpc, ThreadPoolLimitOutgoing) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
constexpr size_t kNumThreads = 20;
constexpr size_t kNumOutgoingConnections = 10;
constexpr size_t kNumCalls = kNumOutgoingConnections + 3;
@@ -842,7 +860,11 @@
testThreadPoolOverSaturated(proc.rootIface, kNumCalls);
}
-TEST_P(BinderRpcThreads, ThreadingStressTest) {
+TEST_P(BinderRpc, ThreadingStressTest) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
constexpr size_t kNumClientThreads = 10;
constexpr size_t kNumServerThreads = 10;
constexpr size_t kNumCalls = 100;
@@ -871,7 +893,11 @@
for (auto& t : threads) t.join();
}
-TEST_P(BinderRpcThreads, OnewayStressTest) {
+TEST_P(BinderRpc, OnewayStressTest) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
constexpr size_t kNumClientThreads = 10;
constexpr size_t kNumServerThreads = 10;
constexpr size_t kNumCalls = 1000;
@@ -906,7 +932,11 @@
EXPECT_LT(epochMsAfter, epochMsBefore + kReallyLongTimeMs);
}
-TEST_P(BinderRpcThreads, OnewayCallQueueing) {
+TEST_P(BinderRpc, OnewayCallQueueing) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
constexpr size_t kNumSleeps = 10;
constexpr size_t kNumExtraServerThreads = 4;
constexpr size_t kSleepMs = 50;
@@ -935,7 +965,11 @@
saturateThreadPool(1 + kNumExtraServerThreads, proc.rootIface);
}
-TEST_P(BinderRpcThreads, OnewayCallExhaustion) {
+TEST_P(BinderRpc, OnewayCallExhaustion) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
constexpr size_t kNumClients = 2;
constexpr size_t kTooLongMs = 1000;
@@ -978,17 +1012,16 @@
TEST_P(BinderRpc, Callbacks) {
const static std::string kTestString = "good afternoon!";
- bool bothSingleThreaded = !kEnableRpcThreads || singleThreaded();
-
for (bool callIsOneway : {true, false}) {
for (bool callbackIsOneway : {true, false}) {
for (bool delayed : {true, false}) {
- if (bothSingleThreaded && (callIsOneway || callbackIsOneway || delayed)) {
+ if (clientOrServerSingleThreaded() &&
+ (callIsOneway || callbackIsOneway || delayed)) {
// we have no incoming connections to receive the callback
continue;
}
- size_t numIncomingConnections = bothSingleThreaded ? 0 : 1;
+ size_t numIncomingConnections = clientOrServerSingleThreaded() ? 0 : 1;
auto proc = createRpcTestSocketServerProcess(
{.numThreads = 1,
.numSessions = 1,
@@ -1036,7 +1069,7 @@
}
TEST_P(BinderRpc, SingleDeathRecipient) {
- if (singleThreaded() || !kEnableRpcThreads) {
+ if (clientOrServerSingleThreaded()) {
GTEST_SKIP() << "This test requires multiple threads";
}
class MyDeathRec : public IBinder::DeathRecipient {
@@ -1062,10 +1095,7 @@
}
std::unique_lock<std::mutex> lock(dr->mMtx);
- if (!dr->dead) {
- EXPECT_EQ(std::cv_status::no_timeout, dr->mCv.wait_for(lock, 1000ms));
- }
- EXPECT_TRUE(dr->dead) << "Failed to receive the death notification.";
+ ASSERT_TRUE(dr->mCv.wait_for(lock, 1000ms, [&]() { return dr->dead; }));
// need to wait for the session to shutdown so we don't "Leak session"
EXPECT_TRUE(proc.proc.sessions.at(0).session->shutdownAndWait(true));
@@ -1073,7 +1103,7 @@
}
TEST_P(BinderRpc, SingleDeathRecipientOnShutdown) {
- if (singleThreaded() || !kEnableRpcThreads) {
+ if (clientOrServerSingleThreaded()) {
GTEST_SKIP() << "This test requires multiple threads";
}
class MyDeathRec : public IBinder::DeathRecipient {
@@ -1127,7 +1157,7 @@
}
TEST_P(BinderRpc, UnlinkDeathRecipient) {
- if (singleThreaded() || !kEnableRpcThreads) {
+ if (clientOrServerSingleThreaded()) {
GTEST_SKIP() << "This test requires multiple threads";
}
class MyDeathRec : public IBinder::DeathRecipient {
@@ -1193,7 +1223,7 @@
// libbinder.so (when using static libraries, even a client and service
// using the same kind of static library should have separate copies of the
// variables).
- if (!kEnableSharedLibs || singleThreaded() || noKernel()) {
+ if (!kEnableSharedLibs || serverSingleThreaded() || noKernel()) {
GTEST_SKIP() << "Test disabled because Binder kernel driver was disabled "
"at build time.";
}
@@ -1393,7 +1423,11 @@
return ret;
}
-TEST_P(BinderRpcThreads, Fds) {
+TEST_P(BinderRpc, Fds) {
+ if (serverSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
ssize_t beforeFds = countFds();
ASSERT_GE(beforeFds, 0);
{
@@ -1534,15 +1568,6 @@
::testing::Values(false, true)),
BinderRpc::PrintParamInfo);
-INSTANTIATE_TEST_CASE_P(PerSocket, BinderRpcThreads,
- ::testing::Combine(::testing::ValuesIn(testSocketTypes()),
- ::testing::ValuesIn(RpcSecurityValues()),
- ::testing::ValuesIn(testVersions()),
- ::testing::ValuesIn(testVersions()),
- ::testing::Values(false),
- ::testing::Values(false, true)),
- BinderRpc::PrintParamInfo);
-
class BinderRpcServerRootObject
: public ::testing::TestWithParam<std::tuple<bool, bool, RpcSecurity>> {};
diff --git a/libs/binder/trusty/OS.cpp b/libs/binder/trusty/OS.cpp
index bbfa381..b21fe6a 100644
--- a/libs/binder/trusty/OS.cpp
+++ b/libs/binder/trusty/OS.cpp
@@ -14,7 +14,11 @@
* limitations under the License.
*/
+#if defined(TRUSTY_USERSPACE)
#include <openssl/rand.h>
+#else
+#include <lib/rand/rand.h>
+#endif
#include "../OS.h"
@@ -28,8 +32,13 @@
}
status_t getRandomBytes(uint8_t* data, size_t size) {
+#if defined(TRUSTY_USERSPACE)
int res = RAND_bytes(data, size);
return res == 1 ? OK : UNKNOWN_ERROR;
+#else
+ int res = rand_get_bytes(data, size);
+ return res == 0 ? OK : UNKNOWN_ERROR;
+#endif // TRUSTY_USERSPACE
}
status_t dupFileDescriptor(int oldFd, int* newFd) {
diff --git a/libs/ftl/optional_test.cpp b/libs/ftl/optional_test.cpp
index 6a8c8f9..ede159a 100644
--- a/libs/ftl/optional_test.cpp
+++ b/libs/ftl/optional_test.cpp
@@ -17,6 +17,7 @@
#include <ftl/optional.h>
#include <ftl/static_vector.h>
#include <ftl/string.h>
+#include <ftl/unit.h>
#include <gtest/gtest.h>
#include <functional>
@@ -62,6 +63,13 @@
EXPECT_EQ(out, "abc"s);
}
+ // No return value.
+ {
+ Optional opt = "food"s;
+ EXPECT_EQ(ftl::unit, opt.transform(ftl::unit_fn([](std::string& str) { str.pop_back(); })));
+ EXPECT_EQ(opt, "foo"s);
+ }
+
// Chaining.
EXPECT_EQ(14u, Optional(StaticVector{"upside"s, "down"s})
.transform([](StaticVector<std::string, 3>&& v) {
diff --git a/libs/ftl/small_map_test.cpp b/libs/ftl/small_map_test.cpp
index 1740a2b..634877f 100644
--- a/libs/ftl/small_map_test.cpp
+++ b/libs/ftl/small_map_test.cpp
@@ -15,12 +15,15 @@
*/
#include <ftl/small_map.h>
+#include <ftl/unit.h>
#include <gtest/gtest.h>
#include <cctype>
#include <string>
+#include <string_view>
using namespace std::string_literals;
+using namespace std::string_view_literals;
namespace android::test {
@@ -38,7 +41,7 @@
EXPECT_TRUE(map.contains(123));
- EXPECT_EQ(map.get(42, [](const std::string& s) { return s.size(); }), 3u);
+ EXPECT_EQ(map.get(42).transform([](const std::string& s) { return s.size(); }), 3u);
const auto opt = map.get(-1);
ASSERT_TRUE(opt);
@@ -50,7 +53,7 @@
map.emplace_or_replace(0, "vanilla", 2u, 3u);
EXPECT_TRUE(map.dynamic());
- EXPECT_EQ(map, SmallMap(ftl::init::map(-1, "xyz")(0, "nil")(42, "???")(123, "abc")));
+ EXPECT_EQ(map, SmallMap(ftl::init::map(-1, "xyz"sv)(0, "nil"sv)(42, "???"sv)(123, "abc"sv)));
}
TEST(SmallMap, Construct) {
@@ -70,7 +73,7 @@
EXPECT_EQ(map.max_size(), 5u);
EXPECT_FALSE(map.dynamic());
- EXPECT_EQ(map, SmallMap(ftl::init::map(123, "abc")(456, "def")(789, "ghi")));
+ EXPECT_EQ(map, SmallMap(ftl::init::map(123, "abc"sv)(456, "def"sv)(789, "ghi"sv)));
}
{
// In-place constructor with different types.
@@ -81,7 +84,7 @@
EXPECT_EQ(map.max_size(), 5u);
EXPECT_FALSE(map.dynamic());
- EXPECT_EQ(map, SmallMap(ftl::init::map(42, "???")(123, "abc")(-1, "\0\0\0")));
+ EXPECT_EQ(map, SmallMap(ftl::init::map(42, "???"sv)(123, "abc"sv)(-1, ""sv)));
}
{
// In-place constructor with implicit size.
@@ -92,7 +95,7 @@
EXPECT_EQ(map.max_size(), 3u);
EXPECT_FALSE(map.dynamic());
- EXPECT_EQ(map, SmallMap(ftl::init::map(-1, "\0\0\0")(42, "???")(123, "abc")));
+ EXPECT_EQ(map, SmallMap(ftl::init::map(-1, ""sv)(42, "???"sv)(123, "abc"sv)));
}
}
@@ -108,7 +111,7 @@
{
// Convertible types; same capacity.
SmallMap map1 = ftl::init::map<char, std::string>('M', "mega")('G', "giga");
- const SmallMap map2 = ftl::init::map('T', "tera")('P', "peta");
+ const SmallMap map2 = ftl::init::map('T', "tera"sv)('P', "peta"sv);
map1 = map2;
EXPECT_EQ(map1, map2);
@@ -147,7 +150,7 @@
}
}
-TEST(SmallMap, Find) {
+TEST(SmallMap, Get) {
{
// Constant reference.
const SmallMap map = ftl::init::map('a', 'A')('b', 'B')('c', 'C');
@@ -172,14 +175,15 @@
EXPECT_EQ(d, 'D');
}
{
- // Constant unary operation.
+ // Immutable transform operation.
const SmallMap map = ftl::init::map('a', 'x')('b', 'y')('c', 'z');
- EXPECT_EQ(map.get('c', [](char c) { return std::toupper(c); }), 'Z');
+ EXPECT_EQ(map.get('c').transform([](char c) { return std::toupper(c); }), 'Z');
}
{
- // Mutable unary operation.
+ // Mutable transform operation.
SmallMap map = ftl::init::map('a', 'x')('b', 'y')('c', 'z');
- EXPECT_TRUE(map.get('c', [](char& c) { c = std::toupper(c); }));
+ EXPECT_EQ(map.get('c').transform(ftl::unit_fn([](char& c) { c = std::toupper(c); })),
+ ftl::unit);
EXPECT_EQ(map, SmallMap(ftl::init::map('c', 'Z')('b', 'y')('a', 'x')));
}
@@ -247,7 +251,7 @@
}
{
// Replacement arguments can refer to the replaced mapping.
- const auto ref = map.get(2, [](const auto& s) { return s.str[0]; });
+ const auto ref = map.get(2).transform([](const String& s) { return s.str[0]; });
ASSERT_TRUE(ref);
// Construct std::string from one character.
@@ -292,7 +296,7 @@
}
{
// Replacement arguments can refer to the replaced mapping.
- const auto ref = map.get(2, [](const auto& s) { return s.str[0]; });
+ const auto ref = map.get(2).transform([](const String& s) { return s.str[0]; });
ASSERT_TRUE(ref);
// Construct std::string from one character.
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index bb66085..4d5978c 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -40,8 +40,6 @@
x(0),
y(0),
z(0),
- w(0),
- h(0),
alpha(0),
flags(0),
mask(0),
@@ -84,8 +82,6 @@
SAFE_PARCEL(output.writeFloat, x);
SAFE_PARCEL(output.writeFloat, y);
SAFE_PARCEL(output.writeInt32, z);
- SAFE_PARCEL(output.writeUint32, w);
- SAFE_PARCEL(output.writeUint32, h);
SAFE_PARCEL(output.writeUint32, layerStack.id);
SAFE_PARCEL(output.writeFloat, alpha);
SAFE_PARCEL(output.writeUint32, flags);
@@ -180,8 +176,6 @@
SAFE_PARCEL(input.readFloat, &x);
SAFE_PARCEL(input.readFloat, &y);
SAFE_PARCEL(input.readInt32, &z);
- SAFE_PARCEL(input.readUint32, &w);
- SAFE_PARCEL(input.readUint32, &h);
SAFE_PARCEL(input.readUint32, &layerStack.id);
SAFE_PARCEL(input.readFloat, &alpha);
@@ -457,11 +451,6 @@
what &= ~eRelativeLayerChanged;
z = other.z;
}
- if (other.what & eSizeChanged) {
- what |= eSizeChanged;
- w = other.w;
- h = other.h;
- }
if (other.what & eAlphaChanged) {
what |= eAlphaChanged;
alpha = other.alpha;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index e8aaf62..34edd65 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1038,9 +1038,7 @@
flags |= ISurfaceComposer::eEarlyWakeupEnd;
}
- sp<IBinder> applyToken = mApplyToken
- ? mApplyToken
- : IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ sp<IBinder> applyToken = mApplyToken ? mApplyToken : sApplyToken;
sf->setTransactionState(mFrameTimelineInfo, composerStates, displayStates, flags, applyToken,
mInputWindowCommands, mDesiredPresentTime, mIsAutoTimestamp,
@@ -1055,6 +1053,15 @@
return NO_ERROR;
}
+sp<IBinder> SurfaceComposerClient::Transaction::sApplyToken = new BBinder();
+
+sp<IBinder> SurfaceComposerClient::Transaction::getDefaultApplyToken() {
+ return sApplyToken;
+}
+
+void SurfaceComposerClient::Transaction::setDefaultApplyToken(sp<IBinder> applyToken) {
+ sApplyToken = applyToken;
+}
// ---------------------------------------------------------------------------
sp<IBinder> SurfaceComposerClient::createDisplay(const String8& displayName, bool secure) {
@@ -1165,21 +1172,6 @@
return setFlags(sc, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden);
}
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSize(
- const sp<SurfaceControl>& sc, uint32_t w, uint32_t h) {
- layer_state_t* s = getLayerState(sc);
- if (!s) {
- mStatus = BAD_INDEX;
- return *this;
- }
- s->what |= layer_state_t::eSizeChanged;
- s->w = w;
- s->h = h;
-
- registerSurfaceControlForCallback(sc);
- return *this;
-}
-
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayer(
const sp<SurfaceControl>& sc, int32_t z) {
layer_state_t* s = getLayerState(sc);
diff --git a/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp b/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp
index 05564e0..48c90c5 100644
--- a/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp
+++ b/libs/gui/fuzzer/libgui_surfaceComposerClient_fuzzer.cpp
@@ -182,8 +182,6 @@
sp<SurfaceControl> surface = makeSurfaceControl();
SurfaceComposerClient::Transaction transaction;
- transaction.setSize(surface, mFdp.ConsumeIntegral<uint32_t>(),
- mFdp.ConsumeIntegral<uint32_t>());
int32_t layer = mFdp.ConsumeIntegral<int32_t>();
transaction.setLayer(surface, layer);
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 759fcc6..3c7b162 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -148,7 +148,7 @@
enum {
ePositionChanged = 0x00000001,
eLayerChanged = 0x00000002,
- eSizeChanged = 0x00000004,
+ // unused = 0x00000004,
eAlphaChanged = 0x00000008,
eMatrixChanged = 0x00000010,
eTransparentRegionChanged = 0x00000020,
@@ -217,8 +217,6 @@
float x;
float y;
int32_t z;
- uint32_t w;
- uint32_t h;
ui::LayerStack layerStack = ui::DEFAULT_LAYER_STACK;
float alpha;
uint32_t flags;
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 20c38d8..8c47ebc 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -390,6 +390,7 @@
class Transaction : public Parcelable {
private:
+ static sp<IBinder> sApplyToken;
void releaseBufferIfOverwriting(const layer_state_t& state);
static void mergeFrameTimelineInfo(FrameTimelineInfo& t, const FrameTimelineInfo& other);
static void clearFrameTimelineInfo(FrameTimelineInfo& t);
@@ -468,10 +469,9 @@
Transaction& merge(Transaction&& other);
Transaction& show(const sp<SurfaceControl>& sc);
Transaction& hide(const sp<SurfaceControl>& sc);
- Transaction& setPosition(const sp<SurfaceControl>& sc,
- float x, float y);
- Transaction& setSize(const sp<SurfaceControl>& sc,
- uint32_t w, uint32_t h);
+ Transaction& setPosition(const sp<SurfaceControl>& sc, float x, float y);
+ // b/243180033 remove once functions are not called from vendor code
+ Transaction& setSize(const sp<SurfaceControl>&, uint32_t, uint32_t) { return *this; }
Transaction& setLayer(const sp<SurfaceControl>& sc,
int32_t z);
@@ -669,6 +669,9 @@
* TODO (b/213644870): Remove all permissioned things from Transaction
*/
void sanitize();
+
+ static sp<IBinder> getDefaultApplyToken();
+ static void setDefaultApplyToken(sp<IBinder> applyToken);
};
status_t clearLayerFrameStats(const sp<IBinder>& token) const;
diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp
index d6b4579..7371033 100644
--- a/libs/input/KeyLayoutMap.cpp
+++ b/libs/input/KeyLayoutMap.cpp
@@ -192,7 +192,8 @@
}
// Return pair of sensor type and sensor data index, for the input device abs code
-base::Result<std::pair<InputDeviceSensorType, int32_t>> KeyLayoutMap::mapSensor(int32_t absCode) {
+base::Result<std::pair<InputDeviceSensorType, int32_t>> KeyLayoutMap::mapSensor(
+ int32_t absCode) const {
auto it = mSensorsByAbsCode.find(absCode);
if (it == mSensorsByAbsCode.end()) {
ALOGD_IF(DEBUG_MAPPING, "mapSensor: absCode=%d, ~ Failed.", absCode);
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index bfa44ac..06a38c8 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -52,6 +52,7 @@
#include <filesystem>
#include <regex>
+#include <utility>
#include "EventHub.h"
@@ -193,8 +194,7 @@
}
/**
- * Returns the sysfs root path of the input device
- *
+ * Returns the sysfs root path of the input device.
*/
static std::optional<std::filesystem::path> getSysfsRootPath(const char* devicePath) {
std::error_code errorCode;
@@ -301,6 +301,83 @@
return colors;
}
+/**
+ * Read information about batteries exposed through the sysfs path.
+ */
+static std::unordered_map<int32_t /*batteryId*/, RawBatteryInfo> readBatteryConfiguration(
+ const std::filesystem::path& sysfsRootPath) {
+ std::unordered_map<int32_t, RawBatteryInfo> batteryInfos;
+ int32_t nextBatteryId = 0;
+ // Check if device has any battery.
+ const auto& paths = findSysfsNodes(sysfsRootPath, SysfsClass::POWER_SUPPLY);
+ for (const auto& nodePath : paths) {
+ RawBatteryInfo info;
+ info.id = ++nextBatteryId;
+ info.path = nodePath;
+ info.name = nodePath.filename();
+
+ // Scan the path for all the files
+ // Refer to https://www.kernel.org/doc/Documentation/leds/leds-class.txt
+ const auto& files = allFilesInPath(nodePath);
+ for (const auto& file : files) {
+ const auto it = BATTERY_CLASSES.find(file.filename().string());
+ if (it != BATTERY_CLASSES.end()) {
+ info.flags |= it->second;
+ }
+ }
+ batteryInfos.insert_or_assign(info.id, info);
+ ALOGD("configureBatteryLocked rawBatteryId %d name %s", info.id, info.name.c_str());
+ }
+ return batteryInfos;
+}
+
+/**
+ * Read information about lights exposed through the sysfs path.
+ */
+static std::unordered_map<int32_t /*lightId*/, RawLightInfo> readLightsConfiguration(
+ const std::filesystem::path& sysfsRootPath) {
+ std::unordered_map<int32_t, RawLightInfo> lightInfos;
+ int32_t nextLightId = 0;
+ // Check if device has any lights.
+ const auto& paths = findSysfsNodes(sysfsRootPath, SysfsClass::LEDS);
+ for (const auto& nodePath : paths) {
+ RawLightInfo info;
+ info.id = ++nextLightId;
+ info.path = nodePath;
+ info.name = nodePath.filename();
+ info.maxBrightness = std::nullopt;
+ size_t nameStart = info.name.rfind(":");
+ if (nameStart != std::string::npos) {
+ // Trim the name to color name
+ info.name = info.name.substr(nameStart + 1);
+ // Set InputLightClass flag for colors
+ const auto it = LIGHT_CLASSES.find(info.name);
+ if (it != LIGHT_CLASSES.end()) {
+ info.flags |= it->second;
+ }
+ }
+ // Scan the path for all the files
+ // Refer to https://www.kernel.org/doc/Documentation/leds/leds-class.txt
+ const auto& files = allFilesInPath(nodePath);
+ for (const auto& file : files) {
+ const auto it = LIGHT_CLASSES.find(file.filename().string());
+ if (it != LIGHT_CLASSES.end()) {
+ info.flags |= it->second;
+ // If the node has maximum brightness, read it
+ if (it->second == InputLightClass::MAX_BRIGHTNESS) {
+ std::string str;
+ if (base::ReadFileToString(file, &str)) {
+ info.maxBrightness = std::stoi(str);
+ }
+ }
+ }
+ }
+ lightInfos.insert_or_assign(info.id, info);
+ ALOGD("configureLightsLocked rawLightId %d name %s", info.id, info.name.c_str());
+ }
+ return lightInfos;
+}
+
// --- Global Functions ---
ftl::Flags<InputDeviceClass> getAbsAxisUsage(int32_t axis,
@@ -357,18 +434,18 @@
// --- EventHub::Device ---
-EventHub::Device::Device(int fd, int32_t id, const std::string& path,
- const InputDeviceIdentifier& identifier)
+EventHub::Device::Device(int fd, int32_t id, std::string path, InputDeviceIdentifier identifier,
+ std::shared_ptr<const AssociatedDevice> assocDev)
: fd(fd),
id(id),
- path(path),
- identifier(identifier),
+ path(std::move(path)),
+ identifier(std::move(identifier)),
classes(0),
configuration(nullptr),
virtualKeyMap(nullptr),
ffEffectPlaying(false),
ffEffectId(-1),
- associatedDevice(nullptr),
+ associatedDevice(std::move(assocDev)),
controllerNumber(0),
enabled(true),
isVirtual(fd < 0) {}
@@ -557,75 +634,6 @@
return NAME_NOT_FOUND;
}
-// Check the sysfs path for any input device batteries, returns true if battery found.
-bool EventHub::AssociatedDevice::configureBatteryLocked() {
- nextBatteryId = 0;
- // Check if device has any battery.
- const auto& paths = findSysfsNodes(sysfsRootPath, SysfsClass::POWER_SUPPLY);
- for (const auto& nodePath : paths) {
- RawBatteryInfo info;
- info.id = ++nextBatteryId;
- info.path = nodePath;
- info.name = nodePath.filename();
-
- // Scan the path for all the files
- // Refer to https://www.kernel.org/doc/Documentation/leds/leds-class.txt
- const auto& files = allFilesInPath(nodePath);
- for (const auto& file : files) {
- const auto it = BATTERY_CLASSES.find(file.filename().string());
- if (it != BATTERY_CLASSES.end()) {
- info.flags |= it->second;
- }
- }
- batteryInfos.insert_or_assign(info.id, info);
- ALOGD("configureBatteryLocked rawBatteryId %d name %s", info.id, info.name.c_str());
- }
- return !batteryInfos.empty();
-}
-
-// Check the sysfs path for any input device lights, returns true if lights found.
-bool EventHub::AssociatedDevice::configureLightsLocked() {
- nextLightId = 0;
- // Check if device has any lights.
- const auto& paths = findSysfsNodes(sysfsRootPath, SysfsClass::LEDS);
- for (const auto& nodePath : paths) {
- RawLightInfo info;
- info.id = ++nextLightId;
- info.path = nodePath;
- info.name = nodePath.filename();
- info.maxBrightness = std::nullopt;
- size_t nameStart = info.name.rfind(":");
- if (nameStart != std::string::npos) {
- // Trim the name to color name
- info.name = info.name.substr(nameStart + 1);
- // Set InputLightClass flag for colors
- const auto it = LIGHT_CLASSES.find(info.name);
- if (it != LIGHT_CLASSES.end()) {
- info.flags |= it->second;
- }
- }
- // Scan the path for all the files
- // Refer to https://www.kernel.org/doc/Documentation/leds/leds-class.txt
- const auto& files = allFilesInPath(nodePath);
- for (const auto& file : files) {
- const auto it = LIGHT_CLASSES.find(file.filename().string());
- if (it != LIGHT_CLASSES.end()) {
- info.flags |= it->second;
- // If the node has maximum brightness, read it
- if (it->second == InputLightClass::MAX_BRIGHTNESS) {
- std::string str;
- if (base::ReadFileToString(file, &str)) {
- info.maxBrightness = std::stoi(str);
- }
- }
- }
- }
- lightInfos.insert_or_assign(info.id, info);
- ALOGD("configureLightsLocked rawLightId %d name %s", info.id, info.name.c_str());
- }
- return !lightInfos.empty();
-}
-
/**
* Get the capabilities for the current process.
* Crashes the system if unable to create / check / destroy the capabilities object.
@@ -1034,7 +1042,7 @@
}
base::Result<std::pair<InputDeviceSensorType, int32_t>> EventHub::mapSensor(int32_t deviceId,
- int32_t absCode) {
+ int32_t absCode) const {
std::scoped_lock _l(mLock);
Device* device = getDeviceLocked(deviceId);
@@ -1056,18 +1064,19 @@
return device->associatedDevice->batteryInfos;
}
-const std::vector<int32_t> EventHub::getRawBatteryIds(int32_t deviceId) {
+std::vector<int32_t> EventHub::getRawBatteryIds(int32_t deviceId) const {
std::scoped_lock _l(mLock);
std::vector<int32_t> batteryIds;
- for (const auto [id, info] : getBatteryInfoLocked(deviceId)) {
+ for (const auto& [id, info] : getBatteryInfoLocked(deviceId)) {
batteryIds.push_back(id);
}
return batteryIds;
}
-std::optional<RawBatteryInfo> EventHub::getRawBatteryInfo(int32_t deviceId, int32_t batteryId) {
+std::optional<RawBatteryInfo> EventHub::getRawBatteryInfo(int32_t deviceId,
+ int32_t batteryId) const {
std::scoped_lock _l(mLock);
const auto infos = getBatteryInfoLocked(deviceId);
@@ -1081,7 +1090,7 @@
}
// Gets the light info map from light ID to RawLightInfo of the miscellaneous device associated
-// with the deivice ID. Returns an empty map if no miscellaneous device found.
+// with the device ID. Returns an empty map if no miscellaneous device found.
const std::unordered_map<int32_t, RawLightInfo>& EventHub::getLightInfoLocked(
int32_t deviceId) const {
static const std::unordered_map<int32_t, RawLightInfo> EMPTY_LIGHT_INFO = {};
@@ -1092,18 +1101,18 @@
return device->associatedDevice->lightInfos;
}
-const std::vector<int32_t> EventHub::getRawLightIds(int32_t deviceId) {
+std::vector<int32_t> EventHub::getRawLightIds(int32_t deviceId) const {
std::scoped_lock _l(mLock);
std::vector<int32_t> lightIds;
- for (const auto [id, info] : getLightInfoLocked(deviceId)) {
+ for (const auto& [id, info] : getLightInfoLocked(deviceId)) {
lightIds.push_back(id);
}
return lightIds;
}
-std::optional<RawLightInfo> EventHub::getRawLightInfo(int32_t deviceId, int32_t lightId) {
+std::optional<RawLightInfo> EventHub::getRawLightInfo(int32_t deviceId, int32_t lightId) const {
std::scoped_lock _l(mLock);
const auto infos = getLightInfoLocked(deviceId);
@@ -1116,7 +1125,7 @@
return std::nullopt;
}
-std::optional<int32_t> EventHub::getLightBrightness(int32_t deviceId, int32_t lightId) {
+std::optional<int32_t> EventHub::getLightBrightness(int32_t deviceId, int32_t lightId) const {
std::scoped_lock _l(mLock);
const auto infos = getLightInfoLocked(deviceId);
@@ -1133,7 +1142,7 @@
}
std::optional<std::unordered_map<LightColor, int32_t>> EventHub::getLightIntensities(
- int32_t deviceId, int32_t lightId) {
+ int32_t deviceId, int32_t lightId) const {
std::scoped_lock _l(mLock);
const auto infos = getLightInfoLocked(deviceId);
@@ -1358,6 +1367,27 @@
identifier.descriptor.c_str());
}
+std::shared_ptr<const EventHub::AssociatedDevice> EventHub::obtainAssociatedDeviceLocked(
+ const std::filesystem::path& devicePath) const {
+ const std::optional<std::filesystem::path> sysfsRootPathOpt =
+ getSysfsRootPath(devicePath.c_str());
+ if (!sysfsRootPathOpt) {
+ return nullptr;
+ }
+
+ const auto& path = *sysfsRootPathOpt;
+ for (const auto& [id, dev] : mDevices) {
+ if (dev->associatedDevice && dev->associatedDevice->sysfsRootPath == path) {
+ return dev->associatedDevice;
+ }
+ }
+
+ return std::make_shared<AssociatedDevice>(
+ AssociatedDevice{.sysfsRootPath = path,
+ .batteryInfos = readBatteryConfiguration(path),
+ .lightInfos = readLightsConfiguration(path)});
+}
+
void EventHub::vibrate(int32_t deviceId, const VibrationElement& element) {
std::scoped_lock _l(mLock);
Device* device = getDeviceLocked(deviceId);
@@ -1415,7 +1445,7 @@
}
}
-std::vector<int32_t> EventHub::getVibratorIds(int32_t deviceId) {
+std::vector<int32_t> EventHub::getVibratorIds(int32_t deviceId) const {
std::scoped_lock _l(mLock);
std::vector<int32_t> vibrators;
Device* device = getDeviceLocked(deviceId);
@@ -2024,7 +2054,9 @@
// Allocate device. (The device object takes ownership of the fd at this point.)
int32_t deviceId = mNextDeviceId++;
- std::unique_ptr<Device> device = std::make_unique<Device>(fd, deviceId, devicePath, identifier);
+ std::unique_ptr<Device> device =
+ std::make_unique<Device>(fd, deviceId, devicePath, identifier,
+ obtainAssociatedDeviceLocked(devicePath));
ALOGV("add device %d: %s\n", deviceId, devicePath.c_str());
ALOGV(" bus: %04x\n"
@@ -2042,27 +2074,6 @@
// Load the configuration file for the device.
device->loadConfigurationLocked();
- bool hasBattery = false;
- bool hasLights = false;
- // Check the sysfs root path
- std::optional<std::filesystem::path> sysfsRootPath = getSysfsRootPath(devicePath.c_str());
- if (sysfsRootPath.has_value()) {
- std::shared_ptr<AssociatedDevice> associatedDevice;
- for (const auto& [id, dev] : mDevices) {
- if (device->identifier.descriptor == dev->identifier.descriptor &&
- !dev->associatedDevice) {
- associatedDevice = dev->associatedDevice;
- }
- }
- if (!associatedDevice) {
- associatedDevice = std::make_shared<AssociatedDevice>(sysfsRootPath.value());
- }
- hasBattery = associatedDevice->configureBatteryLocked();
- hasLights = associatedDevice->configureLightsLocked();
-
- device->associatedDevice = associatedDevice;
- }
-
// Figure out the kinds of events the device reports.
device->readDeviceBitMask(EVIOCGBIT(EV_KEY, 0), device->keyBitmask);
device->readDeviceBitMask(EVIOCGBIT(EV_ABS, 0), device->absBitmask);
@@ -2212,12 +2223,12 @@
}
// Classify InputDeviceClass::BATTERY.
- if (hasBattery) {
+ if (device->associatedDevice && !device->associatedDevice->batteryInfos.empty()) {
device->classes |= InputDeviceClass::BATTERY;
}
// Classify InputDeviceClass::LIGHT.
- if (hasLights) {
+ if (device->associatedDevice && !device->associatedDevice->lightInfos.empty()) {
device->classes |= InputDeviceClass::LIGHT;
}
@@ -2285,7 +2296,7 @@
return true;
}
-bool EventHub::isDeviceEnabled(int32_t deviceId) {
+bool EventHub::isDeviceEnabled(int32_t deviceId) const {
std::scoped_lock _l(mLock);
Device* device = getDeviceLocked(deviceId);
if (device == nullptr) {
@@ -2340,7 +2351,7 @@
std::unique_ptr<Device> device =
std::make_unique<Device>(-1, ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, "<virtual>",
- identifier);
+ identifier, nullptr /*associatedDevice*/);
device->classes = InputDeviceClass::KEYBOARD | InputDeviceClass::ALPHAKEY |
InputDeviceClass::DPAD | InputDeviceClass::VIRTUAL;
device->loadKeyMapLocked();
@@ -2509,7 +2520,7 @@
mNeedToReopenDevices = true;
}
-void EventHub::dump(std::string& dump) {
+void EventHub::dump(std::string& dump) const {
dump += "Event Hub State:\n";
{ // acquire lock
@@ -2544,12 +2555,13 @@
device->keyMap.keyCharacterMapFile.c_str());
dump += StringPrintf(INDENT3 "ConfigurationFile: %s\n",
device->configurationFile.c_str());
- dump += INDENT3 "VideoDevice: ";
- if (device->videoDevice) {
- dump += device->videoDevice->dump() + "\n";
- } else {
- dump += "<none>\n";
- }
+ dump += StringPrintf(INDENT3 "VideoDevice: %s\n",
+ device->videoDevice ? device->videoDevice->dump().c_str()
+ : "<none>");
+ dump += StringPrintf(INDENT3 "SysfsDevicePath: %s\n",
+ device->associatedDevice
+ ? device->associatedDevice->sysfsRootPath.c_str()
+ : "<none>");
}
dump += INDENT "Unattached video devices:\n";
@@ -2562,9 +2574,9 @@
} // release lock
}
-void EventHub::monitor() {
+void EventHub::monitor() const {
// Acquire and release the lock to ensure that the event hub has not deadlocked.
std::unique_lock<std::mutex> lock(mLock);
}
-}; // namespace android
+} // namespace android
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index 4733ecb..8aec367 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -21,6 +21,7 @@
#include <climits>
#include <filesystem>
#include <unordered_map>
+#include <utility>
#include <vector>
#include <batteryservice/BatteryService.h>
@@ -281,22 +282,23 @@
*/
virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) = 0;
virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) = 0;
- virtual base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(int32_t deviceId,
- int32_t absCode) = 0;
+ virtual base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(
+ int32_t deviceId, int32_t absCode) const = 0;
// Raw batteries are sysfs power_supply nodes we found from the EventHub device sysfs node,
// containing the raw info of the sysfs node structure.
- virtual const std::vector<int32_t> getRawBatteryIds(int32_t deviceId) = 0;
+ virtual std::vector<int32_t> getRawBatteryIds(int32_t deviceId) const = 0;
virtual std::optional<RawBatteryInfo> getRawBatteryInfo(int32_t deviceId,
- int32_t BatteryId) = 0;
+ int32_t BatteryId) const = 0;
// Raw lights are sysfs led light nodes we found from the EventHub device sysfs node,
// containing the raw info of the sysfs node structure.
- virtual const std::vector<int32_t> getRawLightIds(int32_t deviceId) = 0;
- virtual std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId, int32_t lightId) = 0;
- virtual std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) = 0;
+ virtual std::vector<int32_t> getRawLightIds(int32_t deviceId) const = 0;
+ virtual std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId,
+ int32_t lightId) const = 0;
+ virtual std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) const = 0;
virtual void setLightBrightness(int32_t deviceId, int32_t lightId, int32_t brightness) = 0;
virtual std::optional<std::unordered_map<LightColor, int32_t>> getLightIntensities(
- int32_t deviceId, int32_t lightId) = 0;
+ int32_t deviceId, int32_t lightId) const = 0;
virtual void setLightIntensities(int32_t deviceId, int32_t lightId,
std::unordered_map<LightColor, int32_t> intensities) = 0;
/*
@@ -332,7 +334,7 @@
/* Control the vibrator. */
virtual void vibrate(int32_t deviceId, const VibrationElement& effect) = 0;
virtual void cancelVibrate(int32_t deviceId) = 0;
- virtual std::vector<int32_t> getVibratorIds(int32_t deviceId) = 0;
+ virtual std::vector<int32_t> getVibratorIds(int32_t deviceId) const = 0;
/* Query battery level. */
virtual std::optional<int32_t> getBatteryCapacity(int32_t deviceId,
@@ -348,13 +350,13 @@
virtual void wake() = 0;
/* Dump EventHub state to a string. */
- virtual void dump(std::string& dump) = 0;
+ virtual void dump(std::string& dump) const = 0;
/* Called by the heatbeat to ensures that the reader has not deadlocked. */
- virtual void monitor() = 0;
+ virtual void monitor() const = 0;
/* Return true if the device is enabled. */
- virtual bool isDeviceEnabled(int32_t deviceId) = 0;
+ virtual bool isDeviceEnabled(int32_t deviceId) const = 0;
/* Enable an input device */
virtual status_t enableDevice(int32_t deviceId) = 0;
@@ -462,20 +464,22 @@
AxisInfo* outAxisInfo) const override final;
base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(
- int32_t deviceId, int32_t absCode) override final;
+ int32_t deviceId, int32_t absCode) const override final;
- const std::vector<int32_t> getRawBatteryIds(int32_t deviceId) override final;
+ std::vector<int32_t> getRawBatteryIds(int32_t deviceId) const override final;
std::optional<RawBatteryInfo> getRawBatteryInfo(int32_t deviceId,
- int32_t BatteryId) override final;
+ int32_t BatteryId) const override final;
- const std::vector<int32_t> getRawLightIds(int32_t deviceId) override final;
+ std::vector<int32_t> getRawLightIds(int32_t deviceId) const override final;
- std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId, int32_t lightId) override final;
+ std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId,
+ int32_t lightId) const override final;
- std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) override final;
+ std::optional<int32_t> getLightBrightness(int32_t deviceId,
+ int32_t lightId) const override final;
void setLightBrightness(int32_t deviceId, int32_t lightId, int32_t brightness) override final;
std::optional<std::unordered_map<LightColor, int32_t>> getLightIntensities(
- int32_t deviceId, int32_t lightId) override final;
+ int32_t deviceId, int32_t lightId) const override final;
void setLightIntensities(int32_t deviceId, int32_t lightId,
std::unordered_map<LightColor, int32_t> intensities) override final;
@@ -511,15 +515,15 @@
void vibrate(int32_t deviceId, const VibrationElement& effect) override final;
void cancelVibrate(int32_t deviceId) override final;
- std::vector<int32_t> getVibratorIds(int32_t deviceId) override final;
+ std::vector<int32_t> getVibratorIds(int32_t deviceId) const override final;
void requestReopenDevices() override final;
void wake() override final;
- void dump(std::string& dump) override final;
+ void dump(std::string& dump) const override final;
- void monitor() override final;
+ void monitor() const override final;
std::optional<int32_t> getBatteryCapacity(int32_t deviceId,
int32_t batteryId) const override final;
@@ -527,7 +531,7 @@
std::optional<int32_t> getBatteryStatus(int32_t deviceId,
int32_t batteryId) const override final;
- bool isDeviceEnabled(int32_t deviceId) override final;
+ bool isDeviceEnabled(int32_t deviceId) const override final;
status_t enableDevice(int32_t deviceId) override final;
@@ -536,20 +540,13 @@
~EventHub() override;
private:
+ // Holds information about the sysfs device associated with the Device.
struct AssociatedDevice {
- // The device descriptor from evdev device the misc device associated with.
- std::string descriptor;
// The sysfs root path of the misc device.
std::filesystem::path sysfsRootPath;
- int32_t nextBatteryId;
- int32_t nextLightId;
- std::unordered_map<int32_t, RawBatteryInfo> batteryInfos;
- std::unordered_map<int32_t, RawLightInfo> lightInfos;
- explicit AssociatedDevice(std::filesystem::path sysfsRootPath)
- : sysfsRootPath(sysfsRootPath), nextBatteryId(0), nextLightId(0) {}
- bool configureBatteryLocked();
- bool configureLightsLocked();
+ std::unordered_map<int32_t /*batteryId*/, RawBatteryInfo> batteryInfos;
+ std::unordered_map<int32_t /*lightId*/, RawLightInfo> lightInfos;
};
struct Device {
@@ -582,13 +579,13 @@
int16_t ffEffectId; // initially -1
// A shared_ptr of a device associated with the input device.
- // The input devices with same descriptor has the same associated device.
- std::shared_ptr<AssociatedDevice> associatedDevice;
+ // The input devices that have the same sysfs path have the same associated device.
+ const std::shared_ptr<const AssociatedDevice> associatedDevice;
int32_t controllerNumber;
- Device(int fd, int32_t id, const std::string& path,
- const InputDeviceIdentifier& identifier);
+ Device(int fd, int32_t id, std::string path, InputDeviceIdentifier identifier,
+ std::shared_ptr<const AssociatedDevice> assocDev);
~Device();
void close();
@@ -633,6 +630,8 @@
void createVirtualKeyboardLocked() REQUIRES(mLock);
void addDeviceLocked(std::unique_ptr<Device> device) REQUIRES(mLock);
void assignDescriptorLocked(InputDeviceIdentifier& identifier) REQUIRES(mLock);
+ std::shared_ptr<const AssociatedDevice> obtainAssociatedDeviceLocked(
+ const std::filesystem::path& devicePath) const REQUIRES(mLock);
void closeDeviceByPathLocked(const std::string& devicePath) REQUIRES(mLock);
void closeVideoDeviceByPathLocked(const std::string& devicePath) REQUIRES(mLock);
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 17ee54f..924c4d0 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -441,11 +441,6 @@
} else if (getDeviceContext().hasInputProperty(INPUT_PROP_POINTER)) {
// The device is a pointing device like a track pad.
mParameters.deviceType = Parameters::DeviceType::POINTER;
- } else if (getDeviceContext().hasRelativeAxis(REL_X) ||
- getDeviceContext().hasRelativeAxis(REL_Y)) {
- // The device is a cursor device with a touch pad attached.
- // By default don't use the touch pad to move the pointer.
- mParameters.deviceType = Parameters::DeviceType::TOUCH_PAD;
} else {
// The device is a touch pad of unknown purpose.
mParameters.deviceType = Parameters::DeviceType::POINTER;
@@ -458,8 +453,6 @@
deviceTypeString)) {
if (deviceTypeString == "touchScreen") {
mParameters.deviceType = Parameters::DeviceType::TOUCH_SCREEN;
- } else if (deviceTypeString == "touchPad") {
- mParameters.deviceType = Parameters::DeviceType::TOUCH_PAD;
} else if (deviceTypeString == "touchNavigation") {
mParameters.deviceType = Parameters::DeviceType::TOUCH_NAVIGATION;
} else if (deviceTypeString == "pointer") {
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index 3cb11aa..cdf1c7d 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -197,7 +197,6 @@
struct Parameters {
enum class DeviceType {
TOUCH_SCREEN,
- TOUCH_PAD,
TOUCH_NAVIGATION,
POINTER,
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index a0e6192..9a0c565 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -509,7 +509,7 @@
enqueueEvent(ARBITRARY_TIME, READ_TIME, deviceId, EventHubInterface::DEVICE_REMOVED, 0, 0);
}
- bool isDeviceEnabled(int32_t deviceId) {
+ bool isDeviceEnabled(int32_t deviceId) const override {
Device* device = getDevice(deviceId);
if (device == nullptr) {
ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
@@ -518,7 +518,7 @@
return device->enabled;
}
- status_t enableDevice(int32_t deviceId) {
+ status_t enableDevice(int32_t deviceId) override {
status_t result;
Device* device = getDevice(deviceId);
if (device == nullptr) {
@@ -533,7 +533,7 @@
return result;
}
- status_t disableDevice(int32_t deviceId) {
+ status_t disableDevice(int32_t deviceId) override {
Device* device = getDevice(deviceId);
if (device == nullptr) {
ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
@@ -795,8 +795,8 @@
status_t mapAxis(int32_t, int32_t, AxisInfo*) const override { return NAME_NOT_FOUND; }
- base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(int32_t deviceId,
- int32_t absCode) {
+ base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(
+ int32_t deviceId, int32_t absCode) const override {
Device* device = getDevice(deviceId);
if (!device) {
return Errorf("Sensor device not found.");
@@ -981,7 +981,7 @@
void cancelVibrate(int32_t) override {}
- std::vector<int32_t> getVibratorIds(int32_t deviceId) override { return mVibrators; };
+ std::vector<int32_t> getVibratorIds(int32_t deviceId) const override { return mVibrators; };
std::optional<int32_t> getBatteryCapacity(int32_t, int32_t) const override {
return BATTERY_CAPACITY;
@@ -991,13 +991,14 @@
return BATTERY_STATUS;
}
- const std::vector<int32_t> getRawBatteryIds(int32_t deviceId) { return {}; }
+ std::vector<int32_t> getRawBatteryIds(int32_t deviceId) const override { return {}; }
- std::optional<RawBatteryInfo> getRawBatteryInfo(int32_t deviceId, int32_t batteryId) {
+ std::optional<RawBatteryInfo> getRawBatteryInfo(int32_t deviceId,
+ int32_t batteryId) const override {
return std::nullopt;
}
- const std::vector<int32_t> getRawLightIds(int32_t deviceId) override {
+ std::vector<int32_t> getRawLightIds(int32_t deviceId) const override {
std::vector<int32_t> ids;
for (const auto& [rawId, info] : mRawLightInfos) {
ids.push_back(rawId);
@@ -1005,7 +1006,7 @@
return ids;
}
- std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId, int32_t lightId) override {
+ std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId, int32_t lightId) const override {
auto it = mRawLightInfos.find(lightId);
if (it == mRawLightInfos.end()) {
return std::nullopt;
@@ -1022,7 +1023,7 @@
mLightIntensities.emplace(lightId, intensities);
};
- std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) override {
+ std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) const override {
auto lightIt = mLightBrightness.find(lightId);
if (lightIt == mLightBrightness.end()) {
return std::nullopt;
@@ -1031,7 +1032,7 @@
}
std::optional<std::unordered_map<LightColor, int32_t>> getLightIntensities(
- int32_t deviceId, int32_t lightId) override {
+ int32_t deviceId, int32_t lightId) const override {
auto lightIt = mLightIntensities.find(lightId);
if (lightIt == mLightIntensities.end()) {
return std::nullopt;
@@ -1039,13 +1040,9 @@
return lightIt->second;
};
- virtual bool isExternal(int32_t) const {
- return false;
- }
+ void dump(std::string&) const override {}
- void dump(std::string&) override {}
-
- void monitor() override {}
+ void monitor() const override {}
void requestReopenDevices() override {}
@@ -5325,25 +5322,6 @@
ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper.getSources());
}
-TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndIsACursor_ReturnsTouchPad) {
- mFakeEventHub->addRelativeAxis(EVENTHUB_ID, REL_X);
- mFakeEventHub->addRelativeAxis(EVENTHUB_ID, REL_Y);
- prepareButtons();
- prepareAxes(POSITION);
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
-
- ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper.getSources());
-}
-
-TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchPad_ReturnsTouchPad) {
- prepareButtons();
- prepareAxes(POSITION);
- addConfigurationProperty("touch.deviceType", "touchPad");
- SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
-
- ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper.getSources());
-}
-
TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
prepareButtons();
prepareAxes(POSITION);
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index cce6ad7..0cedfc8 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -531,8 +531,6 @@
FrameTracer::FrameEvent::QUEUE);
}
- mDrawingState.width = mDrawingState.buffer->getWidth();
- mDrawingState.height = mDrawingState.buffer->getHeight();
mDrawingState.releaseBufferEndpoint = bufferData.releaseBufferEndpoint;
return true;
}
@@ -622,14 +620,6 @@
return willPresent;
}
-bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) {
- mDrawingState.sequence++;
- mDrawingState.transparentRegionHint = transparent;
- mDrawingState.modified = true;
- setTransactionFlags(eTransactionNeeded);
- return true;
-}
-
Rect BufferStateLayer::getBufferSize(const State& /*s*/) const {
// for buffer state layers we use the display frame size as the buffer size.
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index a0f13e2..a0a52bf 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -116,9 +116,6 @@
void releasePendingBuffer(nsecs_t dequeueReadyTime) override;
- Region getActiveTransparentRegion(const Layer::State& s) const override {
- return s.transparentRegionHint;
- }
Rect getCrop(const Layer::State& s) const;
bool setTransform(uint32_t transform) override;
@@ -137,10 +134,6 @@
bool setPosition(float /*x*/, float /*y*/) override;
bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/);
- // Override to ignore legacy layer state properties that are not used by BufferStateLayer
- bool setSize(uint32_t /*w*/, uint32_t /*h*/) override { return false; }
- bool setTransparentRegionHint(const Region& transparent) override;
-
// BufferStateLayers can return Rect::INVALID_RECT if the layer does not have a display frame
// and its parent layer is not bounded
Rect getBufferSize(const State& s) const override;
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
index 929f9dc..566537b 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
@@ -839,10 +839,7 @@
base::GetBoolProperty(std::string("debug.sf.trace_hint_sessions"), false);
PowerAdvisor::HalWrapper* PowerAdvisor::getPowerHal() {
- static std::unique_ptr<HalWrapper> sHalWrapper = nullptr;
- static bool sHasHal = true;
-
- if (!sHasHal) {
+ if (!mHasHal) {
return nullptr;
}
@@ -850,57 +847,57 @@
std::vector<int32_t> oldPowerHintSessionThreadIds;
std::optional<int64_t> oldTargetWorkDuration;
- if (sHalWrapper != nullptr) {
- oldPowerHintSessionThreadIds = sHalWrapper->getPowerHintSessionThreadIds();
- oldTargetWorkDuration = sHalWrapper->getTargetWorkDuration();
+ if (mHalWrapper != nullptr) {
+ oldPowerHintSessionThreadIds = mHalWrapper->getPowerHintSessionThreadIds();
+ oldTargetWorkDuration = mHalWrapper->getTargetWorkDuration();
}
// If we used to have a HAL, but it stopped responding, attempt to reconnect
if (mReconnectPowerHal) {
- sHalWrapper = nullptr;
+ mHalWrapper = nullptr;
mReconnectPowerHal = false;
}
- if (sHalWrapper != nullptr) {
- auto wrapper = sHalWrapper.get();
+ if (mHalWrapper != nullptr) {
+ auto wrapper = mHalWrapper.get();
// If the wrapper is fine, return it, but if it indicates a reconnect, remake it
if (!wrapper->shouldReconnectHAL()) {
return wrapper;
}
ALOGD("Reconnecting Power HAL");
- sHalWrapper = nullptr;
+ mHalWrapper = nullptr;
}
// At this point, we know for sure there is no running session
mPowerHintSessionRunning = false;
// First attempt to connect to the AIDL Power HAL
- sHalWrapper = AidlPowerHalWrapper::connect();
+ mHalWrapper = AidlPowerHalWrapper::connect();
// If that didn't succeed, attempt to connect to the HIDL Power HAL
- if (sHalWrapper == nullptr) {
- sHalWrapper = HidlPowerHalWrapper::connect();
+ if (mHalWrapper == nullptr) {
+ mHalWrapper = HidlPowerHalWrapper::connect();
} else {
ALOGD("Successfully connecting AIDL Power HAL");
// If AIDL, pass on any existing hint session values
- sHalWrapper->setPowerHintSessionThreadIds(oldPowerHintSessionThreadIds);
+ mHalWrapper->setPowerHintSessionThreadIds(oldPowerHintSessionThreadIds);
// Only set duration and start if duration is defined
if (oldTargetWorkDuration.has_value()) {
- sHalWrapper->setTargetWorkDuration(*oldTargetWorkDuration);
+ mHalWrapper->setTargetWorkDuration(*oldTargetWorkDuration);
// Only start if possible to run and both threadids and duration are defined
if (usePowerHintSession() && !oldPowerHintSessionThreadIds.empty()) {
- mPowerHintSessionRunning = sHalWrapper->startPowerHintSession();
+ mPowerHintSessionRunning = mHalWrapper->startPowerHintSession();
}
}
}
// If we make it to this point and still don't have a HAL, it's unlikely we
// will, so stop trying
- if (sHalWrapper == nullptr) {
- sHasHal = false;
+ if (mHalWrapper == nullptr) {
+ mHasHal = false;
}
- return sHalWrapper.get();
+ return mHalWrapper.get();
}
} // namespace impl
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
index c4a35e0..53db612 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
@@ -154,6 +154,13 @@
void setTotalFrameTargetWorkDuration(nsecs_t targetDuration) override;
private:
+ friend class PowerAdvisorTest;
+
+ // Tracks if powerhal exists
+ bool mHasHal = true;
+ // Holds the hal wrapper for getPowerHal
+ std::unique_ptr<HalWrapper> mHalWrapper GUARDED_BY(mPowerHalMutex) = nullptr;
+
HalWrapper* getPowerHal() REQUIRES(mPowerHalMutex);
bool mReconnectPowerHal GUARDED_BY(mPowerHalMutex) = false;
std::mutex mPowerHalMutex;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index dfff8fe..8a401eb 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -111,16 +111,11 @@
sSequence = *args.sequence + 1;
}
mDrawingState.flags = layerFlags;
- mDrawingState.active_legacy.transform.set(0, 0);
mDrawingState.crop.makeInvalid();
- mDrawingState.requestedCrop = mDrawingState.crop;
mDrawingState.z = 0;
mDrawingState.color.a = 1.0f;
mDrawingState.layerStack = ui::DEFAULT_LAYER_STACK;
mDrawingState.sequence = 0;
- mDrawingState.requested_legacy = mDrawingState.active_legacy;
- mDrawingState.width = UINT32_MAX;
- mDrawingState.height = UINT32_MAX;
mDrawingState.transform.set(0, 0);
mDrawingState.frameNumber = 0;
mDrawingState.bufferTransform = 0;
@@ -875,20 +870,6 @@
return (p != nullptr) && p->isTrustedOverlay();
}
-bool Layer::setSize(uint32_t w, uint32_t h) {
- if (mDrawingState.requested_legacy.w == w && mDrawingState.requested_legacy.h == h)
- return false;
- mDrawingState.requested_legacy.w = w;
- mDrawingState.requested_legacy.h = h;
- mDrawingState.modified = true;
- setTransactionFlags(eTransactionNeeded);
-
- // record the new size, from this point on, when the client request
- // a buffer, it'll get the new size.
- setDefaultBufferSize(mDrawingState.requested_legacy.w, mDrawingState.requested_legacy.h);
- return true;
-}
-
bool Layer::setAlpha(float alpha) {
if (mDrawingState.color.a == alpha) return false;
mDrawingState.sequence++;
@@ -978,7 +959,8 @@
}
bool Layer::setTransparentRegionHint(const Region& transparent) {
- mDrawingState.requestedTransparentRegion_legacy = transparent;
+ mDrawingState.sequence++;
+ mDrawingState.transparentRegionHint = transparent;
mDrawingState.modified = true;
setTransactionFlags(eTransactionNeeded);
return true;
@@ -1007,9 +989,8 @@
}
bool Layer::setCrop(const Rect& crop) {
- if (mDrawingState.requestedCrop == crop) return false;
+ if (mDrawingState.crop == crop) return false;
mDrawingState.sequence++;
- mDrawingState.requestedCrop = crop;
mDrawingState.crop = crop;
mDrawingState.modified = true;
@@ -1433,7 +1414,6 @@
sp<Layer> parent = mDrawingParent.promote();
info.mParentName = parent ? parent->getName() : "none"s;
info.mType = getType();
- info.mTransparentRegion = ds.activeTransparentRegion_legacy;
info.mVisibleRegion = getVisibleRegion(display);
info.mSurfaceDamageRegion = surfaceDamageRegion;
@@ -1441,8 +1421,6 @@
info.mX = ds.transform.tx();
info.mY = ds.transform.ty();
info.mZ = ds.z;
- info.mWidth = ds.width;
- info.mHeight = ds.height;
info.mCrop = ds.crop;
info.mColor = ds.color;
info.mFlags = ds.flags;
@@ -2141,7 +2119,7 @@
}
}
- LayerProtoHelper::writeToProto(state.activeTransparentRegion_legacy,
+ LayerProtoHelper::writeToProto(state.transparentRegionHint,
[&]() { return layerInfo->mutable_transparent_region(); });
layerInfo->set_layer_stack(getLayerStack().id);
@@ -2151,9 +2129,6 @@
return layerInfo->mutable_requested_position();
});
- LayerProtoHelper::writeSizeToProto(state.width, state.height,
- [&]() { return layerInfo->mutable_size(); });
-
LayerProtoHelper::writeToProto(state.crop, [&]() { return layerInfo->mutable_crop(); });
layerInfo->set_is_opaque(isOpaque(state));
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 6e83b23..b05a4a0 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -150,40 +150,23 @@
using FrameRateCompatibility = scheduler::LayerInfo::FrameRateCompatibility;
struct State {
- Geometry active_legacy;
- Geometry requested_legacy;
int32_t z;
-
ui::LayerStack layerStack;
-
uint32_t flags;
- uint8_t reserved[2];
int32_t sequence; // changes when visible regions can change
bool modified;
-
// Crop is expressed in layer space coordinate.
Rect crop;
- Rect requestedCrop;
-
- // the transparentRegion hint is a bit special, it's latched only
- // when we receive a buffer -- this is because it's "content"
- // dependent.
- Region activeTransparentRegion_legacy;
- Region requestedTransparentRegion_legacy;
-
LayerMetadata metadata;
-
// If non-null, a Surface this Surface's Z-order is interpreted relative to.
wp<Layer> zOrderRelativeOf;
bool isRelativeOf{false};
// A list of surfaces whose Z-order is interpreted relative to ours.
SortedVector<wp<Layer>> zOrderRelatives;
-
half4 color;
float cornerRadius;
int backgroundBlurRadius;
-
gui::WindowInfo inputInfo;
wp<Layer> touchableRegionCrop;
@@ -192,15 +175,10 @@
// The fields below this point are only used by BufferStateLayer
uint64_t frameNumber;
- uint32_t width;
- uint32_t height;
ui::Transform transform;
-
uint32_t bufferTransform;
bool transformToDisplayInverse;
-
Region transparentRegionHint;
-
std::shared_ptr<renderengine::ExternalTexture> buffer;
client_cache_t clientCacheId;
sp<Fence> acquireFence;
@@ -208,11 +186,9 @@
HdrMetadata hdrMetadata;
Region surfaceDamageRegion;
int32_t api;
-
sp<NativeHandle> sidebandStream;
mat4 colorTransform;
bool hasColorTransform;
-
// pointer to background color layer that, if set, appears below the buffer state layer
// and the buffer state layer's children. Z order will be set to
// INT_MIN
@@ -237,7 +213,6 @@
// Default frame rate compatibility used to set the layer refresh rate votetype.
FrameRateCompatibility defaultFrameRateCompatibility;
-
FrameRate frameRate;
// The combined frame rate of parents / children of this layer
@@ -257,7 +232,6 @@
// When the transaction was posted
nsecs_t postTime;
-
sp<ITransactionCompletedListener> releaseBufferListener;
// SurfaceFrame that tracks the timeline of Transactions that contain a Buffer. Only one
// such SurfaceFrame exists because only one buffer can be presented on the layer per vsync.
@@ -278,16 +252,11 @@
// Whether or not this layer is a trusted overlay for input
bool isTrustedOverlay;
-
Rect bufferCrop;
Rect destinationFrame;
-
sp<IBinder> releaseBufferEndpoint;
-
gui::DropInputMode dropInputMode;
-
bool autoRefresh = false;
-
bool dimmingEnabled = true;
};
@@ -345,32 +314,6 @@
virtual sp<Layer> createClone() = 0;
- // Geometry setting functions.
- //
- // The following group of functions are used to specify the layers
- // bounds, and the mapping of the texture on to those bounds. According
- // to various settings changes to them may apply immediately, or be delayed until
- // a pending resize is completed by the producer submitting a buffer. For example
- // if we were to change the buffer size, and update the matrix ahead of the
- // new buffer arriving, then we would be stretching the buffer to a different
- // aspect before and after the buffer arriving, which probably isn't what we wanted.
- //
- // The first set of geometry functions are controlled by the scaling mode, described
- // in window.h. The scaling mode may be set by the client, as it submits buffers.
- //
- // Put simply, if our scaling mode is SCALING_MODE_FREEZE, then
- // matrix updates will not be applied while a resize is pending
- // and the size and transform will remain in their previous state
- // until a new buffer is submitted. If the scaling mode is another value
- // then the old-buffer will immediately be scaled to the pending size
- // and the new matrix will be immediately applied following this scaling
- // transformation.
-
- // Set the default buffer size for the assosciated Producer, in pixels. This is
- // also the rendered size of the layer prior to any transformations. Parent
- // or local matrix transformations will not affect the size of the buffer,
- // but may affect it's on-screen size or clipping.
- virtual bool setSize(uint32_t w, uint32_t h);
// Set a 2x2 transformation matrix on the layer. This transform
// will be applied after parent transforms, but before any final
// producer specified transform.
@@ -407,7 +350,7 @@
// is specified in pixels.
virtual bool setBackgroundBlurRadius(int backgroundBlurRadius);
virtual bool setBlurRegions(const std::vector<BlurRegion>& effectRegions);
- virtual bool setTransparentRegionHint(const Region& transparent);
+ bool setTransparentRegionHint(const Region& transparent);
virtual bool setTrustedOverlay(bool);
virtual bool setFlags(uint32_t flags, uint32_t mask);
virtual bool setLayerStack(ui::LayerStack);
@@ -500,11 +443,9 @@
// to avoid grabbing the lock again to avoid deadlock
virtual bool isCreatedFromMainThread() const { return false; }
- uint32_t getActiveWidth(const Layer::State& s) const { return s.width; }
- uint32_t getActiveHeight(const Layer::State& s) const { return s.height; }
ui::Transform getActiveTransform(const Layer::State& s) const { return s.transform; }
- virtual Region getActiveTransparentRegion(const Layer::State& s) const {
- return s.activeTransparentRegion_legacy;
+ Region getActiveTransparentRegion(const Layer::State& s) const {
+ return s.transparentRegionHint;
}
virtual Rect getCrop(const Layer::State& s) const { return s.crop; }
virtual bool needsFiltering(const DisplayDevice*) const { return false; }
@@ -524,8 +465,6 @@
virtual void updateCloneBufferInfo(){};
- virtual void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) {}
-
virtual bool isHdrY410() const { return false; }
/*
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 704cfc7..e1fcaa0 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3247,10 +3247,11 @@
mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
if (!layer->needsInputInfo()) return;
- const auto opt = displayInputInfos.get(layer->getLayerStack(),
- [](const auto& info) -> Layer::InputDisplayArgs {
- return {&info.transform, info.isSecure};
- });
+ const auto opt = displayInputInfos.get(layer->getLayerStack())
+ .transform([](const DisplayDevice::InputInfo& info) {
+ return Layer::InputDisplayArgs{&info.transform, info.isSecure};
+ });
+
outWindowInfos.push_back(layer->fillInputInfo(opt.value_or(Layer::InputDisplayArgs{})));
});
@@ -4255,11 +4256,6 @@
}
}
}
- if (what & layer_state_t::eSizeChanged) {
- if (layer->setSize(s.w, s.h)) {
- flags |= eTraversalNeeded;
- }
- }
if (what & layer_state_t::eAlphaChanged) {
if (layer->setAlpha(s.alpha))
flags |= eTraversalNeeded;
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index 66691c2..6797aa6 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -135,8 +135,6 @@
layer->mDrawingState.transform.ty());
addDepthLocked(transaction, layerId, layer->mDrawingState.z);
addAlphaLocked(transaction, layerId, layer->mDrawingState.color.a);
- addTransparentRegionLocked(transaction, layerId,
- layer->mDrawingState.activeTransparentRegion_legacy);
addLayerStackLocked(transaction, layerId, layer->mDrawingState.layerStack);
addCropLocked(transaction, layerId, layer->mDrawingState.crop);
addCornerRadiusLocked(transaction, layerId, layer->mDrawingState.cornerRadius);
@@ -420,9 +418,6 @@
if (state.what & layer_state_t::eLayerChanged) {
addDepthLocked(transaction, layerId, state.z);
}
- if (state.what & layer_state_t::eSizeChanged) {
- addSizeLocked(transaction, layerId, state.w, state.h);
- }
if (state.what & layer_state_t::eAlphaChanged) {
addAlphaLocked(transaction, layerId, state.alpha);
}
@@ -522,8 +517,6 @@
SurfaceCreation* creation(increment->mutable_surface_creation());
creation->set_id(getLayerId(layer));
creation->set_name(layer->getName());
- creation->set_w(layer->mDrawingState.active_legacy.w);
- creation->set_h(layer->mDrawingState.active_legacy.h);
}
void SurfaceInterceptor::addSurfaceDeletionLocked(Increment* increment,
diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
index 77dec6f..dcc529e 100644
--- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
+++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
@@ -88,10 +88,7 @@
if (layer.what & layer_state_t::eLayerChanged) {
proto.set_z(layer.z);
}
- if (layer.what & layer_state_t::eSizeChanged) {
- proto.set_w(layer.w);
- proto.set_h(layer.h);
- }
+
if (layer.what & layer_state_t::eLayerStackChanged) {
proto.set_layer_stack(layer.layerStack.id);
}
@@ -376,10 +373,6 @@
if (proto.what() & layer_state_t::eLayerChanged) {
layer.z = proto.z();
}
- if (proto.what() & layer_state_t::eSizeChanged) {
- layer.w = proto.w();
- layer.h = proto.h();
- }
if (proto.what() & layer_state_t::eLayerStackChanged) {
layer.layerStack.id = proto.layer_stack();
}
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
index f507ef0..9584492 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
@@ -379,7 +379,8 @@
RefreshRateStats refreshRateStats(timeStats, Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()),
PowerMode::OFF);
- const auto fpsOpt = displayModes.get(modeId, [](const auto& mode) { return mode->getFps(); });
+ const auto fpsOpt = displayModes.get(modeId).transform(
+ [](const DisplayModePtr& mode) { return mode->getFps(); });
refreshRateStats.setRefreshRate(*fpsOpt);
refreshRateStats.setPowerMode(mFdp.PickValueInArray(kPowerModes));
diff --git a/services/surfaceflinger/layerproto/transactions.proto b/services/surfaceflinger/layerproto/transactions.proto
index 49487ee..b687abc 100644
--- a/services/surfaceflinger/layerproto/transactions.proto
+++ b/services/surfaceflinger/layerproto/transactions.proto
@@ -82,7 +82,7 @@
eChangesLsbNone = 0;
ePositionChanged = 0x00000001;
eLayerChanged = 0x00000002;
- eSizeChanged = 0x00000004;
+ // unused = 0x00000004;
eAlphaChanged = 0x00000008;
eMatrixChanged = 0x00000010;
diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h
index 4b91605..0e8f3dd 100644
--- a/services/surfaceflinger/tests/LayerTransactionTest.h
+++ b/services/surfaceflinger/tests/LayerTransactionTest.h
@@ -233,7 +233,7 @@
Rect(halfW, halfH, bufferWidth, bufferHeight),
bottomRight);
- Transaction().setBuffer(layer, buffer).setSize(layer, bufferWidth, bufferHeight).apply();
+ Transaction().setBuffer(layer, buffer).apply();
}
std::unique_ptr<ScreenCapture> screenshot() {
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index 8dcd013..d79e592 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -140,6 +140,7 @@
mComposerClient = sp<SurfaceComposerClient>::make();
ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
+ GTEST_SKIP();
}
void TearDown() override {
@@ -342,9 +343,7 @@
t.setPosition(mBGSurfaceControl, POSITION_UPDATE, POSITION_UPDATE);
}
-void SurfaceInterceptorTest::sizeUpdate(Transaction& t) {
- t.setSize(mBGSurfaceControl, SIZE_UPDATE, SIZE_UPDATE);
-}
+void SurfaceInterceptorTest::sizeUpdate(Transaction&) {}
void SurfaceInterceptorTest::alphaUpdate(Transaction& t) {
t.setAlpha(mBGSurfaceControl, ALPHA_UPDATE);
@@ -472,15 +471,8 @@
return foundPosition;
}
-bool SurfaceInterceptorTest::sizeUpdateFound(const SurfaceChange& change, bool foundSize) {
- bool hasWidth(change.size().h() == SIZE_UPDATE);
- bool hasHeight(change.size().w() == SIZE_UPDATE);
- if (hasWidth && hasHeight && !foundSize) {
- foundSize = true;
- } else if (hasWidth && hasHeight && foundSize) {
- [] () { FAIL(); }();
- }
- return foundSize;
+bool SurfaceInterceptorTest::sizeUpdateFound(const SurfaceChange&, bool) {
+ return true;
}
bool SurfaceInterceptorTest::alphaUpdateFound(const SurfaceChange& change, bool foundAlpha) {
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 7823363..004f31c 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -24,6 +24,7 @@
filegroup {
name: "libsurfaceflinger_mock_sources",
srcs: [
+ "mock/DisplayHardware/MockAidlPowerHalWrapper.cpp",
"mock/DisplayHardware/MockComposer.cpp",
"mock/DisplayHardware/MockHWC2.cpp",
"mock/DisplayHardware/MockIPower.cpp",
@@ -95,6 +96,7 @@
"LayerTest.cpp",
"LayerTestUtils.cpp",
"MessageQueueTest.cpp",
+ "PowerAdvisorTest.cpp",
"SurfaceFlinger_CreateDisplayTest.cpp",
"SurfaceFlinger_DestroyDisplayTest.cpp",
"SurfaceFlinger_DisplayModeSwitching.cpp",
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 2571e3a..0666561 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -828,8 +828,6 @@
static void initLayerDrawingStateAndComputeBounds(CompositionTest* test, sp<L> layer) {
auto& layerDrawingState = test->mFlinger.mutableLayerDrawingState(layer);
layerDrawingState.layerStack = LAYER_STACK;
- layerDrawingState.width = 100;
- layerDrawingState.height = 100;
layerDrawingState.color = half4(LayerProperties::COLOR[0], LayerProperties::COLOR[1],
LayerProperties::COLOR[2], LayerProperties::COLOR[3]);
layer->computeBounds(FloatRect(0, 0, 100, 100), ui::Transform(), 0.f /* shadowRadius */);
diff --git a/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp b/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
new file mode 100644
index 0000000..8711a42
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
@@ -0,0 +1,203 @@
+/*
+ * Copyright 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 "PowerAdvisorTest"
+
+#include <DisplayHardware/PowerAdvisor.h>
+#include <compositionengine/Display.h>
+#include <ftl/fake_guard.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <ui/DisplayId.h>
+#include <chrono>
+#include "TestableSurfaceFlinger.h"
+#include "mock/DisplayHardware/MockAidlPowerHalWrapper.h"
+
+using namespace android;
+using namespace android::Hwc2::mock;
+using namespace android::hardware::power;
+using namespace std::chrono_literals;
+using namespace testing;
+
+namespace android::Hwc2::impl {
+
+class PowerAdvisorTest : public testing::Test {
+public:
+ void SetUp() override;
+ void startPowerHintSession();
+ void fakeBasicFrameTiming(nsecs_t startTime, nsecs_t vsyncPeriod);
+ void setExpectedTiming(nsecs_t startTime, nsecs_t vsyncPeriod);
+ nsecs_t getFenceWaitDelayDuration(bool skipValidate);
+
+protected:
+ TestableSurfaceFlinger mFlinger;
+ std::unique_ptr<PowerAdvisor> mPowerAdvisor;
+ NiceMock<MockAidlPowerHalWrapper>* mMockAidlWrapper;
+ nsecs_t kErrorMargin = std::chrono::nanoseconds(1ms).count();
+};
+
+void PowerAdvisorTest::SetUp() FTL_FAKE_GUARD(mPowerAdvisor->mPowerHalMutex) {
+ std::unique_ptr<MockAidlPowerHalWrapper> mockAidlWrapper =
+ std::make_unique<NiceMock<MockAidlPowerHalWrapper>>();
+ mPowerAdvisor = std::make_unique<PowerAdvisor>(*mFlinger.flinger());
+ ON_CALL(*mockAidlWrapper.get(), supportsPowerHintSession()).WillByDefault(Return(true));
+ ON_CALL(*mockAidlWrapper.get(), startPowerHintSession()).WillByDefault(Return(true));
+ mPowerAdvisor->mHalWrapper = std::move(mockAidlWrapper);
+ mMockAidlWrapper =
+ reinterpret_cast<NiceMock<MockAidlPowerHalWrapper>*>(mPowerAdvisor->mHalWrapper.get());
+}
+
+void PowerAdvisorTest::startPowerHintSession() {
+ const std::vector<int32_t> threadIds = {1, 2, 3};
+ mPowerAdvisor->enablePowerHint(true);
+ mPowerAdvisor->startPowerHintSession(threadIds);
+}
+
+void PowerAdvisorTest::setExpectedTiming(nsecs_t totalFrameTarget, nsecs_t expectedPresentTime) {
+ mPowerAdvisor->setTotalFrameTargetWorkDuration(totalFrameTarget);
+ mPowerAdvisor->setExpectedPresentTime(expectedPresentTime);
+}
+
+void PowerAdvisorTest::fakeBasicFrameTiming(nsecs_t startTime, nsecs_t vsyncPeriod) {
+ mPowerAdvisor->setCommitStart(startTime);
+ mPowerAdvisor->setFrameDelay(0);
+ mPowerAdvisor->setTargetWorkDuration(vsyncPeriod);
+}
+
+nsecs_t PowerAdvisorTest::getFenceWaitDelayDuration(bool skipValidate) {
+ return (skipValidate ? PowerAdvisor::kFenceWaitStartDelaySkippedValidate
+ : PowerAdvisor::kFenceWaitStartDelayValidated)
+ .count();
+}
+
+namespace {
+
+TEST_F(PowerAdvisorTest, hintSessionUseHwcDisplay) {
+ mPowerAdvisor->onBootFinished();
+ startPowerHintSession();
+
+ std::vector<DisplayId> displayIds{PhysicalDisplayId::fromPort(42u)};
+
+ // 60hz
+ const nsecs_t vsyncPeriod = std::chrono::nanoseconds(1s).count() / 60;
+ const nsecs_t presentDuration = std::chrono::nanoseconds(5ms).count();
+ const nsecs_t postCompDuration = std::chrono::nanoseconds(1ms).count();
+
+ nsecs_t startTime = 100;
+
+ // advisor only starts on frame 2 so do an initial no-op frame
+ fakeBasicFrameTiming(startTime, vsyncPeriod);
+ setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
+ mPowerAdvisor->setDisplays(displayIds);
+ mPowerAdvisor->setSfPresentTiming(startTime, startTime + presentDuration);
+ mPowerAdvisor->setCompositeEnd(startTime + presentDuration + postCompDuration);
+
+ // increment the frame
+ startTime += vsyncPeriod;
+
+ const nsecs_t expectedDuration = kErrorMargin + presentDuration + postCompDuration;
+ EXPECT_CALL(*mMockAidlWrapper, sendActualWorkDuration(Eq(expectedDuration), _)).Times(1);
+
+ fakeBasicFrameTiming(startTime, vsyncPeriod);
+ setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
+ mPowerAdvisor->setDisplays(displayIds);
+ mPowerAdvisor->setHwcValidateTiming(displayIds[0], startTime + 1000000, startTime + 1500000);
+ mPowerAdvisor->setHwcPresentTiming(displayIds[0], startTime + 2000000, startTime + 2500000);
+ mPowerAdvisor->setSfPresentTiming(startTime, startTime + presentDuration);
+ mPowerAdvisor->sendActualWorkDuration();
+}
+
+TEST_F(PowerAdvisorTest, hintSessionSubtractsHwcFenceTime) {
+ mPowerAdvisor->onBootFinished();
+ startPowerHintSession();
+
+ std::vector<DisplayId> displayIds{PhysicalDisplayId::fromPort(42u)};
+
+ // 60hz
+ const nsecs_t vsyncPeriod = std::chrono::nanoseconds(1s).count() / 60;
+ const nsecs_t presentDuration = std::chrono::nanoseconds(5ms).count();
+ const nsecs_t postCompDuration = std::chrono::nanoseconds(1ms).count();
+ const nsecs_t hwcBlockedDuration = std::chrono::nanoseconds(500us).count();
+
+ nsecs_t startTime = 100;
+
+ // advisor only starts on frame 2 so do an initial no-op frame
+ fakeBasicFrameTiming(startTime, vsyncPeriod);
+ setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
+ mPowerAdvisor->setDisplays(displayIds);
+ mPowerAdvisor->setSfPresentTiming(startTime, startTime + presentDuration);
+ mPowerAdvisor->setCompositeEnd(startTime + presentDuration + postCompDuration);
+
+ // increment the frame
+ startTime += vsyncPeriod;
+
+ const nsecs_t expectedDuration = kErrorMargin + presentDuration +
+ getFenceWaitDelayDuration(false) - hwcBlockedDuration + postCompDuration;
+ EXPECT_CALL(*mMockAidlWrapper, sendActualWorkDuration(Eq(expectedDuration), _)).Times(1);
+
+ fakeBasicFrameTiming(startTime, vsyncPeriod);
+ setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
+ mPowerAdvisor->setDisplays(displayIds);
+ mPowerAdvisor->setHwcValidateTiming(displayIds[0], startTime + 1000000, startTime + 1500000);
+ mPowerAdvisor->setHwcPresentTiming(displayIds[0], startTime + 2000000, startTime + 3000000);
+ // now report the fence as having fired during the display HWC time
+ mPowerAdvisor->setSfPresentTiming(startTime + 2000000 + hwcBlockedDuration,
+ startTime + presentDuration);
+ mPowerAdvisor->sendActualWorkDuration();
+}
+
+TEST_F(PowerAdvisorTest, hintSessionUsingSecondaryVirtualDisplays) {
+ mPowerAdvisor->onBootFinished();
+ startPowerHintSession();
+
+ std::vector<DisplayId> displayIds{PhysicalDisplayId::fromPort(42u), GpuVirtualDisplayId(0),
+ GpuVirtualDisplayId(1)};
+
+ // 60hz
+ const nsecs_t vsyncPeriod = std::chrono::nanoseconds(1s).count() / 60;
+ // make present duration much later than the hwc display by itself will account for
+ const nsecs_t presentDuration = std::chrono::nanoseconds(10ms).count();
+ const nsecs_t postCompDuration = std::chrono::nanoseconds(1ms).count();
+
+ nsecs_t startTime = 100;
+
+ // advisor only starts on frame 2 so do an initial no-op frame
+ fakeBasicFrameTiming(startTime, vsyncPeriod);
+ setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
+ mPowerAdvisor->setDisplays(displayIds);
+ mPowerAdvisor->setSfPresentTiming(startTime, startTime + presentDuration);
+ mPowerAdvisor->setCompositeEnd(startTime + presentDuration + postCompDuration);
+
+ // increment the frame
+ startTime += vsyncPeriod;
+
+ const nsecs_t expectedDuration = kErrorMargin + presentDuration + postCompDuration;
+ EXPECT_CALL(*mMockAidlWrapper, sendActualWorkDuration(Eq(expectedDuration), _)).Times(1);
+
+ fakeBasicFrameTiming(startTime, vsyncPeriod);
+ setExpectedTiming(vsyncPeriod, startTime + vsyncPeriod);
+ mPowerAdvisor->setDisplays(displayIds);
+
+ // don't report timing for the gpu displays since they don't use hwc
+ mPowerAdvisor->setHwcValidateTiming(displayIds[0], startTime + 1000000, startTime + 1500000);
+ mPowerAdvisor->setHwcPresentTiming(displayIds[0], startTime + 2000000, startTime + 2500000);
+ mPowerAdvisor->setSfPresentTiming(startTime, startTime + presentDuration);
+ mPowerAdvisor->sendActualWorkDuration();
+}
+
+} // namespace
+} // namespace android::Hwc2::impl
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockAidlPowerHalWrapper.cpp b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockAidlPowerHalWrapper.cpp
new file mode 100644
index 0000000..5049b1d
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockAidlPowerHalWrapper.cpp
@@ -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.
+ */
+
+#include "MockAidlPowerHalWrapper.h"
+#include "MockIPower.h"
+
+namespace android::Hwc2::mock {
+
+MockAidlPowerHalWrapper::MockAidlPowerHalWrapper()
+ : AidlPowerHalWrapper(sp<testing::NiceMock<MockIPower>>::make()){};
+MockAidlPowerHalWrapper::~MockAidlPowerHalWrapper() = default;
+
+} // namespace android::Hwc2::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockAidlPowerHalWrapper.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockAidlPowerHalWrapper.h
new file mode 100644
index 0000000..657ced3
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockAidlPowerHalWrapper.h
@@ -0,0 +1,51 @@
+/*
+ * 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 <gmock/gmock.h>
+
+#include "DisplayHardware/PowerAdvisor.h"
+
+namespace android {
+namespace hardware {
+namespace power {
+class IPower;
+}
+} // namespace hardware
+} // namespace android
+
+namespace android::Hwc2::mock {
+
+class MockAidlPowerHalWrapper : public Hwc2::impl::AidlPowerHalWrapper {
+public:
+ MockAidlPowerHalWrapper();
+ ~MockAidlPowerHalWrapper() override;
+ MOCK_METHOD(bool, setExpensiveRendering, (bool enabled), (override));
+ MOCK_METHOD(bool, notifyDisplayUpdateImminent, (), (override));
+ MOCK_METHOD(bool, supportsPowerHintSession, (), (override));
+ MOCK_METHOD(bool, isPowerHintSessionRunning, (), (override));
+ MOCK_METHOD(void, restartPowerHintSession, (), (override));
+ MOCK_METHOD(void, setPowerHintSessionThreadIds, (const std::vector<int32_t>& threadIds),
+ (override));
+ MOCK_METHOD(bool, startPowerHintSession, (), (override));
+ MOCK_METHOD(void, setTargetWorkDuration, (nsecs_t targetDuration), (override));
+ MOCK_METHOD(void, sendActualWorkDuration, (nsecs_t actualDuration, nsecs_t timestamp),
+ (override));
+ MOCK_METHOD(bool, shouldReconnectHAL, (), (override));
+};
+
+} // namespace android::Hwc2::mock
\ No newline at end of file
diff --git a/services/vibratorservice/Android.bp b/services/vibratorservice/Android.bp
index 2002bdf..5403baf 100644
--- a/services/vibratorservice/Android.bp
+++ b/services/vibratorservice/Android.bp
@@ -59,6 +59,12 @@
"-Wunreachable-code",
],
+ // FIXME: Workaround LTO build breakage
+ // http://b/241699694
+ lto: {
+ never: true,
+ },
+
local_include_dirs: ["include"],
export_include_dirs: ["include"],
diff --git a/services/vibratorservice/test/Android.bp b/services/vibratorservice/test/Android.bp
index adba3db..3294724 100644
--- a/services/vibratorservice/test/Android.bp
+++ b/services/vibratorservice/test/Android.bp
@@ -57,9 +57,4 @@
static_libs: [
"libgmock",
],
- // FIXME: Workaround LTO build breakage
- // http://b/241699694
- lto: {
- never: true,
- },
}
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 0a33760..1815c46 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -763,7 +763,11 @@
// We must support R8G8B8A8
std::vector<VkSurfaceFormatKHR> all_formats = {
{VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
- {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}};
+ {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
+ // Also allow to use PASS_THROUGH + HAL_DATASPACE_ARBITRARY
+ {VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_PASS_THROUGH_EXT},
+ {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_PASS_THROUGH_EXT},
+ };
if (colorspace_ext) {
all_formats.emplace_back(VkSurfaceFormatKHR{