@@ -2,11 +2,14 @@ use crate::error::AppError;
22use serde_json:: { json, Value } ;
33use std:: collections:: HashMap ;
44use std:: env;
5+ #[ cfg( unix) ]
56use std:: ffi:: CString ;
67use std:: ffi:: OsString ;
78use std:: io:: { Read , Write } ;
9+ #[ cfg( unix) ]
810use std:: mem:: MaybeUninit ;
911use std:: net:: { SocketAddr , TcpStream } ;
12+ #[ cfg( unix) ]
1013use std:: os:: fd:: RawFd ;
1114use std:: path:: { Path , PathBuf } ;
1215use std:: process:: { Command , Stdio } ;
@@ -36,6 +39,9 @@ const MODIFIER_OPTION: u32 = 1 << 2;
3639const MODIFIER_COMMAND : u32 = 1 << 3 ;
3740const MODIFIER_CAPS_LOCK : u32 = 1 << 4 ;
3841
42+ #[ cfg( not( unix) ) ]
43+ type RawFd = i32 ;
44+
3945type TimedMap < T > = Option < ( Instant , HashMap < String , T > ) > ;
4046type DisplayMetricsCache = HashMap < String , ( Instant , AndroidDisplayMetrics ) > ;
4147type ConsoleConnectionCache = HashMap < u16 , TcpStream > ;
@@ -1102,6 +1108,7 @@ impl AndroidSharedVideoFrameStream {
11021108
11031109impl Drop for AndroidSharedVideoFrameStream {
11041110 fn drop ( & mut self ) {
1111+ #[ cfg( unix) ]
11051112 unsafe {
11061113 if !self . ptr . is_null ( ) && self . length > 0 {
11071114 libc:: munmap ( self . ptr . cast ( ) , self . length ) ;
@@ -1150,75 +1157,86 @@ fn round_android_h264_dimension(value: u32) -> u32 {
11501157}
11511158
11521159fn open_android_shared_video_memory ( handle : & str ) -> Result < ( RawFd , * mut u8 , usize ) , AppError > {
1153- let mut names = vec ! [ handle. to_owned( ) ] ;
1154- if !handle. starts_with ( '/' ) {
1155- names. push ( format ! ( "/{handle}" ) ) ;
1156- }
1157- let mut last_error = None ;
1158- for name in names {
1159- let c_name = CString :: new ( name. as_str ( ) )
1160- . map_err ( |_| AppError :: native ( "Android shared video handle contains a NUL byte." ) ) ?;
1161- let fd = unsafe { libc:: shm_open ( c_name. as_ptr ( ) , libc:: O_RDONLY , 0 ) } ;
1162- if fd < 0 {
1163- last_error = Some ( std:: io:: Error :: last_os_error ( ) ) ;
1164- continue ;
1165- }
1160+ #[ cfg( not( unix) ) ]
1161+ {
1162+ return Err ( AppError :: native ( format ! (
1163+ "Android emulator shared video `{handle}` requires POSIX shared memory and is not available on this host."
1164+ ) ) ) ;
1165+ }
11661166
1167- let mut stat = MaybeUninit :: < libc:: stat > :: uninit ( ) ;
1168- if unsafe { libc:: fstat ( fd, stat. as_mut_ptr ( ) ) } != 0 {
1169- let error = std:: io:: Error :: last_os_error ( ) ;
1170- unsafe {
1171- libc:: close ( fd) ;
1172- }
1173- last_error = Some ( error) ;
1174- continue ;
1167+ #[ cfg( unix) ]
1168+ {
1169+ let mut names = vec ! [ handle. to_owned( ) ] ;
1170+ if !handle. starts_with ( '/' ) {
1171+ names. push ( format ! ( "/{handle}" ) ) ;
11751172 }
1176- let stat = unsafe { stat. assume_init ( ) } ;
1177- let length = usize:: try_from ( stat. st_size ) . map_err ( |_| {
1178- unsafe {
1179- libc:: close ( fd) ;
1173+ let mut last_error = None ;
1174+ for name in names {
1175+ let c_name = CString :: new ( name. as_str ( ) ) . map_err ( |_| {
1176+ AppError :: native ( "Android shared video handle contains a NUL byte." )
1177+ } ) ?;
1178+ let fd = unsafe { libc:: shm_open ( c_name. as_ptr ( ) , libc:: O_RDONLY , 0 ) } ;
1179+ if fd < 0 {
1180+ last_error = Some ( std:: io:: Error :: last_os_error ( ) ) ;
1181+ continue ;
11801182 }
1181- AppError :: native ( format ! (
1182- "Android emulator shared video `{handle}` reported an invalid size."
1183- ) )
1184- } ) ?;
1185- if length <= ANDROID_SHARED_VIDEO_HEADER_BYTES {
1186- unsafe {
1187- libc:: close ( fd) ;
1183+
1184+ let mut stat = MaybeUninit :: < libc:: stat > :: uninit ( ) ;
1185+ if unsafe { libc:: fstat ( fd, stat. as_mut_ptr ( ) ) } != 0 {
1186+ let error = std:: io:: Error :: last_os_error ( ) ;
1187+ unsafe {
1188+ libc:: close ( fd) ;
1189+ }
1190+ last_error = Some ( error) ;
1191+ continue ;
1192+ }
1193+ let stat = unsafe { stat. assume_init ( ) } ;
1194+ let length = usize:: try_from ( stat. st_size ) . map_err ( |_| {
1195+ unsafe {
1196+ libc:: close ( fd) ;
1197+ }
1198+ AppError :: native ( format ! (
1199+ "Android emulator shared video `{handle}` reported an invalid size."
1200+ ) )
1201+ } ) ?;
1202+ if length <= ANDROID_SHARED_VIDEO_HEADER_BYTES {
1203+ unsafe {
1204+ libc:: close ( fd) ;
1205+ }
1206+ return Err ( AppError :: native ( format ! (
1207+ "Android emulator shared video `{handle}` is smaller than the display header."
1208+ ) ) ) ;
11881209 }
1189- return Err ( AppError :: native ( format ! (
1190- "Android emulator shared video `{handle}` is smaller than the display header."
1191- ) ) ) ;
1192- }
11931210
1194- let ptr = unsafe {
1195- libc:: mmap (
1196- ptr:: null_mut ( ) ,
1197- length,
1198- libc:: PROT_READ ,
1199- libc:: MAP_SHARED ,
1200- fd,
1201- 0 ,
1202- )
1203- } ;
1204- if ptr == libc:: MAP_FAILED {
1205- let error = std:: io:: Error :: last_os_error ( ) ;
1206- unsafe {
1207- libc:: close ( fd) ;
1211+ let ptr = unsafe {
1212+ libc:: mmap (
1213+ ptr:: null_mut ( ) ,
1214+ length,
1215+ libc:: PROT_READ ,
1216+ libc:: MAP_SHARED ,
1217+ fd,
1218+ 0 ,
1219+ )
1220+ } ;
1221+ if ptr == libc:: MAP_FAILED {
1222+ let error = std:: io:: Error :: last_os_error ( ) ;
1223+ unsafe {
1224+ libc:: close ( fd) ;
1225+ }
1226+ last_error = Some ( error) ;
1227+ continue ;
12081228 }
1209- last_error = Some ( error) ;
1210- continue ;
1229+ return Ok ( ( fd, ptr. cast :: < u8 > ( ) , length) ) ;
12111230 }
1212- return Ok ( ( fd, ptr. cast :: < u8 > ( ) , length) ) ;
1213- }
12141231
1215- Err ( AppError :: native ( format ! (
1232+ Err ( AppError :: native ( format ! (
12161233 "Android emulator shared video `{handle}` is unavailable. Start the emulator through SimDeck or launch it with `-share-vid`{}." ,
12171234 last_error
12181235 . as_ref( )
12191236 . map( |error| format!( " ({error})" ) )
12201237 . unwrap_or_default( )
12211238 ) ) )
1239+ }
12221240}
12231241
12241242fn read_android_shared_video_header_volatile (
0 commit comments