android video service wakelock

Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
21pages 2023-11-23 19:47:16 +08:00
parent c6ace470e3
commit bd81e4d0fb
7 changed files with 87 additions and 9 deletions

13
Cargo.lock generated
View File

@ -121,6 +121,17 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android-wakelock"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "296e5b7c23adb32743194b1810604b772f2be10f0b0387365cb3ba09cd5c1851"
dependencies = [
"jni 0.21.1",
"log",
"ndk-context",
]
[[package]] [[package]]
name = "android_log-sys" name = "android_log-sys"
version = "0.3.1" version = "0.3.1"
@ -5197,6 +5208,7 @@ dependencies = [
name = "rustdesk" name = "rustdesk"
version = "1.2.4" version = "1.2.4"
dependencies = [ dependencies = [
"android-wakelock",
"android_logger", "android_logger",
"arboard", "arboard",
"async-process", "async-process",
@ -5487,6 +5499,7 @@ dependencies = [
"lazy_static", "lazy_static",
"log", "log",
"ndk", "ndk",
"ndk-context",
"num_cpus", "num_cpus",
"pkg-config", "pkg-config",
"quest", "quest",

View File

@ -147,6 +147,7 @@ once_cell = {version = "1.18", optional = true}
[target.'cfg(target_os = "android")'.dependencies] [target.'cfg(target_os = "android")'.dependencies]
android_logger = "0.13" android_logger = "0.13"
jni = "0.21" jni = "0.21"
android-wakelock = "0.1"
[workspace] [workspace]
members = ["libs/scrap", "libs/hbb_common", "libs/enigo", "libs/clipboard", "libs/virtual_display", "libs/virtual_display/dylib", "libs/portable"] members = ["libs/scrap", "libs/hbb_common", "libs/enigo", "libs/clipboard", "libs/virtual_display", "libs/virtual_display/dylib", "libs/portable"]

View File

@ -211,6 +211,7 @@ class MainService : Service() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
Log.d(logTag,"MainService onCreate") Log.d(logTag,"MainService onCreate")
init(this)
HandlerThread("Service", Process.THREAD_PRIORITY_BACKGROUND).apply { HandlerThread("Service", Process.THREAD_PRIORITY_BACKGROUND).apply {
start() start()
serviceLooper = looper serviceLooper = looper
@ -315,7 +316,6 @@ class MainService : Service() {
mediaProjection = mediaProjection =
mediaProjectionManager.getMediaProjection(Activity.RESULT_OK, it) mediaProjectionManager.getMediaProjection(Activity.RESULT_OK, it)
checkMediaPermission() checkMediaPermission()
init(this)
_isReady = true _isReady = true
} ?: let { } ?: let {
Log.d(logTag, "getParcelableExtra intent null, invoke requestMediaProjection") Log.d(logTag, "getParcelableExtra intent null, invoke requestMediaProjection")

View File

@ -36,6 +36,7 @@ lazy_static = "1.4"
log = "0.4" log = "0.4"
serde_json = "1.0" serde_json = "1.0"
ndk = { version = "0.7", features = ["media"], optional = true} ndk = { version = "0.7", features = ["media"], optional = true}
ndk-context = "0.1"
[target.'cfg(not(target_os = "android"))'.dev-dependencies] [target.'cfg(not(target_os = "android"))'.dev-dependencies]
repng = "0.2" repng = "0.2"

View File

@ -19,6 +19,7 @@ lazy_static! {
static ref MAIN_SERVICE_CTX: RwLock<Option<GlobalRef>> = RwLock::new(None); // MainService -> video service / audio service / info static ref MAIN_SERVICE_CTX: RwLock<Option<GlobalRef>> = RwLock::new(None); // MainService -> video service / audio service / info
static ref VIDEO_RAW: Mutex<FrameRaw> = Mutex::new(FrameRaw::new("video", MAX_VIDEO_FRAME_TIMEOUT)); static ref VIDEO_RAW: Mutex<FrameRaw> = Mutex::new(FrameRaw::new("video", MAX_VIDEO_FRAME_TIMEOUT));
static ref AUDIO_RAW: Mutex<FrameRaw> = Mutex::new(FrameRaw::new("audio", MAX_AUDIO_FRAME_TIMEOUT)); static ref AUDIO_RAW: Mutex<FrameRaw> = Mutex::new(FrameRaw::new("audio", MAX_AUDIO_FRAME_TIMEOUT));
static ref NDK_CONTEXT_INITED: Mutex<bool> = Default::default();
} }
const MAX_VIDEO_FRAME_TIMEOUT: Duration = Duration::from_millis(100); const MAX_VIDEO_FRAME_TIMEOUT: Duration = Duration::from_millis(100);
@ -150,6 +151,7 @@ pub extern "system" fn Java_com_carriez_flutter_1hbb_MainService_init(
*JVM.write().unwrap() = Some(jvm); *JVM.write().unwrap() = Some(jvm);
if let Ok(context) = env.new_global_ref(ctx) { if let Ok(context) = env.new_global_ref(ctx) {
*MAIN_SERVICE_CTX.write().unwrap() = Some(context); *MAIN_SERVICE_CTX.write().unwrap() = Some(context);
init_ndk_context().ok();
} }
} }
} }
@ -165,7 +167,12 @@ pub fn call_main_service_pointer_input(kind: &str, mask: i32, x: i32, y: i32) ->
ctx, ctx,
"rustPointerInput", "rustPointerInput",
"(Ljava/lang/String;III)V", "(Ljava/lang/String;III)V",
&[JValue::Object(&JObject::from(kind)), JValue::Int(mask), JValue::Int(x), JValue::Int(y)], &[
JValue::Object(&JObject::from(kind)),
JValue::Int(mask),
JValue::Int(x),
JValue::Int(y),
],
)?; )?;
return Ok(()); return Ok(());
} else { } else {
@ -246,3 +253,26 @@ pub fn call_main_service_set_by_name(
return Err(JniError::ThrowFailed(-1)); return Err(JniError::ThrowFailed(-1));
} }
} }
fn init_ndk_context() -> JniResult<()> {
let mut lock = NDK_CONTEXT_INITED.lock().unwrap();
if *lock {
unsafe {
ndk_context::release_android_context();
}
}
if let (Some(jvm), Some(ctx)) = (
JVM.read().unwrap().as_ref(),
MAIN_SERVICE_CTX.read().unwrap().as_ref(),
) {
unsafe {
ndk_context::initialize_android_context(
jvm.get_java_vm_pointer() as _,
ctx.as_obj().as_raw() as _,
);
}
*lock = true;
return Ok(());
}
Err(JniError::ThrowFailed(-1))
}

View File

@ -80,6 +80,39 @@ pub fn get_active_username() -> String {
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
pub const PA_SAMPLE_RATE: u32 = 48000; pub const PA_SAMPLE_RATE: u32 = 48000;
#[cfg(target_os = "android")]
#[derive(Default)]
pub struct WakeLock {
lock: Option<android_wakelock::WakeLock>,
}
#[cfg(target_os = "android")]
impl WakeLock {
pub fn new(tag: &str) -> Self {
let tag = format!("{}:{tag}", crate::get_app_name());
match android_wakelock::partial(tag) {
Ok(lock) => Self { lock: Some(lock) },
Err(e) => {
hbb_common::log::error!("Failed to get wakelock: {e:?}");
Self::default()
}
}
}
pub fn acquire(&self) -> Option<android_wakelock::Guard> {
match self.lock.as_ref() {
Some(lock) => match lock.acquire() {
Ok(guard) => Some(guard),
Err(e) => {
hbb_common::log::error!("Failed to acquire wakelock guard: {e:?}");
None
}
},
None => None,
}
}
}
pub(crate) struct InstallingService; // please use new pub(crate) struct InstallingService; // please use new
impl InstallingService { impl InstallingService {

View File

@ -363,8 +363,12 @@ fn get_capturer(current: usize, portable_service_running: bool) -> ResultType<Ca
} }
fn run(vs: VideoService) -> ResultType<()> { fn run(vs: VideoService) -> ResultType<()> {
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(target_os = "android"))]
let _wake_lock = get_wake_lock(); let _wake_lock = get_wake_lock();
#[cfg(target_os = "android")]
let wake_lock = crate::platform::WakeLock::new("video service");
#[cfg(target_os = "android")]
let _lock_guard = wake_lock.acquire();
// Wayland only support one video capturer for now. It is ok to call ensure_inited() here. // Wayland only support one video capturer for now. It is ok to call ensure_inited() here.
// //
@ -619,7 +623,6 @@ fn get_recorder(
height: usize, height: usize,
codec_name: &CodecName, codec_name: &CodecName,
) -> Arc<Mutex<Option<Recorder>>> { ) -> Arc<Mutex<Option<Recorder>>> {
#[cfg(not(target_os = "ios"))]
let recorder = if !Config::get_option("allow-auto-record-incoming").is_empty() { let recorder = if !Config::get_option("allow-auto-record-incoming").is_empty() {
use crate::hbbs_http::record_upload; use crate::hbbs_http::record_upload;
@ -644,8 +647,6 @@ fn get_recorder(
} else { } else {
Default::default() Default::default()
}; };
#[cfg(target_os = "ios")]
let recorder: Arc<Mutex<Option<Recorder>>> = Default::default();
recorder recorder
} }
@ -690,7 +691,6 @@ fn handle_one_frame(
vf.display = display as _; vf.display = display as _;
let mut msg = Message::new(); let mut msg = Message::new();
msg.set_video_frame(vf); msg.set_video_frame(vf);
#[cfg(not(target_os = "ios"))]
recorder recorder
.lock() .lock()
.unwrap() .unwrap()
@ -735,7 +735,7 @@ fn start_uac_elevation_check() {
}); });
} }
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(target_os = "android"))]
fn get_wake_lock() -> crate::platform::WakeLock { fn get_wake_lock() -> crate::platform::WakeLock {
let (display, idle, sleep) = if cfg!(windows) { let (display, idle, sleep) = if cfg!(windows) {
(true, false, false) (true, false, false)
@ -784,7 +784,7 @@ pub fn make_display_changed_msg(
width: display.width, width: display.width,
height: display.height, height: display.height,
cursor_embedded: display_service::capture_cursor_embedded(), cursor_embedded: display_service::capture_cursor_embedded(),
#[cfg(not(any(target_os = "android", target_os = "ios")))] #[cfg(not(target_os = "android"))]
resolutions: Some(SupportedResolutions { resolutions: Some(SupportedResolutions {
resolutions: if display.name.is_empty() { resolutions: if display.name.is_empty() {
vec![] vec![]