Merge "Add deprecation message." into main
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index 23f33d8..4a77967 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -79,7 +79,10 @@
 
 cc_defaults {
     name: "dumpstate_defaults",
-    defaults: ["dumpstate_cflag_defaults"],
+    defaults: [
+        "aconfig_lib_cc_static_link.defaults",
+        "dumpstate_cflag_defaults",
+    ],
     shared_libs: [
         "android.hardware.dumpstate@1.0",
         "android.hardware.dumpstate@1.1",
diff --git a/services/inputflinger/BlockingQueue.h b/include/input/BlockingQueue.h
similarity index 100%
rename from services/inputflinger/BlockingQueue.h
rename to include/input/BlockingQueue.h
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 57a48d7..090e35b 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -446,7 +446,7 @@
     },
 }
 
-cc_library_static {
+cc_library {
     name: "libbinder_rpc_no_kernel",
     vendor_available: true,
     defaults: [
@@ -458,7 +458,7 @@
     ],
 }
 
-cc_library_static {
+cc_library {
     name: "libbinder_rpc_no_blob",
     vendor_available: true,
     defaults: [
@@ -474,7 +474,7 @@
     ],
 }
 
-cc_library_static {
+cc_library {
     name: "libbinder_rpc_no_native_handle",
     vendor_available: true,
     defaults: [
@@ -490,7 +490,7 @@
     ],
 }
 
-cc_library_static {
+cc_library {
     name: "libbinder_rpc_single_threaded",
     defaults: [
         "libbinder_common_defaults",
@@ -505,7 +505,7 @@
     ],
 }
 
-cc_library_static {
+cc_library {
     name: "libbinder_rpc_single_threaded_no_kernel",
     defaults: [
         "libbinder_common_defaults",
diff --git a/libs/binder/liblog_stub/include/log/log.h b/libs/binder/liblog_stub/include/log/log.h
index 91c9632..dad0020 100644
--- a/libs/binder/liblog_stub/include/log/log.h
+++ b/libs/binder/liblog_stub/include/log/log.h
@@ -54,16 +54,16 @@
 #define IF_ALOGW() IF_ALOG(LOG_WARN, LOG_TAG)
 #define IF_ALOGE() IF_ALOG(LOG_ERROR, LOG_TAG)
 
-#define ALOG(priority, tag, fmt, ...)                                          \
-    do {                                                                       \
-        if (false)[[/*VERY*/ unlikely]] { /* ignore unused __VA_ARGS__ */      \
-            std::fprintf(stderr, fmt __VA_OPT__(, ) __VA_ARGS__);              \
-        }                                                                      \
-        IF_ALOG(priority, tag) {                                               \
-            __android_log_print(ANDROID_##priority, tag,                       \
-                                tag ": " fmt "\n" __VA_OPT__(, ) __VA_ARGS__); \
-        }                                                                      \
-        if constexpr (ANDROID_##priority == ANDROID_LOG_FATAL) std::abort();   \
+#define ALOG(priority, tag, fmt, ...)                                        \
+    do {                                                                     \
+        if (false)[[/*VERY*/ unlikely]] { /* ignore unused __VA_ARGS__ */    \
+            std::fprintf(stderr, fmt __VA_OPT__(, ) __VA_ARGS__);            \
+        }                                                                    \
+        IF_ALOG(priority, tag) {                                             \
+            __android_log_print(ANDROID_##priority, tag, "%s: " fmt "\n",    \
+                                (tag)__VA_OPT__(, ) __VA_ARGS__);            \
+        }                                                                    \
+        if constexpr (ANDROID_##priority == ANDROID_LOG_FATAL) std::abort(); \
     } while (false)
 #define ALOGV(...) ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
 #define ALOGD(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
index c665ad8..52edae4 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -18,11 +18,8 @@
 
 #include <android/binder_ibinder.h>
 #include <android/binder_status.h>
-#include <sys/cdefs.h>
-
-#ifndef __TRUSTY__
 #include <android/llndk-versioning.h>
-#endif
+#include <sys/cdefs.h>
 
 __BEGIN_DECLS
 
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 35002eb..6800a8d 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -200,9 +200,11 @@
     defaults: [
         "binder_test_defaults",
     ],
+    header_libs: [
+        "libbinder_headers_base",
+    ],
     shared_libs: [
         "libbase",
-        "liblog",
     ],
     srcs: [
         "FileUtils.cpp",
diff --git a/libs/binder/tests/binderThroughputTest.cpp b/libs/binder/tests/binderThroughputTest.cpp
index 10912c7..f912348 100644
--- a/libs/binder/tests/binderThroughputTest.cpp
+++ b/libs/binder/tests/binderThroughputTest.cpp
@@ -7,9 +7,10 @@
 #include <cstdlib>
 #include <cstdio>
 
+#include <fstream>
 #include <iostream>
-#include <vector>
 #include <tuple>
+#include <vector>
 
 #include <unistd.h>
 #include <sys/wait.h>
@@ -63,6 +64,18 @@
     uint64_t worst() {
         return *max_element(data.begin(), data.end());
     }
+    void dump_to_file(string filename) {
+        ofstream output;
+        output.open(filename);
+        if (!output.is_open()) {
+            cerr << "Failed to open '" << filename << "'." << endl;
+            exit(EXIT_FAILURE);
+        }
+        for (uint64_t value : data) {
+            output << value << "\n";
+        }
+        output.close();
+    }
     void dump() {
         if (data.size() == 0) {
             // This avoids index-out-of-bounds below.
@@ -293,12 +306,8 @@
     }
 }
 
-void run_main(int iterations,
-              int workers,
-              int payload_size,
-              int cs_pair,
-              bool training_round=false)
-{
+void run_main(int iterations, int workers, int payload_size, int cs_pair,
+              bool training_round = false, bool dump_to_file = false, string dump_filename = "") {
     vector<Pipe> pipes;
     // Create all the workers and wait for them to spawn.
     for (int i = 0; i < workers; i++) {
@@ -349,6 +358,9 @@
         warn_latency = 2 * tot_results.worst();
         cout << "Max latency during training: " << tot_results.worst() / 1.0E6 << "ms" << endl;
     } else {
+        if (dump_to_file) {
+            tot_results.dump_to_file(dump_filename);
+        }
         tot_results.dump();
     }
 }
@@ -361,6 +373,8 @@
     bool cs_pair = false;
     bool training_round = false;
     int max_time_us;
+    bool dump_to_file = false;
+    string dump_filename;
 
     // Parse arguments.
     for (int i = 1; i < argc; i++) {
@@ -372,6 +386,7 @@
             cout << "\t-s N    : Specify payload size." << endl;
             cout << "\t-t      : Run training round." << endl;
             cout << "\t-w N    : Specify total number of workers." << endl;
+            cout << "\t-d FILE : Dump raw data to file." << endl;
             return 0;
         }
         if (string(argv[i]) == "-w") {
@@ -430,14 +445,24 @@
             i++;
             continue;
         }
+        if (string(argv[i]) == "-d") {
+            if (i + 1 == argc) {
+                cout << "-d requires an argument\n" << endl;
+                exit(EXIT_FAILURE);
+            }
+            dump_to_file = true;
+            dump_filename = argv[i + 1];
+            i++;
+            continue;
+        }
     }
 
     if (training_round) {
         cout << "Start training round" << endl;
-        run_main(iterations, workers, payload_size, cs_pair, training_round=true);
+        run_main(iterations, workers, payload_size, cs_pair, true);
         cout << "Completed training round" << endl << endl;
     }
 
-    run_main(iterations, workers, payload_size, cs_pair);
+    run_main(iterations, workers, payload_size, cs_pair, false, dump_to_file, dump_filename);
     return 0;
 }
diff --git a/libs/binder/trusty/ndk/include/android/llndk-versioning.h b/libs/binder/trusty/ndk/include/android/llndk-versioning.h
new file mode 100644
index 0000000..3ae3d8f
--- /dev/null
+++ b/libs/binder/trusty/ndk/include/android/llndk-versioning.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2024 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
+
+#define __INTRODUCED_IN_LLNDK(x) /* nothing on Trusty */
diff --git a/libs/binder/trusty/ndk/include/sys/cdefs.h b/libs/binder/trusty/ndk/include/sys/cdefs.h
index 7528f2b..4e9b0e8 100644
--- a/libs/binder/trusty/ndk/include/sys/cdefs.h
+++ b/libs/binder/trusty/ndk/include/sys/cdefs.h
@@ -27,4 +27,3 @@
 #endif
 
 #define __INTRODUCED_IN(x) /* nothing on Trusty */
-#define __INTRODUCED_IN_LLNDK(x) /* nothing on Trusty */
diff --git a/libs/binder/trusty/rust/binder_rpc_test/binder_rpc_test_session/lib.rs b/libs/binder/trusty/rust/binder_rpc_test/binder_rpc_test_session/lib.rs
new file mode 100644
index 0000000..22cba44
--- /dev/null
+++ b/libs/binder/trusty/rust/binder_rpc_test/binder_rpc_test_session/lib.rs
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2023 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::{Interface, ParcelFileDescriptor, SpIBinder, Status, StatusCode, Strong};
+use binder_rpc_test_aidl::aidl::IBinderRpcCallback::IBinderRpcCallback;
+use binder_rpc_test_aidl::aidl::IBinderRpcSession::IBinderRpcSession;
+use binder_rpc_test_aidl::aidl::IBinderRpcTest::IBinderRpcTest;
+use std::sync::Mutex;
+
+static G_NUM: Mutex<i32> = Mutex::new(0);
+
+#[derive(Debug, Default)]
+pub struct MyBinderRpcSession {
+    name: String,
+}
+
+impl MyBinderRpcSession {
+    pub fn new(name: &str) -> Self {
+        Self::increment_instance_count();
+        Self { name: name.to_string() }
+    }
+
+    pub fn get_instance_count() -> i32 {
+        *G_NUM.lock().unwrap()
+    }
+
+    fn increment_instance_count() {
+        *G_NUM.lock().unwrap() += 1;
+    }
+
+    fn decrement_instance_count() {
+        *G_NUM.lock().unwrap() -= 1;
+    }
+}
+
+impl Drop for MyBinderRpcSession {
+    fn drop(&mut self) {
+        MyBinderRpcSession::decrement_instance_count();
+    }
+}
+
+impl Interface for MyBinderRpcSession {}
+
+impl IBinderRpcSession for MyBinderRpcSession {
+    fn getName(&self) -> Result<String, Status> {
+        Ok(self.name.clone())
+    }
+}
+
+impl IBinderRpcTest for MyBinderRpcSession {
+    fn sendString(&self, _: &str) -> Result<(), Status> {
+        todo!()
+    }
+    fn doubleString(&self, _s: &str) -> Result<String, Status> {
+        todo!()
+    }
+    fn getClientPort(&self) -> Result<i32, Status> {
+        todo!()
+    }
+    fn countBinders(&self) -> Result<Vec<i32>, Status> {
+        todo!()
+    }
+    fn getNullBinder(&self) -> Result<SpIBinder, Status> {
+        todo!()
+    }
+    fn pingMe(&self, _binder: &SpIBinder) -> Result<i32, Status> {
+        todo!()
+    }
+    fn repeatBinder(&self, _binder: Option<&SpIBinder>) -> Result<Option<SpIBinder>, Status> {
+        todo!()
+    }
+    fn holdBinder(&self, _binder: Option<&SpIBinder>) -> Result<(), Status> {
+        todo!()
+    }
+    fn getHeldBinder(&self) -> Result<Option<SpIBinder>, Status> {
+        todo!()
+    }
+    fn nestMe(
+        &self,
+        binder: &Strong<(dyn IBinderRpcTest + 'static)>,
+        count: i32,
+    ) -> Result<(), Status> {
+        if count < 0 {
+            Ok(())
+        } else {
+            binder.nestMe(binder, count - 1)
+        }
+    }
+    fn alwaysGiveMeTheSameBinder(&self) -> Result<SpIBinder, Status> {
+        todo!()
+    }
+    fn openSession(
+        &self,
+        _name: &str,
+    ) -> Result<Strong<(dyn IBinderRpcSession + 'static)>, Status> {
+        todo!()
+    }
+    fn getNumOpenSessions(&self) -> Result<i32, Status> {
+        todo!()
+    }
+    fn lock(&self) -> Result<(), Status> {
+        todo!()
+    }
+    fn unlockInMsAsync(&self, _: i32) -> Result<(), Status> {
+        todo!()
+    }
+    fn lockUnlock(&self) -> Result<(), Status> {
+        todo!()
+    }
+    fn sleepMs(&self, _: i32) -> Result<(), Status> {
+        todo!()
+    }
+    fn sleepMsAsync(&self, _: i32) -> Result<(), Status> {
+        todo!()
+    }
+    fn doCallback(
+        &self,
+        _: &Strong<(dyn IBinderRpcCallback + 'static)>,
+        _: bool,
+        _: bool,
+        _: &str,
+    ) -> Result<(), Status> {
+        todo!()
+    }
+    fn doCallbackAsync(
+        &self,
+        _: &Strong<(dyn IBinderRpcCallback + 'static)>,
+        _: bool,
+        _: bool,
+        _: &str,
+    ) -> Result<(), Status> {
+        todo!()
+    }
+    fn die(&self, _: bool) -> Result<(), Status> {
+        Err(Status::from(StatusCode::UNKNOWN_TRANSACTION))
+    }
+    fn scheduleShutdown(&self) -> Result<(), Status> {
+        todo!()
+    }
+    fn useKernelBinderCallingId(&self) -> Result<(), Status> {
+        todo!()
+    }
+    fn echoAsFile(&self, _: &str) -> Result<ParcelFileDescriptor, Status> {
+        todo!()
+    }
+    fn concatFiles(&self, _: &[ParcelFileDescriptor]) -> Result<ParcelFileDescriptor, Status> {
+        todo!()
+    }
+    fn blockingSendFdOneway(&self, _: &ParcelFileDescriptor) -> Result<(), Status> {
+        todo!()
+    }
+    fn blockingRecvFd(&self) -> Result<ParcelFileDescriptor, Status> {
+        todo!()
+    }
+    fn blockingSendIntOneway(&self, _: i32) -> Result<(), Status> {
+        todo!()
+    }
+    fn blockingRecvInt(&self) -> Result<i32, Status> {
+        todo!()
+    }
+}
diff --git a/libs/binder/trusty/rust/binder_rpc_test/binder_rpc_test_session/rules.mk b/libs/binder/trusty/rust/binder_rpc_test/binder_rpc_test_session/rules.mk
new file mode 100644
index 0000000..ae26355
--- /dev/null
+++ b/libs/binder/trusty/rust/binder_rpc_test/binder_rpc_test_session/rules.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2023 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.
+#
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+LIBBINDER_DIR := $(LOCAL_DIR)/../../../..
+
+MODULE := $(LOCAL_DIR)
+
+MODULE_SRCS := $(LOCAL_DIR)/lib.rs
+
+MODULE_CRATE_NAME := binder_rpc_test_session
+
+MODULE_LIBRARY_DEPS += \
+	$(LIBBINDER_DIR)/trusty/rust \
+	$(LIBBINDER_DIR)/trusty/rust/rpcbinder \
+	$(LOCAL_DIR)/../aidl \
+	$(call FIND_CRATE,log) \
+	trusty/user/base/lib/trusty-std \
+
+include make/library.mk
diff --git a/libs/binder/trusty/rust/binder_rpc_test/main.rs b/libs/binder/trusty/rust/binder_rpc_test/main.rs
index 3c1e784..baea5a8 100644
--- a/libs/binder/trusty/rust/binder_rpc_test/main.rs
+++ b/libs/binder/trusty/rust/binder_rpc_test/main.rs
@@ -15,8 +15,11 @@
  */
 #![cfg(test)]
 
-use binder::{IBinder, Strong};
-use binder_rpc_test_aidl::aidl::IBinderRpcTest::IBinderRpcTest;
+use binder::{BinderFeatures, IBinder, Status, StatusCode, Strong};
+use binder_rpc_test_aidl::aidl::IBinderRpcSession::{BnBinderRpcSession, IBinderRpcSession};
+use binder_rpc_test_aidl::aidl::IBinderRpcTest::{BnBinderRpcTest, IBinderRpcTest};
+use binder_rpc_test_session::MyBinderRpcSession;
+use libc::{clock_gettime, CLOCK_REALTIME};
 use rpcbinder::RpcSession;
 use trusty_std::ffi::{CString, FallibleCString};
 
@@ -25,19 +28,190 @@
 const SERVICE_PORT: &str = "com.android.trusty.binderRpcTestService.V1";
 const RUST_SERVICE_PORT: &str = "com.android.trusty.rust.binderRpcTestService.V1";
 
+macro_rules! service_test {
+    ($c_name:ident, $rust_name:ident, $body:expr) => {
+        #[test]
+        fn $c_name() {
+            $body(get_service(SERVICE_PORT))
+        }
+        #[test]
+        fn $rust_name() {
+            $body(get_service(RUST_SERVICE_PORT))
+        }
+    };
+}
+
 fn get_service(port: &str) -> Strong<dyn IBinderRpcTest> {
     let port = CString::try_new(port).expect("Failed to allocate port name");
     RpcSession::new().setup_trusty_client(port.as_c_str()).expect("Failed to create session")
 }
 
-#[test]
-fn ping() {
-    let srv = get_service(SERVICE_PORT);
-    assert_eq!(srv.as_binder().ping_binder(), Ok(()));
+fn expect_sessions(expected: i32, srv: &Strong<dyn IBinderRpcTest>) {
+    let count = srv.getNumOpenSessions();
+    assert!(count.is_ok());
+    assert_eq!(expected, count.unwrap());
 }
 
-#[test]
-fn ping_rust() {
-    let srv = get_service(RUST_SERVICE_PORT);
-    assert_eq!(srv.as_binder().ping_binder(), Ok(()));
+fn get_time_ns() -> u64 {
+    let mut ts = libc::timespec { tv_sec: 0, tv_nsec: 0 };
+
+    // Safety: Passing valid pointer to variable ts which lives past end of call
+    assert_eq!(unsafe { clock_gettime(CLOCK_REALTIME, &mut ts) }, 0);
+
+    ts.tv_sec as u64 * 1_000_000_000u64 + ts.tv_nsec as u64
 }
+
+fn get_time_ms() -> u64 {
+    get_time_ns() / 1_000_000u64
+}
+
+// ----------
+
+service_test! {ping, ping_rust, |srv: Strong<dyn IBinderRpcTest>| {
+    assert_eq!(srv.as_binder().ping_binder(), Ok(()));
+}}
+
+service_test! {send_something_oneway, send_something_oneway_rust, |srv: Strong<dyn IBinderRpcTest>| {
+    assert_eq!(srv.sendString("Foo"), Ok(()));
+}}
+
+service_test! {send_and_get_result_back, send_and_get_result_back_rust, |srv: Strong<dyn IBinderRpcTest>| {
+    assert_eq!(srv.doubleString("Foo"), Ok(String::from("FooFoo")));
+}}
+
+service_test! {send_and_get_result_back_big, send_and_get_result_back_big_rust, |srv: Strong<dyn IBinderRpcTest>| {
+    let single_len = 512;
+    let single = "a".repeat(single_len);
+    assert_eq!(srv.doubleString(&single), Ok(String::from(single.clone() + &single)));
+}}
+
+service_test! {invalid_null_binder_return, invalid_null_binder_return_rust, |srv: Strong<dyn IBinderRpcTest>| {
+    let binder = srv.getNullBinder();
+    assert!(binder == Err(Status::from(StatusCode::UNEXPECTED_NULL)) || binder == Err(Status::from(StatusCode::UNKNOWN_TRANSACTION)));
+}}
+
+service_test! {call_me_back, call_me_back_rust, |srv: Strong<dyn IBinderRpcTest>| {
+    let binder =
+        BnBinderRpcSession::new_binder(MyBinderRpcSession::new("Foo"), BinderFeatures::default())
+            .as_binder();
+    let result = srv.pingMe(&binder);
+    assert_eq!(result, Ok(0));
+}}
+
+service_test! {repeat_binder, repeat_binder_rust, |srv: Strong<dyn IBinderRpcTest>| {
+    let in_binder =
+        BnBinderRpcSession::new_binder(MyBinderRpcSession::new("Foo"), BinderFeatures::default())
+            .as_binder();
+    let result = srv.repeatBinder(Some(&in_binder));
+    assert_eq!(result.unwrap().unwrap(), in_binder);
+}}
+
+service_test! {repeat_their_binder, repeat_their_binder_rust, |srv: Strong<dyn IBinderRpcTest>| {
+    let session = srv.openSession("Test");
+    assert!(session.is_ok());
+
+    let in_binder = session.unwrap().as_binder();
+    let out_binder = srv.repeatBinder(Some(&in_binder));
+    assert_eq!(out_binder.unwrap().unwrap(), in_binder);
+}}
+
+service_test! {hold_binder, hold_binder_rust, |srv: Strong<dyn IBinderRpcTest>| {
+    let name = "Foo";
+
+    let binder =
+        BnBinderRpcSession::new_binder(MyBinderRpcSession::new(name), BinderFeatures::default())
+            .as_binder();
+    assert!(srv.holdBinder(Some(&binder)).is_ok());
+
+    let held = srv.getHeldBinder();
+    assert!(held.is_ok());
+    let held = held.unwrap();
+    assert!(held.is_some());
+    let held = held.unwrap();
+    assert_eq!(binder, held);
+
+    let session = held.into_interface::<dyn IBinderRpcSession>();
+    assert!(session.is_ok());
+
+    let session_name = session.unwrap().getName();
+    assert!(session_name.is_ok());
+    let session_name = session_name.unwrap();
+    assert_eq!(session_name, name);
+
+    assert!(srv.holdBinder(None).is_ok());
+}}
+
+service_test! {nested_transactions, nested_transactions_rust, |srv: Strong<dyn IBinderRpcTest>| {
+    let binder =
+        BnBinderRpcTest::new_binder(MyBinderRpcSession::new("Nest"), BinderFeatures::default());
+    assert!(srv.nestMe(&binder, 10).is_ok());
+}}
+
+service_test! {same_binder_equality, same_binder_equality_rust, |srv: Strong<dyn IBinderRpcTest>| {
+    let a = srv.alwaysGiveMeTheSameBinder();
+    assert!(a.is_ok());
+
+    let b = srv.alwaysGiveMeTheSameBinder();
+    assert!(b.is_ok());
+
+    assert_eq!(a.unwrap(), b.unwrap());
+}}
+
+service_test! {single_session, single_session_rust, |srv: Strong<dyn IBinderRpcTest>| {
+    let session = srv.openSession("aoeu");
+    assert!(session.is_ok());
+    let session = session.unwrap();
+    let name = session.getName();
+    assert!(name.is_ok());
+    assert_eq!(name.unwrap(), "aoeu");
+
+    let count = srv.getNumOpenSessions();
+    assert!(count.is_ok());
+    assert_eq!(count.unwrap(), 1);
+
+    drop(session);
+    let count = srv.getNumOpenSessions();
+    assert!(count.is_ok());
+    assert_eq!(count.unwrap(), 0);
+}}
+
+service_test! {many_session, many_session_rust, |srv: Strong<dyn IBinderRpcTest>| {
+    let mut sessions = Vec::new();
+
+    for i in 0..15 {
+        expect_sessions(i, &srv);
+
+        let session = srv.openSession(&(i.to_string()));
+        assert!(session.is_ok());
+        sessions.push(session.unwrap());
+    }
+
+    expect_sessions(sessions.len() as i32, &srv);
+
+    for i in 0..sessions.len() {
+        let name = sessions[i].getName();
+        assert!(name.is_ok());
+        assert_eq!(name.unwrap(), i.to_string());
+    }
+
+    expect_sessions(sessions.len() as i32, &srv);
+
+    while !sessions.is_empty() {
+        sessions.pop();
+
+        expect_sessions(sessions.len() as i32, &srv);
+    }
+
+    expect_sessions(0, &srv);
+}}
+
+service_test! {one_way_call_does_not_wait, one_way_call_does_not_wait_rust, |srv: Strong<dyn IBinderRpcTest>| {
+    let really_long_time_ms = 100;
+    let sleep_ms = really_long_time_ms * 5;
+
+    let before = get_time_ms();
+    let _ = srv.sleepMsAsync(sleep_ms);
+    let after = get_time_ms();
+
+    assert!(after < before + really_long_time_ms as u64);
+}}
diff --git a/libs/binder/trusty/rust/binder_rpc_test/manifest.json b/libs/binder/trusty/rust/binder_rpc_test/manifest.json
index c2ecaa4..384ed44 100644
--- a/libs/binder/trusty/rust/binder_rpc_test/manifest.json
+++ b/libs/binder/trusty/rust/binder_rpc_test/manifest.json
@@ -1,7 +1,7 @@
 {
     "uuid": "91eed949-8a9e-4569-9c83-5935fb624025",
     "app_name": "rust_binder_rpc_test",
-    "min_heap": 16384,
+    "min_heap": 32768,
     "min_stack": 16384,
     "mgmt_flags": {
         "non_critical_app": true
diff --git a/libs/binder/trusty/rust/binder_rpc_test/rules.mk b/libs/binder/trusty/rust/binder_rpc_test/rules.mk
index 192a159..8347a35 100644
--- a/libs/binder/trusty/rust/binder_rpc_test/rules.mk
+++ b/libs/binder/trusty/rust/binder_rpc_test/rules.mk
@@ -26,6 +26,8 @@
 	$(LIBBINDER_DIR)/trusty/rust \
 	$(LIBBINDER_DIR)/trusty/rust/rpcbinder \
 	$(LOCAL_DIR)/aidl \
+	$(LOCAL_DIR)/binder_rpc_test_session \
+	$(call FIND_CRATE,log) \
 	trusty/user/base/lib/trusty-std \
 
 MODULE_RUST_TESTS := true
diff --git a/libs/binder/trusty/rust/binder_rpc_test/service/main.rs b/libs/binder/trusty/rust/binder_rpc_test/service/main.rs
index b9a86bf..c4a758a 100644
--- a/libs/binder/trusty/rust/binder_rpc_test/service/main.rs
+++ b/libs/binder/trusty/rust/binder_rpc_test/service/main.rs
@@ -13,61 +13,126 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-use binder::{BinderFeatures, Interface, ParcelFileDescriptor, SpIBinder, Status, Strong};
+use binder::{
+    BinderFeatures, IBinder, Interface, ParcelFileDescriptor, SpIBinder, Status, StatusCode, Strong,
+};
 use binder_rpc_test_aidl::aidl::IBinderRpcCallback::IBinderRpcCallback;
-use binder_rpc_test_aidl::aidl::IBinderRpcSession::IBinderRpcSession;
+use binder_rpc_test_aidl::aidl::IBinderRpcSession::{BnBinderRpcSession, IBinderRpcSession};
 use binder_rpc_test_aidl::aidl::IBinderRpcTest::{BnBinderRpcTest, IBinderRpcTest};
+use binder_rpc_test_session::MyBinderRpcSession;
+use libc::{c_long, nanosleep, timespec};
 use rpcbinder::RpcServer;
 use std::rc::Rc;
+use std::sync::Mutex;
 use tipc::{service_dispatcher, wrap_service, Manager, PortCfg};
 
 const RUST_SERVICE_PORT: &str = "com.android.trusty.rust.binderRpcTestService.V1";
 
+// -----------------------------------------------------------------------------
+
+static SESSION_COUNT: Mutex<i32> = Mutex::new(0);
+static HOLD_BINDER: Mutex<Option<SpIBinder>> = Mutex::new(None);
+static SAME_BINDER: Mutex<Option<SpIBinder>> = Mutex::new(None);
+
 #[derive(Debug, Default)]
-struct TestService;
+struct TestService {
+    port: i32,
+    name: String,
+}
+
+#[allow(dead_code)]
+impl TestService {
+    fn new(name: &str) -> Self {
+        *SESSION_COUNT.lock().unwrap() += 1;
+        Self { name: name.to_string(), ..Default::default() }
+    }
+
+    fn get_instance_count() -> i32 {
+        *SESSION_COUNT.lock().unwrap()
+    }
+}
+
+impl Drop for TestService {
+    fn drop(&mut self) {
+        *SESSION_COUNT.lock().unwrap() -= 1;
+    }
+}
 
 impl Interface for TestService {}
 
+impl IBinderRpcSession for TestService {
+    fn getName(&self) -> Result<String, Status> {
+        Ok(self.name.clone())
+    }
+}
+
 impl IBinderRpcTest for TestService {
     fn sendString(&self, _: &str) -> Result<(), Status> {
-        todo!()
+        // This is a oneway function, so caller returned immediately and gives back an Ok(()) regardless of what this returns
+        Ok(())
     }
-    fn doubleString(&self, _: &str) -> Result<String, Status> {
-        todo!()
+    fn doubleString(&self, s: &str) -> Result<String, Status> {
+        let ss = [s, s].concat();
+        Ok(ss)
     }
     fn getClientPort(&self) -> Result<i32, Status> {
-        todo!()
+        Ok(self.port)
     }
     fn countBinders(&self) -> Result<Vec<i32>, Status> {
         todo!()
     }
     fn getNullBinder(&self) -> Result<SpIBinder, Status> {
-        todo!()
+        Err(Status::from(StatusCode::UNKNOWN_TRANSACTION))
     }
-    fn pingMe(&self, _: &SpIBinder) -> Result<i32, Status> {
-        todo!()
+    fn pingMe(&self, binder: &SpIBinder) -> Result<i32, Status> {
+        match binder.clone().ping_binder() {
+            Ok(()) => Ok(StatusCode::OK as i32),
+            Err(e) => Err(Status::from(e)),
+        }
     }
-    fn repeatBinder(&self, _: Option<&SpIBinder>) -> Result<Option<SpIBinder>, Status> {
-        todo!()
+    fn repeatBinder(&self, binder: Option<&SpIBinder>) -> Result<Option<SpIBinder>, Status> {
+        match binder {
+            Some(x) => Ok(Some(x.clone())),
+            None => Err(Status::from(StatusCode::BAD_VALUE)),
+        }
     }
-    fn holdBinder(&self, _: Option<&SpIBinder>) -> Result<(), Status> {
-        todo!()
+    fn holdBinder(&self, binder: Option<&SpIBinder>) -> Result<(), Status> {
+        *HOLD_BINDER.lock().unwrap() = binder.cloned();
+        Ok(())
     }
     fn getHeldBinder(&self) -> Result<Option<SpIBinder>, Status> {
-        todo!()
+        Ok((*HOLD_BINDER.lock().unwrap()).clone())
     }
-    fn nestMe(&self, _: &Strong<(dyn IBinderRpcTest + 'static)>, _: i32) -> Result<(), Status> {
-        todo!()
+    fn nestMe(
+        &self,
+        binder: &Strong<(dyn IBinderRpcTest + 'static)>,
+        count: i32,
+    ) -> Result<(), Status> {
+        if count < 0 {
+            Ok(())
+        } else {
+            binder.nestMe(binder, count - 1)
+        }
     }
     fn alwaysGiveMeTheSameBinder(&self) -> Result<SpIBinder, Status> {
-        todo!()
+        let mut locked = SAME_BINDER.lock().unwrap();
+        Ok((*locked)
+            .get_or_insert_with(|| {
+                BnBinderRpcTest::new_binder(TestService::default(), BinderFeatures::default())
+                    .as_binder()
+            })
+            .clone())
     }
-    fn openSession(&self, _: &str) -> Result<Strong<(dyn IBinderRpcSession + 'static)>, Status> {
-        todo!()
+    fn openSession(&self, name: &str) -> Result<Strong<(dyn IBinderRpcSession + 'static)>, Status> {
+        let s = BnBinderRpcSession::new_binder(
+            MyBinderRpcSession::new(name),
+            BinderFeatures::default(),
+        );
+        Ok(s)
     }
     fn getNumOpenSessions(&self) -> Result<i32, Status> {
-        todo!()
+        let count = MyBinderRpcSession::get_instance_count();
+        Ok(count)
     }
     fn lock(&self) -> Result<(), Status> {
         todo!()
@@ -78,11 +143,21 @@
     fn lockUnlock(&self) -> Result<(), Status> {
         todo!()
     }
-    fn sleepMs(&self, _: i32) -> Result<(), Status> {
-        todo!()
+    fn sleepMs(&self, ms: i32) -> Result<(), Status> {
+        let ts = timespec {
+            tv_sec: (ms / 1000) as c_long,
+            tv_nsec: (ms % 1000) as c_long * 1_000_000 as c_long,
+        };
+
+        let mut rem = timespec { tv_sec: 0, tv_nsec: 0 };
+
+        // Safety: Passing valid pointers to variables ts & rem which live past end of call
+        assert_eq!(unsafe { nanosleep(&ts, &mut rem) }, 0);
+
+        Ok(())
     }
-    fn sleepMsAsync(&self, _: i32) -> Result<(), Status> {
-        todo!()
+    fn sleepMsAsync(&self, ms: i32) -> Result<(), Status> {
+        self.sleepMs(ms)
     }
     fn doCallback(
         &self,
@@ -103,7 +178,7 @@
         todo!()
     }
     fn die(&self, _: bool) -> Result<(), Status> {
-        todo!()
+        Err(Status::from(StatusCode::UNKNOWN_TRANSACTION))
     }
     fn scheduleShutdown(&self) -> Result<(), Status> {
         todo!()
diff --git a/libs/binder/trusty/rust/binder_rpc_test/service/rules.mk b/libs/binder/trusty/rust/binder_rpc_test/service/rules.mk
index 1ddc382..f71ee9b 100644
--- a/libs/binder/trusty/rust/binder_rpc_test/service/rules.mk
+++ b/libs/binder/trusty/rust/binder_rpc_test/service/rules.mk
@@ -25,7 +25,10 @@
 MODULE_LIBRARY_DEPS += \
 	$(LIBBINDER_DIR)/trusty/rust \
 	$(LIBBINDER_DIR)/trusty/rust/rpcbinder \
+	$(LIBBINDER_DIR)/trusty/rust/binder_rpc_server \
 	$(LOCAL_DIR)/../aidl \
+	$(LOCAL_DIR)/../binder_rpc_test_session \
+	$(LOCAL_DIR)/.. \
 	trusty/user/base/lib/tipc/rust \
 
 MANIFEST := $(LOCAL_DIR)/manifest.json
diff --git a/libs/binder/trusty/rust/rules.mk b/libs/binder/trusty/rust/rules.mk
index c5e671a..36bd3a2 100644
--- a/libs/binder/trusty/rust/rules.mk
+++ b/libs/binder/trusty/rust/rules.mk
@@ -28,6 +28,7 @@
 	$(LIBBINDER_DIR)/trusty/rust/binder_ndk_sys \
 	$(LIBBINDER_DIR)/trusty/rust/binder_rpc_unstable_bindgen \
 	external/rust/crates/downcast-rs \
+	external/rust/crates/libc \
 	trusty/user/base/lib/trusty-sys \
 
 MODULE_RUSTFLAGS += \
diff --git a/libs/bufferstreams/Android.bp b/libs/bufferstreams/Android.bp
index 365fc45..6c2a980 100644
--- a/libs/bufferstreams/Android.bp
+++ b/libs/bufferstreams/Android.bp
@@ -19,6 +19,7 @@
 aconfig_declarations {
     name: "bufferstreams_flags",
     package: "com.android.graphics.bufferstreams.flags",
+    container: "system",
     srcs: [
         "aconfig/bufferstreams_flags.aconfig",
     ],
diff --git a/libs/bufferstreams/aconfig/bufferstreams_flags.aconfig b/libs/bufferstreams/aconfig/bufferstreams_flags.aconfig
index e258725..d0f7812 100644
--- a/libs/bufferstreams/aconfig/bufferstreams_flags.aconfig
+++ b/libs/bufferstreams/aconfig/bufferstreams_flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.graphics.bufferstreams.flags"
+container: "system"
 
 flag {
   name: "bufferstreams_steel_thread"
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 8643148..059e19e 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -23,6 +23,7 @@
 aconfig_declarations {
     name: "libgui_flags",
     package: "com.android.graphics.libgui.flags",
+    container: "system",
     srcs: ["libgui_flags.aconfig"],
 }
 
diff --git a/libs/gui/libgui_flags.aconfig b/libs/gui/libgui_flags.aconfig
index b081030..3864699 100644
--- a/libs/gui/libgui_flags.aconfig
+++ b/libs/gui/libgui_flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.graphics.libgui.flags"
+container: "system"
 
 flag {
   name: "bq_setframerate"
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 252040d..20b3538 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -39,6 +39,7 @@
 aconfig_declarations {
     name: "com.android.input.flags-aconfig",
     package: "com.android.input.flags",
+    container: "system",
     srcs: ["input_flags.aconfig"],
 }
 
diff --git a/libs/input/input_flags.aconfig b/libs/input/input_flags.aconfig
index 54eeb39..dbc002c 100644
--- a/libs/input/input_flags.aconfig
+++ b/libs/input/input_flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.input.flags"
+container: "system"
 
 flag {
   name: "enable_outbound_event_verification"
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index 13cfb49..9137a34 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -13,6 +13,7 @@
     cpp_std: "c++20",
     host_supported: true,
     srcs: [
+        "BlockingQueue_test.cpp",
         "IdGenerator_test.cpp",
         "InputChannel_test.cpp",
         "InputDevice_test.cpp",
diff --git a/services/inputflinger/tests/BlockingQueue_test.cpp b/libs/input/tests/BlockingQueue_test.cpp
similarity index 97%
rename from services/inputflinger/tests/BlockingQueue_test.cpp
rename to libs/input/tests/BlockingQueue_test.cpp
index 754a5c4..924b937 100644
--- a/services/inputflinger/tests/BlockingQueue_test.cpp
+++ b/libs/input/tests/BlockingQueue_test.cpp
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#include "../BlockingQueue.h"
-
+#include <input/BlockingQueue.h>
 
 #include <gtest/gtest.h>
 #include <thread>
@@ -109,7 +108,7 @@
     BlockingQueue<int> queue(capacity);
 
     // Fill queue from a different thread
-    std::thread fillQueue([&queue](){
+    std::thread fillQueue([&queue]() {
         for (size_t i = 0; i < capacity; i++) {
             ASSERT_TRUE(queue.push(static_cast<int>(i)));
         }
@@ -136,7 +135,7 @@
     std::atomic_bool hasReceivedElement = false;
 
     // fill queue from a different thread
-    std::thread waitUntilHasElements([&queue, &hasReceivedElement](){
+    std::thread waitUntilHasElements([&queue, &hasReceivedElement]() {
         queue.pop(); // This should block until an element has been added
         hasReceivedElement = true;
     });
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index 48d793a..080e62b 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -70,6 +70,9 @@
 };
 
 GpuService::~GpuService() {
+    mGpuMem->stop();
+    mGpuWork->stop();
+
     mGpuWorkAsyncInitThread->join();
     mGpuMemAsyncInitThread->join();
 }
diff --git a/services/gpuservice/gpumem/GpuMem.cpp b/services/gpuservice/gpumem/GpuMem.cpp
index 141fe02..d0783df 100644
--- a/services/gpuservice/gpumem/GpuMem.cpp
+++ b/services/gpuservice/gpumem/GpuMem.cpp
@@ -61,6 +61,7 @@
             return;
         }
         // Retry until GPU driver loaded or timeout.
+        if (mStop.load()) return;
         sleep(1);
     }
 
diff --git a/services/gpuservice/gpumem/include/gpumem/GpuMem.h b/services/gpuservice/gpumem/include/gpumem/GpuMem.h
index 9aa74d6..16b201f 100644
--- a/services/gpuservice/gpumem/include/gpumem/GpuMem.h
+++ b/services/gpuservice/gpumem/include/gpumem/GpuMem.h
@@ -34,6 +34,7 @@
     // dumpsys interface
     void dump(const Vector<String16>& args, std::string* result);
     bool isInitialized() { return mInitialized.load(); }
+    void stop() { mStop.store(true); }
 
     // Traverse the gpu memory total map to feed the callback function.
     void traverseGpuMemTotals(const std::function<void(int64_t ts, uint32_t gpuId, uint32_t pid,
@@ -48,6 +49,10 @@
 
     // indicate whether ebpf has been initialized
     std::atomic<bool> mInitialized = false;
+
+    // whether initialization should be stopped
+    std::atomic<bool> mStop = false;
+
     // bpf map for GPU memory total data
     android::bpf::BpfMapRO<uint64_t, uint64_t> mGpuMemTotalMap;
 
diff --git a/services/gpuservice/gpuwork/GpuWork.cpp b/services/gpuservice/gpuwork/GpuWork.cpp
index fd70323..1a744ab 100644
--- a/services/gpuservice/gpuwork/GpuWork.cpp
+++ b/services/gpuservice/gpuwork/GpuWork.cpp
@@ -243,6 +243,7 @@
             return false;
         }
         // Retry until GPU driver loaded or timeout.
+        if (mStop.load()) return false;
         sleep(1);
         errno = 0;
     }
diff --git a/services/gpuservice/gpuwork/include/gpuwork/GpuWork.h b/services/gpuservice/gpuwork/include/gpuwork/GpuWork.h
index cece999..e70da54 100644
--- a/services/gpuservice/gpuwork/include/gpuwork/GpuWork.h
+++ b/services/gpuservice/gpuwork/include/gpuwork/GpuWork.h
@@ -40,6 +40,7 @@
     ~GpuWork();
 
     void initialize();
+    void stop() { mStop.store(true); }
 
     // Dumps the GPU work information.
     void dump(const Vector<String16>& args, std::string* result);
@@ -47,7 +48,7 @@
 private:
     // Attaches tracepoint |tracepoint_group|/|tracepoint_name| to BPF program at path
     // |program_path|. The tracepoint is also enabled.
-    static bool attachTracepoint(const char* program_path, const char* tracepoint_group,
+    bool attachTracepoint(const char* program_path, const char* tracepoint_group,
                                  const char* tracepoint_name);
 
     // Native atom puller callback registered in statsd.
@@ -80,6 +81,9 @@
     // Indicates whether our eBPF components have been initialized.
     std::atomic<bool> mInitialized = false;
 
+    // Indicates whether eBPF initialization should be stopped.
+    std::atomic<bool> mStop = false;
+
     // A thread that periodically checks whether |mGpuWorkMap| is nearly full
     // and, if so, clears it.
     std::thread mMapClearerThread;
diff --git a/services/inputflinger/InputProcessor.h b/services/inputflinger/InputProcessor.h
index dcbfebc..7a00a2d 100644
--- a/services/inputflinger/InputProcessor.h
+++ b/services/inputflinger/InputProcessor.h
@@ -22,7 +22,7 @@
 #include <unordered_map>
 
 #include <aidl/android/hardware/input/processor/IInputProcessor.h>
-#include "BlockingQueue.h"
+#include <input/BlockingQueue.h>
 #include "InputListener.h"
 namespace android {
 
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index 2a03ecc..9c9f643 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -39,7 +39,6 @@
     ],
     srcs: [
         "AnrTracker_test.cpp",
-        "BlockingQueue_test.cpp",
         "CapturedTouchpadEventConverter_test.cpp",
         "CursorInputMapper_test.cpp",
         "EventHub_test.cpp",
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 5002391..c2e67fa 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -15,7 +15,6 @@
  */
 
 #include "../dispatcher/InputDispatcher.h"
-#include "../BlockingQueue.h"
 #include "FakeApplicationHandle.h"
 #include "TestEventMatchers.h"
 
@@ -31,6 +30,7 @@
 #include <flag_macros.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
+#include <input/BlockingQueue.h>
 #include <input/Input.h>
 #include <input/PrintTools.h>
 #include <linux/input.h>
diff --git a/services/inputflinger/tests/fuzzers/BlockingQueueFuzzer.cpp b/services/inputflinger/tests/fuzzers/BlockingQueueFuzzer.cpp
index 219b662..863d0a1 100644
--- a/services/inputflinger/tests/fuzzers/BlockingQueueFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/BlockingQueueFuzzer.cpp
@@ -15,8 +15,8 @@
  */
 
 #include <fuzzer/FuzzedDataProvider.h>
+#include <input/BlockingQueue.h>
 #include <thread>
-#include "BlockingQueue.h"
 
 // Chosen to be a number large enough for variation in fuzzer runs, but not consume too much memory.
 static constexpr size_t MAX_CAPACITY = 1024;
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 0989863..dcef9a3 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -10,6 +10,7 @@
 aconfig_declarations {
     name: "surfaceflinger_flags",
     package: "com.android.graphics.surfaceflinger.flags",
+    container: "system",
     srcs: ["surfaceflinger_flags.aconfig"],
 }
 
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index ae2f2db..0a70d42 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -10,6 +10,7 @@
 cc_defaults {
     name: "libcompositionengine_defaults",
     defaults: [
+        "aconfig_lib_cc_static_link.defaults",
         "android.hardware.graphics.composer3-ndk_shared",
         "android.hardware.power-ndk_shared",
         "librenderengine_deps",
diff --git a/services/surfaceflinger/surfaceflinger_flags.aconfig b/services/surfaceflinger/surfaceflinger_flags.aconfig
index 1a28b81..abe7ec7 100644
--- a/services/surfaceflinger/surfaceflinger_flags.aconfig
+++ b/services/surfaceflinger/surfaceflinger_flags.aconfig
@@ -1,4 +1,5 @@
 package: "com.android.graphics.surfaceflinger.flags"
+container: "system"
 
 flag {
   name: "misc1"
diff --git a/services/surfaceflinger/tests/OWNERS b/services/surfaceflinger/tests/OWNERS
index 1878326..56f2f1b 100644
--- a/services/surfaceflinger/tests/OWNERS
+++ b/services/surfaceflinger/tests/OWNERS
@@ -1,5 +1,8 @@
-per-file HdrSdrRatioOverlay_test.cpp = set noparent
 per-file HdrSdrRatioOverlay_test.cpp = alecmouri@google.com, sallyqi@google.com, jreck@google.com
 
+# Most layer-related files are owned by WM
 per-file Layer* = set noparent
 per-file Layer* = pdwilliams@google.com, vishnun@google.com, melodymhsu@google.com
+
+per-file LayerHistoryTest.cpp = file:/services/surfaceflinger/OWNERS
+per-file LayerInfoTest.cpp = file:/services/surfaceflinger/OWNERS
\ No newline at end of file
diff --git a/services/vibratorservice/VibratorCallbackScheduler.cpp b/services/vibratorservice/VibratorCallbackScheduler.cpp
index 7eda9ef..b2b1988 100644
--- a/services/vibratorservice/VibratorCallbackScheduler.cpp
+++ b/services/vibratorservice/VibratorCallbackScheduler.cpp
@@ -87,13 +87,13 @@
             lock.lock();
         }
         if (mQueue.empty()) {
-            // Wait until a new callback is scheduled.
-            mCondition.wait(mMutex);
+            // Wait until a new callback is scheduled or destructor was called.
+            mCondition.wait(lock, [this] { return mFinished || !mQueue.empty(); });
         } else {
-            // Wait until next callback expires, or a new one is scheduled.
+            // Wait until next callback expires or a new one is scheduled.
             // Use the monotonic steady clock to wait for the measured delay interval via wait_for
             // instead of using a wall clock via wait_until.
-            mCondition.wait_for(mMutex, mQueue.top().getWaitForExpirationDuration());
+            mCondition.wait_for(lock, mQueue.top().getWaitForExpirationDuration());
         }
     }
 }
diff --git a/services/vibratorservice/test/VibratorCallbackSchedulerTest.cpp b/services/vibratorservice/test/VibratorCallbackSchedulerTest.cpp
index 426cd42..881e321 100644
--- a/services/vibratorservice/test/VibratorCallbackSchedulerTest.cpp
+++ b/services/vibratorservice/test/VibratorCallbackSchedulerTest.cpp
@@ -14,20 +14,13 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "VibratorHalWrapperAidlTest"
-
-#include <android-base/thread_annotations.h>
-#include <android/hardware/vibrator/IVibrator.h>
-#include <condition_variable>
-
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
-#include <utils/Log.h>
-#include <thread>
-
 #include <vibratorservice/VibratorCallbackScheduler.h>
 
+#include "test_utils.h"
+
 using std::chrono::milliseconds;
 using std::chrono::steady_clock;
 using std::chrono::time_point;
@@ -39,29 +32,25 @@
 // -------------------------------------------------------------------------------------------------
 
 // Delay allowed for the scheduler to process callbacks during this test.
-static const auto TEST_TIMEOUT = 50ms;
+static const auto TEST_TIMEOUT = 100ms;
 
 class VibratorCallbackSchedulerTest : public Test {
 public:
-    void SetUp() override {
-        mScheduler = std::make_unique<vibrator::CallbackScheduler>();
-        std::lock_guard<std::mutex> lock(mMutex);
-        mExpiredCallbacks.clear();
-    }
+    void SetUp() override { mScheduler = std::make_unique<vibrator::CallbackScheduler>(); }
 
 protected:
     std::mutex mMutex;
-    std::condition_variable_any mCondition;
     std::unique_ptr<vibrator::CallbackScheduler> mScheduler = nullptr;
+    vibrator::TestCounter mCallbackCounter;
     std::vector<int32_t> mExpiredCallbacks GUARDED_BY(mMutex);
 
     std::function<void()> createCallback(int32_t id) {
-        return [=]() {
+        return [this, id]() {
             {
                 std::lock_guard<std::mutex> lock(mMutex);
                 mExpiredCallbacks.push_back(id);
             }
-            mCondition.notify_all();
+            mCallbackCounter.increment();
         };
     }
 
@@ -71,56 +60,42 @@
     }
 
     int32_t waitForCallbacks(int32_t callbackCount, milliseconds timeout) {
-        time_point<steady_clock> expirationTime = steady_clock::now() + timeout + TEST_TIMEOUT;
-        int32_t expiredCallbackCount = 0;
-        while (steady_clock::now() < expirationTime) {
-            std::lock_guard<std::mutex> lock(mMutex);
-            expiredCallbackCount = mExpiredCallbacks.size();
-            if (callbackCount <= expiredCallbackCount) {
-                return expiredCallbackCount;
-            }
-            auto currentTimeout = std::chrono::duration_cast<std::chrono::milliseconds>(
-                    expirationTime - steady_clock::now());
-            if (currentTimeout > currentTimeout.zero()) {
-                // Use the monotonic steady clock to wait for the requested timeout via wait_for
-                // instead of using a wall clock via wait_until.
-                mCondition.wait_for(mMutex, currentTimeout);
-            }
-        }
-        return expiredCallbackCount;
+        mCallbackCounter.tryWaitUntilCountIsAtLeast(callbackCount, timeout);
+        return mCallbackCounter.get();
     }
 };
 
 // -------------------------------------------------------------------------------------------------
 
 TEST_F(VibratorCallbackSchedulerTest, TestScheduleRunsOnlyAfterDelay) {
+    auto callbackDuration = 50ms;
     time_point<steady_clock> startTime = steady_clock::now();
-    mScheduler->schedule(createCallback(1), 50ms);
+    mScheduler->schedule(createCallback(1), callbackDuration);
 
-    ASSERT_EQ(1, waitForCallbacks(1, 50ms));
+    ASSERT_THAT(waitForCallbacks(1, callbackDuration + TEST_TIMEOUT), Eq(1));
     time_point<steady_clock> callbackTime = steady_clock::now();
 
-    // Callback happened at least 50ms after the beginning of the test.
-    ASSERT_TRUE(startTime + 50ms <= callbackTime);
-    ASSERT_THAT(getExpiredCallbacks(), ElementsAre(1));
+    // Callback took at least the required duration to trigger.
+    ASSERT_THAT(callbackTime, Ge(startTime + callbackDuration));
 }
 
 TEST_F(VibratorCallbackSchedulerTest, TestScheduleMultipleCallbacksRunsInDelayOrder) {
     // Schedule first callbacks long enough that all 3 will be scheduled together and run in order.
-    mScheduler->schedule(createCallback(1), 50ms);
-    mScheduler->schedule(createCallback(2), 40ms);
-    mScheduler->schedule(createCallback(3), 10ms);
+    mScheduler->schedule(createCallback(1), 50ms + 2 * TEST_TIMEOUT);
+    mScheduler->schedule(createCallback(2), 50ms + TEST_TIMEOUT);
+    mScheduler->schedule(createCallback(3), 50ms);
 
-    ASSERT_EQ(3, waitForCallbacks(3, 50ms));
+    // Callbacks triggered in the expected order based on the requested durations.
+    ASSERT_THAT(waitForCallbacks(3, 50ms + 3 * TEST_TIMEOUT), Eq(3));
     ASSERT_THAT(getExpiredCallbacks(), ElementsAre(3, 2, 1));
 }
 
 TEST_F(VibratorCallbackSchedulerTest, TestDestructorDropsPendingCallbacksAndKillsThread) {
     // Schedule callback long enough that scheduler will be destroyed while it's still scheduled.
-    mScheduler->schedule(createCallback(1), 50ms);
+    mScheduler->schedule(createCallback(1), 100ms);
     mScheduler.reset(nullptr);
 
     // Should timeout waiting for callback to run.
-    ASSERT_EQ(0, waitForCallbacks(1, 50ms));
-    ASSERT_TRUE(getExpiredCallbacks().empty());
+    ASSERT_THAT(waitForCallbacks(1, 100ms + TEST_TIMEOUT), Eq(0));
+    ASSERT_THAT(getExpiredCallbacks(), IsEmpty());
 }
diff --git a/services/vibratorservice/test/test_utils.h b/services/vibratorservice/test/test_utils.h
index 1933a11..c08cfc6 100644
--- a/services/vibratorservice/test/test_utils.h
+++ b/services/vibratorservice/test/test_utils.h
@@ -85,6 +85,34 @@
     ~TestFactory() = delete;
 };
 
+class TestCounter {
+public:
+    TestCounter(int32_t init = 0) : mMutex(), mCondVar(), mCount(init) {}
+
+    int32_t get() {
+        std::lock_guard<std::mutex> lock(mMutex);
+        return mCount;
+    }
+
+    void increment() {
+        {
+            std::lock_guard<std::mutex> lock(mMutex);
+            mCount += 1;
+        }
+        mCondVar.notify_all();
+    }
+
+    void tryWaitUntilCountIsAtLeast(int32_t count, std::chrono::milliseconds timeout) {
+        std::unique_lock<std::mutex> lock(mMutex);
+        mCondVar.wait_for(lock, timeout, [&] { return mCount >= count; });
+    }
+
+private:
+    std::mutex mMutex;
+    std::condition_variable mCondVar;
+    int32_t mCount GUARDED_BY(mMutex);
+};
+
 // -------------------------------------------------------------------------------------------------
 
 } // namespace vibrator