-
Notifications
You must be signed in to change notification settings - Fork 921
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Android: fully implement
Monitor/VideoModeHandle
- Loading branch information
Showing
4 changed files
with
305 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
use android_activity::AndroidApp; | ||
use jni::objects::{JObject, JObjectArray, JString, JValueOwned}; | ||
use jni::{AttachGuard, JavaVM}; | ||
|
||
pub fn jvm(app: &AndroidApp) -> JavaVM { | ||
unsafe { JavaVM::from_raw(app.vm_as_ptr() as _) }.expect("unexpected null pointer") | ||
} | ||
|
||
pub fn env(jvm: &JavaVM) -> AttachGuard<'_> { | ||
jvm.attach_current_thread().expect("unexpected failure accessing `JNIEnv`") | ||
} | ||
|
||
pub fn activity<'e>(app: &AndroidApp, _: &AttachGuard<'e>) -> Activity<'e> { | ||
Activity(unsafe { JObject::from_raw(app.activity_as_ptr() as _) }) | ||
} | ||
|
||
pub struct Activity<'e>(JObject<'e>); | ||
|
||
impl Activity<'_> { | ||
pub fn window_manager<'e>(&self, env: &mut AttachGuard<'e>) -> WindowManager<'e> { | ||
WindowManager( | ||
env.call_method(&self.0, "getWindowManager", "()Landroid/view/WindowManager;", &[]) | ||
.and_then(JValueOwned::l) | ||
.expect("`Activity.getWindowManager()` is not expected to fail"), | ||
) | ||
} | ||
} | ||
|
||
pub fn context<'e>(_: &mut AttachGuard<'e>) -> Context<'e> { | ||
Context(unsafe { JObject::from_raw(ndk_context::android_context().context() as _) }) | ||
} | ||
|
||
pub struct Context<'e>(JObject<'e>); | ||
|
||
impl Context<'_> { | ||
pub fn display_manager<'e>(&self, env: &mut AttachGuard<'e>) -> DisplayManager<'e> { | ||
let class = env.get_object_class(&self.0).expect("failed to find `Context` class"); | ||
let display_service = env | ||
.get_static_field(&class, "DISPLAY_SERVICE", "Ljava/lang/String;") | ||
.expect("failed to find `Context.DISPLAY_SERVICE"); | ||
let display_manager = env | ||
.call_method(&self.0, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;", &[ | ||
(&display_service).into(), | ||
]) | ||
.and_then(JValueOwned::l) | ||
.expect( | ||
"`Context.getSystemService()` is not expected to fail with \ | ||
`Context.DISPLAY_SERVICE`", | ||
); | ||
|
||
DisplayManager(display_manager) | ||
} | ||
} | ||
|
||
pub struct DisplayManager<'e>(JObject<'e>); | ||
|
||
impl DisplayManager<'_> { | ||
pub fn display<'e>(&self, env: &mut AttachGuard<'e>, display_id: i32) -> Option<Display<'e>> { | ||
env.call_method(&self.0, "getDisplay", "(I)Landroid/view/Display;", &[display_id.into()]) | ||
.and_then(JValueOwned::l) | ||
.map(Display) | ||
.ok() | ||
} | ||
|
||
pub fn displays<'e>(&self, env: &mut AttachGuard<'e>) -> Vec<Display<'e>> { | ||
let displays = JObjectArray::from( | ||
env.call_method(&self.0, "getDisplays", "()[Landroid/view/Display;", &[]) | ||
.and_then(JValueOwned::l) | ||
.expect("`DisplayManager.getDisplays()` is not expected to fail"), | ||
); | ||
|
||
let length = env.get_array_length(&displays).unwrap(); | ||
|
||
(0..length) | ||
.map(|index| env.get_object_array_element(&displays, index).map(Display).unwrap()) | ||
.collect() | ||
} | ||
} | ||
|
||
pub struct WindowManager<'e>(JObject<'e>); | ||
|
||
impl WindowManager<'_> { | ||
pub fn default_display<'e>(&self, env: &mut AttachGuard<'e>) -> Display<'e> { | ||
Display( | ||
env.call_method(&self.0, "getDefaultDisplay", "()Landroid/view/Display;", &[]) | ||
.and_then(JValueOwned::l) | ||
.expect("`WindowManager.getDefaultDisplay()` is not expected to fail"), | ||
) | ||
} | ||
} | ||
|
||
pub struct Display<'e>(JObject<'e>); | ||
|
||
impl Display<'_> { | ||
pub fn default_display(env: &mut AttachGuard<'_>) -> i32 { | ||
let class = env.find_class("android/view/Display").expect("failed to find `Display`"); | ||
env.get_static_field(&class, "DEFAULT_DISPLAY", "I;") | ||
.and_then(JValueOwned::i) | ||
.expect("failed to find `Display.DEFAULT_DISPLAY") | ||
} | ||
|
||
pub fn display_id(&self, env: &mut AttachGuard<'_>) -> i32 { | ||
env.call_method(&self.0, "getDisplayId", "()I", &[]) | ||
.and_then(JValueOwned::i) | ||
.expect("`Display.getDisplayId()` is not expected to fail") | ||
} | ||
|
||
pub fn name(&self, env: &mut AttachGuard<'_>) -> String { | ||
let name = JString::from( | ||
env.call_method(&self.0, "getName", "()Ljava/lang/String;", &[]) | ||
.and_then(JValueOwned::l) | ||
.expect("`Display.name()` is not expected to fail"), | ||
); | ||
let name = env.get_string(&name).unwrap(); | ||
name.to_string_lossy().to_string() | ||
} | ||
|
||
pub fn mode<'e>(&self, env: &mut AttachGuard<'e>) -> Mode<'e> { | ||
Mode( | ||
env.call_method(&self.0, "getMode", "()Landroid/view/Display$Mode;", &[]) | ||
.and_then(JValueOwned::l) | ||
.expect("`Display.getMode()` is not expected to fail"), | ||
) | ||
} | ||
|
||
pub fn supported_modes<'e>(&self, env: &mut AttachGuard<'e>) -> Vec<Mode<'e>> { | ||
let modes = JObjectArray::from( | ||
env.call_method(&self.0, "getSupportedModes", "()[Landroid/view/Display$Mode;", &[]) | ||
.and_then(JValueOwned::l) | ||
.expect("`Display.getSupportedModes()` is not expected to fail"), | ||
); | ||
|
||
let length = env.get_array_length(&modes).unwrap(); | ||
|
||
(0..length) | ||
.map(|index| env.get_object_array_element(&modes, index).map(Mode).unwrap()) | ||
.collect() | ||
} | ||
} | ||
|
||
pub struct Mode<'e>(JObject<'e>); | ||
|
||
impl Mode<'_> { | ||
pub fn mode_id(&self, env: &mut AttachGuard<'_>) -> i32 { | ||
env.call_method(&self.0, "getModeId", "()I", &[]) | ||
.and_then(JValueOwned::i) | ||
.expect("`Display.Mode.getModeId()` is not expected to fail") | ||
} | ||
|
||
pub fn physical_width(&self, env: &mut AttachGuard<'_>) -> i32 { | ||
env.call_method(&self.0, "getPhysicalWidth", "()I", &[]) | ||
.and_then(JValueOwned::i) | ||
.expect("`Display.Mode.getPhysicalWidth()` is not expected to fail") | ||
} | ||
|
||
pub fn physical_height(&self, env: &mut AttachGuard<'_>) -> i32 { | ||
env.call_method(&self.0, "getPhysicalHeight", "()I", &[]) | ||
.and_then(JValueOwned::i) | ||
.expect("`Display.Mode.getPhysicalHeight()` is not expected to fail") | ||
} | ||
|
||
pub fn refresh_rate(&self, env: &mut AttachGuard<'_>) -> f32 { | ||
env.call_method(&self.0, "getRefreshRate", "()F", &[]) | ||
.and_then(JValueOwned::f) | ||
.expect("`Display.Mode.getRefreshRate()` is not expected to fail") | ||
} | ||
} |
Oops, something went wrong.