Skip to content

Commit 93789b2

Browse files
committed
Hack-example to play with Thermal Manager
1 parent fe11cbf commit 93789b2

File tree

5 files changed

+208
-1
lines changed

5 files changed

+208
-1
lines changed

Cargo.toml

+5
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,9 @@ resolver = "2"
33
members = [
44
"ndk",
55
"ndk-sys",
6+
"ndk-examples",
67
]
8+
9+
[patch.crates-io]
10+
ndk = { path = "ndk" }
11+
ndk-sys = { path = "ndk-sys" }

ndk-examples/Cargo.toml

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[package]
2+
name = "ndk-examples"
3+
version = "0.0.0"
4+
publish = false
5+
edition = "2021"
6+
7+
[lib]
8+
crate-type = ["cdylib"]
9+
10+
[dependencies]
11+
anyhow = "1"
12+
log = "0.4"
13+
ndk = { path = "../ndk", features = ["media", "api-level-35"] } # in sync
14+
ndk-sys = { path = "../ndk-sys" }
15+
rustix = { version = "0.38", default-features = false, features = ["std", "pipe", "stdio"] }
16+
# android-activity = { path = "../../android-activity/android-activity", features = ["native-activity"] }
17+
# android-activity = { version = "0.5", features = ["native-activity"] }
18+
# winit = { version = "0.29", features = ["android-native-activity"] }

ndk-examples/manifest.yaml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
android:
2+
manifest:
3+
uses_permission:
4+
- name: android.permission.INTERNET
5+
sdk:
6+
# Need at least API level 28 for MediaDataSource. Otherwise:
7+
# 4907 4963 W Parcel : Expecting binder but got null!
8+
# 4907 4963 E NuMediaExtractor: initMediaExtractor: failed to create MediaExtractor
9+
# 4907 4963 E le.ndk_examples: sf error code: -1010
10+
min_sdk_version: 33
11+
target_sdk_version: 33

ndk-examples/src/lib.rs

+173
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
use std::{
2+
ffi::{CStr, CString},
3+
fs::File,
4+
io::{BufRead as _, BufReader, Read},
5+
os::fd::AsFd,
6+
ptr::{addr_of, NonNull},
7+
sync::{Arc, Mutex},
8+
time::Duration,
9+
};
10+
11+
use anyhow::Result;
12+
use log::{error, info, Level};
13+
use ndk::{
14+
asset::AssetManager,
15+
data_space::DataSpace,
16+
hardware_buffer::HardwareBufferUsage,
17+
looper::{FdEvent, ThreadLooper},
18+
media::{
19+
image_reader::{Image, ImageFormat, ImageReader},
20+
media_format::MediaFormat,
21+
},
22+
native_activity::NativeActivity,
23+
native_window::NativeWindow,
24+
thermal::ThermalManager,
25+
// surface_control::{SurfaceControl, SurfaceTransaction},
26+
};
27+
28+
pub(crate) fn android_log(level: Level, tag: &CStr, msg: &CStr) {
29+
let prio = match level {
30+
Level::Error => ndk_sys::android_LogPriority::ANDROID_LOG_ERROR,
31+
Level::Warn => ndk_sys::android_LogPriority::ANDROID_LOG_WARN,
32+
Level::Info => ndk_sys::android_LogPriority::ANDROID_LOG_INFO,
33+
Level::Debug => ndk_sys::android_LogPriority::ANDROID_LOG_DEBUG,
34+
Level::Trace => ndk_sys::android_LogPriority::ANDROID_LOG_VERBOSE,
35+
};
36+
unsafe {
37+
ndk_sys::__android_log_write(prio.0 as i32, tag.as_ptr(), msg.as_ptr());
38+
}
39+
}
40+
41+
pub(crate) fn forward_stdio_to_logcat() -> std::thread::JoinHandle<std::io::Result<()>> {
42+
// XXX: make this stdout/stderr redirection an optional / opt-in feature?...
43+
44+
let file = {
45+
let logpipe = rustix::pipe::pipe().unwrap();
46+
rustix::stdio::dup2_stdout(&logpipe.1).unwrap();
47+
rustix::stdio::dup2_stderr(&logpipe.1).unwrap();
48+
49+
File::from(logpipe.0)
50+
};
51+
52+
std::thread::Builder::new()
53+
.name("stdio-to-logcat".to_string())
54+
.spawn(move || -> std::io::Result<()> {
55+
let tag = CStr::from_bytes_with_nul(b"RustStdoutStderr\0").unwrap();
56+
let mut reader = BufReader::new(file);
57+
let mut buffer = String::new();
58+
loop {
59+
buffer.clear();
60+
let len = match reader.read_line(&mut buffer) {
61+
Ok(len) => len,
62+
Err(e) => {
63+
error!("Logcat forwarder failed to read stdin/stderr: {e:?}");
64+
break Err(e);
65+
}
66+
};
67+
if len == 0 {
68+
break Ok(());
69+
} else if let Ok(msg) = CString::new(buffer.clone()) {
70+
android_log(Level::Info, tag, &msg);
71+
}
72+
}
73+
})
74+
.expect("Failed to start stdout/stderr to logcat forwarder thread")
75+
}
76+
77+
#[no_mangle]
78+
unsafe extern "C" fn ANativeActivity_onCreate(activity: *mut ndk_sys::ANativeActivity) {
79+
forward_stdio_to_logcat();
80+
81+
let activity = &mut *activity;
82+
83+
let mut thread = std::thread::spawn(move || {
84+
let looper = ThreadLooper::prepare();
85+
let (read, write) = rustix::pipe::pipe().unwrap();
86+
87+
println!("New thread ID {:?}", std::thread::current().id());
88+
let tm = Arc::new(ThermalManager::new().unwrap());
89+
dbg!(tm.current_thermal_status());
90+
// dbg!(tm
91+
// .thermal_headroom_thresholds()
92+
// .unwrap()
93+
// .unwrap()
94+
// .collect::<Vec<_>>());
95+
let token = Arc::new(Mutex::new(None));
96+
let t2 = token.clone();
97+
let tm2 = tm.clone();
98+
*t2.lock().unwrap() = Some(
99+
tm.register_thermal_status_listener(Box::new(move |s| {
100+
println!(
101+
"Thermal callback fired on ID {:?}",
102+
std::thread::current().id()
103+
);
104+
dbg!(s);
105+
println!("BEFORE UNREGISTERED");
106+
tm2.unregister_thermal_status_listener(dbg!(token.lock().unwrap().take().unwrap()))
107+
.unwrap();
108+
println!("UNREGISTERED");
109+
}))
110+
.unwrap(),
111+
);
112+
// std::thread::sleep(Duration::from_millis(2000));
113+
// tm.unregister_thermal_status_listener(x).unwrap();
114+
// std::thread::sleep(Duration::from_millis(200));
115+
looper
116+
.as_foreign()
117+
.add_fd(read.as_fd(), 10, FdEvent::all(), std::ptr::null_mut())
118+
.unwrap();
119+
120+
// rustix::io::write(&write, b"hello\0").unwrap();
121+
122+
loop {
123+
println!("Starting looper");
124+
match looper
125+
.poll_once()
126+
// .poll_once_timeout(Duration::from_millis(200))
127+
.unwrap()
128+
{
129+
ndk::looper::Poll::Wake => todo!(),
130+
ndk::looper::Poll::Callback => {
131+
info!("Callback");
132+
}
133+
ndk::looper::Poll::Timeout => {
134+
rustix::io::write(&write, b"Timeout\0").unwrap();
135+
}
136+
ndk::looper::Poll::Event {
137+
ident,
138+
fd,
139+
events,
140+
data,
141+
} => {
142+
dbg!(fd, events);
143+
let mut data = vec![0; 1024];
144+
let len = dbg!(rustix::io::read(fd, &mut data)).unwrap();
145+
dbg!(&data[..len]);
146+
147+
rustix::io::write(&write, b"Hello from event to CB\0").unwrap();
148+
149+
looper
150+
.as_foreign()
151+
.add_fd_with_callback(read.as_fd(), FdEvent::all(), |fd, event| {
152+
dbg!(fd, events);
153+
let mut data = vec![0; 1024];
154+
let len = dbg!(rustix::io::read(fd, &mut data)).unwrap();
155+
dbg!(&data[..len]);
156+
// rustix::io::write(&write, b"Hello from CB to whomever\0").unwrap();
157+
true
158+
// false
159+
})
160+
.unwrap();
161+
dbg!(&write);
162+
}
163+
}
164+
}
165+
// looper
166+
// .as_foreign()
167+
// .add_fd(read.as_fd(), 10, FdEvent::all(), std::ptr::null_mut());
168+
});
169+
170+
activity.instance = <*mut _>::cast(&mut thread);
171+
std::mem::forget(thread);
172+
// main(app).expect("Main failed")
173+
}

ndk/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ categories = ["os", "os::android-apis", "api-bindings"]
1515

1616
[features]
1717
default = ["rwh_06"]
18-
all = ["audio", "bitmap", "media", "nativewindow", "sync", "api-level-34", "rwh_04", "rwh_05", "rwh_06"]
18+
all = ["audio", "bitmap", "media", "nativewindow", "sync", "api-level-35", "rwh_04", "rwh_05", "rwh_06"]
1919

2020
audio = ["ffi/audio", "api-level-26"]
2121
bitmap = ["ffi/bitmap"]

0 commit comments

Comments
 (0)