Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

android video service wakelock #6515

Merged
merged 1 commit into from Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -147,6 +147,7 @@ once_cell = {version = "1.18", optional = true}
[target.'cfg(target_os = "android")'.dependencies]
android_logger = "0.13"
jni = "0.21"
android-wakelock = "0.1"

[workspace]
members = ["libs/scrap", "libs/hbb_common", "libs/enigo", "libs/clipboard", "libs/virtual_display", "libs/virtual_display/dylib", "libs/portable"]
Expand Down
Expand Up @@ -211,6 +211,7 @@ class MainService : Service() {
override fun onCreate() {
super.onCreate()
Log.d(logTag,"MainService onCreate")
init(this)
HandlerThread("Service", Process.THREAD_PRIORITY_BACKGROUND).apply {
start()
serviceLooper = looper
Expand Down Expand Up @@ -315,7 +316,6 @@ class MainService : Service() {
mediaProjection =
mediaProjectionManager.getMediaProjection(Activity.RESULT_OK, it)
checkMediaPermission()
init(this)
_isReady = true
} ?: let {
Log.d(logTag, "getParcelableExtra intent null, invoke requestMediaProjection")
Expand Down
1 change: 1 addition & 0 deletions libs/scrap/Cargo.toml
Expand Up @@ -36,6 +36,7 @@ lazy_static = "1.4"
log = "0.4"
serde_json = "1.0"
ndk = { version = "0.7", features = ["media"], optional = true}
ndk-context = "0.1"

[target.'cfg(not(target_os = "android"))'.dev-dependencies]
repng = "0.2"
Expand Down
32 changes: 31 additions & 1 deletion libs/scrap/src/android/ffi.rs
Expand Up @@ -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 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 NDK_CONTEXT_INITED: Mutex<bool> = Default::default();
}

const MAX_VIDEO_FRAME_TIMEOUT: Duration = Duration::from_millis(100);
Expand Down Expand Up @@ -150,6 +151,7 @@ pub extern "system" fn Java_com_carriez_flutter_1hbb_MainService_init(
*JVM.write().unwrap() = Some(jvm);
if let Ok(context) = env.new_global_ref(ctx) {
*MAIN_SERVICE_CTX.write().unwrap() = Some(context);
init_ndk_context().ok();
}
}
}
Expand All @@ -165,7 +167,12 @@ pub fn call_main_service_pointer_input(kind: &str, mask: i32, x: i32, y: i32) ->
ctx,
"rustPointerInput",
"(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(());
} else {
Expand Down Expand Up @@ -246,3 +253,26 @@ pub fn call_main_service_set_by_name(
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))
}
33 changes: 33 additions & 0 deletions src/platform/mod.rs
Expand Up @@ -80,6 +80,39 @@ pub fn get_active_username() -> String {
#[cfg(target_os = "android")]
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

impl InstallingService {
Expand Down
14 changes: 7 additions & 7 deletions src/server/video_service.rs
Expand Up @@ -363,8 +363,12 @@ fn get_capturer(current: usize, portable_service_running: bool) -> ResultType<Ca
}

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();
#[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.
//
Expand Down Expand Up @@ -619,7 +623,6 @@ fn get_recorder(
height: usize,
codec_name: &CodecName,
) -> Arc<Mutex<Option<Recorder>>> {
#[cfg(not(target_os = "ios"))]
let recorder = if !Config::get_option("allow-auto-record-incoming").is_empty() {
use crate::hbbs_http::record_upload;

Expand All @@ -644,8 +647,6 @@ fn get_recorder(
} else {
Default::default()
};
#[cfg(target_os = "ios")]
let recorder: Arc<Mutex<Option<Recorder>>> = Default::default();

recorder
}
Expand Down Expand Up @@ -690,7 +691,6 @@ fn handle_one_frame(
vf.display = display as _;
let mut msg = Message::new();
msg.set_video_frame(vf);
#[cfg(not(target_os = "ios"))]
recorder
.lock()
.unwrap()
Expand Down Expand Up @@ -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 {
let (display, idle, sleep) = if cfg!(windows) {
(true, false, false)
Expand Down Expand Up @@ -784,7 +784,7 @@ pub fn make_display_changed_msg(
width: display.width,
height: display.height,
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: if display.name.is_empty() {
vec![]
Expand Down