@@ -22,11 +22,10 @@ async fn pull_android_db_file(
2222 let temp_dir = ensure_temp_dir ( ) ?;
2323 info ! ( "Temp directory: {:?}" , temp_dir) ;
2424
25- let filename = Path :: new ( remote_path) . file_name ( )
26- . ok_or ( "Invalid remote path" ) ?
27- . to_string_lossy ( ) ;
28- let local_path = temp_dir. join ( & * filename) ;
29- info ! ( "Local path will be: {:?}" , local_path) ;
25+ // Generate unique filename to avoid conflicts when multiple files have the same name
26+ let unique_filename = generate_unique_filename ( remote_path) ?;
27+ let local_path = temp_dir. join ( & unique_filename) ;
28+ info ! ( "Local path will be: {:?} (unique filename: {})" , local_path, unique_filename) ;
3029
3130 // Execute ADB command based on admin access
3231 if admin_access {
@@ -449,7 +448,115 @@ pub async fn adb_push_database_file(
449448 success : false ,
450449 data : None ,
451450 error : Some ( format ! ( "Failed to push database file: {}" , e) ) ,
452- } ) ,
451+ } )
452+ }
453+ }
454+
455+ // Get detailed Android device information using adb shell getprop
456+ async fn get_android_device_info ( device_id : & str ) -> Result < std:: collections:: HashMap < String , String > , Box < dyn std:: error:: Error + Send + Sync > > {
457+ info ! ( "Getting Android device info for device: {}" , device_id) ;
458+
459+ let output = execute_adb_command ( & [ "-s" , device_id, "shell" , "getprop" ] ) . await ?;
460+
461+ info ! ( "ADB getprop exit status: {:?}" , output. status) ;
462+
463+ if !output. status . success ( ) {
464+ let stderr = String :: from_utf8_lossy ( & output. stderr ) ;
465+ error ! ( "ADB getprop command failed. Stderr: {}" , stderr) ;
466+ return Err ( format ! ( "ADB getprop failed with exit code: {:?}. Stderr: {}" , output. status. code( ) , stderr) . into ( ) ) ;
467+ }
468+
469+ let stdout = String :: from_utf8_lossy ( & output. stdout ) ;
470+ info ! ( "ADB getprop output length: {} characters" , stdout. len( ) ) ;
471+
472+ let mut device_info = std:: collections:: HashMap :: new ( ) ;
473+ let mut processed_lines = 0 ;
474+
475+ // Parse getprop output and extract key device information
476+ for line in stdout. lines ( ) {
477+ if line. starts_with ( '[' ) && line. contains ( "]: [" ) {
478+ if let Some ( key_end) = line. find ( "]: [" ) {
479+ let key = & line[ 1 ..key_end] ;
480+ if let Some ( value_start) = line. rfind ( "]: [" ) {
481+ let value_part = & line[ value_start + 4 ..] ;
482+ if let Some ( value_end) = value_part. rfind ( ']' ) {
483+ let value = & value_part[ ..value_end] ;
484+
485+ // Only include relevant device info properties
486+ match key {
487+ "ro.product.model" => {
488+ device_info. insert ( "Device Model" . to_string ( ) , value. to_string ( ) ) ;
489+ info ! ( "Found device model: {}" , value) ;
490+ } ,
491+ "ro.product.brand" => {
492+ device_info. insert ( "Brand" . to_string ( ) , value. to_string ( ) ) ;
493+ info ! ( "Found brand: {}" , value) ;
494+ } ,
495+ "ro.product.manufacturer" => { device_info. insert ( "Manufacturer" . to_string ( ) , value. to_string ( ) ) ; } ,
496+ "ro.build.version.release" => {
497+ device_info. insert ( "Android Version" . to_string ( ) , value. to_string ( ) ) ;
498+ info ! ( "Found Android version: {}" , value) ;
499+ } ,
500+ "ro.build.version.sdk" => { device_info. insert ( "SDK Version" . to_string ( ) , value. to_string ( ) ) ; } ,
501+ "ro.build.display.id" => { device_info. insert ( "Build ID" . to_string ( ) , value. to_string ( ) ) ; } ,
502+ "ro.product.cpu.abi" => { device_info. insert ( "CPU Architecture" . to_string ( ) , value. to_string ( ) ) ; } ,
503+ "ro.build.date" => { device_info. insert ( "Build Date" . to_string ( ) , value. to_string ( ) ) ; } ,
504+ "ro.product.device" => { device_info. insert ( "Device Codename" . to_string ( ) , value. to_string ( ) ) ; } ,
505+ "ro.build.version.security_patch" => { device_info. insert ( "Security Patch" . to_string ( ) , value. to_string ( ) ) ; } ,
506+ _ => { }
507+ }
508+ processed_lines += 1 ;
509+ }
510+ }
511+ }
512+ }
513+ }
514+
515+ info ! ( "Processed {} lines from getprop output" , processed_lines) ;
516+
517+ // Add device ID
518+ device_info. insert ( "Device ID" . to_string ( ) , device_id. to_string ( ) ) ;
519+
520+ info ! ( "Successfully retrieved {} device properties" , device_info. len( ) ) ;
521+
522+ if device_info. len ( ) <= 1 {
523+ // Only device ID was added, no properties found
524+ error ! ( "No device properties found in getprop output" ) ;
525+ return Err ( "No device properties could be retrieved from the device" . into ( ) ) ;
526+ }
527+
528+ Ok ( device_info)
529+ }
530+
531+ // Get detailed Android device information
532+ #[ tauri:: command]
533+ pub async fn adb_get_device_info ( device_id : String ) -> Result < DeviceResponse < std:: collections:: HashMap < String , String > > , String > {
534+ log:: info!( "Getting device info for Android device: {}" , device_id) ;
535+
536+ match get_android_device_info ( & device_id) . await {
537+ Ok ( info) => {
538+ log:: info!( "Successfully retrieved device info with {} properties" , info. len( ) ) ;
539+ Ok ( DeviceResponse {
540+ success : true ,
541+ data : Some ( info) ,
542+ error : None ,
543+ } )
544+ } ,
545+ Err ( e) => {
546+ log:: error!( "Failed to get device info: {}" , e) ;
547+
548+ // Return mock data for testing if real command fails
549+ let mut mock_info = std:: collections:: HashMap :: new ( ) ;
550+ mock_info. insert ( "Device ID" . to_string ( ) , device_id. clone ( ) ) ;
551+ mock_info. insert ( "Status" . to_string ( ) , "Mock Data - Real command failed" . to_string ( ) ) ;
552+ mock_info. insert ( "Error" . to_string ( ) , format ! ( "{}" , e) ) ;
553+
554+ Ok ( DeviceResponse {
555+ success : true ,
556+ data : Some ( mock_info) ,
557+ error : Some ( format ! ( "Using mock data - real command failed: {}" , e) ) ,
558+ } )
559+ } ,
453560 }
454561}
455562
0 commit comments