diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-04-30 23:28:27 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2024-04-30 23:28:27 +0000 |
commit | f5540fc357547202082803ab4ade3b26941a6e04 (patch) | |
tree | 6192f9e1c47798846a423f8bcd628d2be3ab4c6d | |
parent | df6be02aa31589d91d17636b005e3487c68a8e8b (diff) | |
parent | 8a0b04ba3c3f185d6ed68e5e9d9df0cead12809a (diff) | |
download | native-f5540fc357547202082803ab4ade3b26941a6e04.tar.gz |
Merge "Snap for 11785460 from 175e75876be5c603d50a9975dd87619bd3088e14 to sdk-release" into sdk-release
-rw-r--r-- | cmds/dumpstate/Android.bp | 5 | ||||
-rw-r--r-- | libs/binder/Android.bp | 10 | ||||
-rw-r--r-- | libs/binder/tests/binderThroughputTest.cpp | 43 | ||||
-rw-r--r-- | libs/binder/trusty/rust/binder_rpc_test/binder_rpc_test_session/lib.rs | 174 | ||||
-rw-r--r-- | libs/binder/trusty/rust/binder_rpc_test/binder_rpc_test_session/rules.mk | 32 | ||||
-rw-r--r-- | libs/binder/trusty/rust/binder_rpc_test/main.rs | 194 | ||||
-rw-r--r-- | libs/binder/trusty/rust/binder_rpc_test/manifest.json | 2 | ||||
-rw-r--r-- | libs/binder/trusty/rust/binder_rpc_test/rules.mk | 2 | ||||
-rw-r--r-- | libs/binder/trusty/rust/binder_rpc_test/service/main.rs | 131 | ||||
-rw-r--r-- | libs/binder/trusty/rust/binder_rpc_test/service/rules.mk | 3 | ||||
-rw-r--r-- | libs/binder/trusty/rust/rules.mk | 1 | ||||
-rw-r--r-- | services/surfaceflinger/CompositionEngine/Android.bp | 1 | ||||
-rw-r--r-- | services/surfaceflinger/tests/OWNERS | 5 | ||||
-rw-r--r-- | services/vibratorservice/VibratorCallbackScheduler.cpp | 8 | ||||
-rw-r--r-- | services/vibratorservice/test/VibratorCallbackSchedulerTest.cpp | 69 | ||||
-rw-r--r-- | services/vibratorservice/test/test_utils.h | 28 |
16 files changed, 602 insertions, 106 deletions
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp index 23f33d85a2..4a77967bb2 100644 --- a/cmds/dumpstate/Android.bp +++ b/cmds/dumpstate/Android.bp @@ -79,7 +79,10 @@ filegroup { 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/libs/binder/Android.bp b/libs/binder/Android.bp index 57a48d7e92..090e35bc37 100644 --- a/libs/binder/Android.bp +++ b/libs/binder/Android.bp @@ -446,7 +446,7 @@ cc_library_host_shared { }, } -cc_library_static { +cc_library { name: "libbinder_rpc_no_kernel", vendor_available: true, defaults: [ @@ -458,7 +458,7 @@ cc_library_static { ], } -cc_library_static { +cc_library { name: "libbinder_rpc_no_blob", vendor_available: true, defaults: [ @@ -474,7 +474,7 @@ cc_library_static { ], } -cc_library_static { +cc_library { name: "libbinder_rpc_no_native_handle", vendor_available: true, defaults: [ @@ -490,7 +490,7 @@ cc_library_static { ], } -cc_library_static { +cc_library { name: "libbinder_rpc_single_threaded", defaults: [ "libbinder_common_defaults", @@ -505,7 +505,7 @@ cc_library_static { ], } -cc_library_static { +cc_library { name: "libbinder_rpc_single_threaded_no_kernel", defaults: [ "libbinder_common_defaults", diff --git a/libs/binder/tests/binderThroughputTest.cpp b/libs/binder/tests/binderThroughputTest.cpp index 10912c7363..f912348689 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 @@ struct ProcResults { 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 signal_all(vector<Pipe>& v) } } -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 @@ void run_main(int iterations, 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 @@ int main(int argc, char *argv[]) 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 @@ int main(int argc, char *argv[]) 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 @@ int main(int argc, char *argv[]) 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/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 0000000000..22cba44975 --- /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 0000000000..ae26355521 --- /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 3c1e784418..baea5a827b 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 @@ test::init!(); 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 c2ecaa4fe3..384ed441c6 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 192a1591ae..8347a359db 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 @@ MODULE_LIBRARY_DEPS += \ $(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 b9a86bf240..c4a758a214 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!() - } - fn openSession(&self, _: &str) -> Result<Strong<(dyn IBinderRpcSession + 'static)>, 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, 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 @@ impl IBinderRpcTest for TestService { 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 @@ impl IBinderRpcTest for TestService { 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 1ddc382197..f71ee9bcbd 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_CRATE_NAME := binder_rpc_test_service 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 c5e671a4f5..36bd3a2e75 100644 --- a/libs/binder/trusty/rust/rules.mk +++ b/libs/binder/trusty/rust/rules.mk @@ -28,6 +28,7 @@ MODULE_LIBRARY_DEPS += \ $(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/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp index ae2f2dbbf5..0a70d4299d 100644 --- a/services/surfaceflinger/CompositionEngine/Android.bp +++ b/services/surfaceflinger/CompositionEngine/Android.bp @@ -10,6 +10,7 @@ package { 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/tests/OWNERS b/services/surfaceflinger/tests/OWNERS index 1878326b0b..56f2f1b07a 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 7eda9ef0c7..b2b1988d97 100644 --- a/services/vibratorservice/VibratorCallbackScheduler.cpp +++ b/services/vibratorservice/VibratorCallbackScheduler.cpp @@ -87,13 +87,13 @@ void CallbackScheduler::loop() { 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 426cd426f7..881e32152c 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 @@ using namespace testing; // ------------------------------------------------------------------------------------------------- // 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 @@ protected: } 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 1933a118ef..c08cfc6bfa 100644 --- a/services/vibratorservice/test/test_utils.h +++ b/services/vibratorservice/test/test_utils.h @@ -85,6 +85,34 @@ private: ~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 |