1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
use num_traits::FromPrimitive;
use crate::{DeviceDirection, SampleFormat};
use super::{
android_device_flags,
utils::{
call_method_no_args_ret_bool, call_method_no_args_ret_char_sequence,
call_method_no_args_ret_int, call_method_no_args_ret_int_array,
call_method_no_args_ret_string, get_context, get_devices, get_system_service,
with_attached, JNIEnv, JObject, JResult,
},
AudioDeviceInfo, AudioDeviceType, Context,
};
impl AudioDeviceInfo {
/**
* Request audio devices using Android Java API
*/
pub fn request(direction: DeviceDirection) -> Result<Vec<AudioDeviceInfo>, String> {
let context = get_context();
with_attached(context, |env, context| {
let sdk_version = env
.get_static_field("android/os/Build$VERSION", "SDK_INT", "I")?
.i()?;
if sdk_version >= 23 {
try_request_devices_info(env, &context, direction)
} else {
Err(jni::errors::Error::MethodNotFound {
name: "".into(),
sig: "".into(),
})
}
})
.map_err(|error| error.to_string())
}
}
fn try_request_devices_info<'j>(
env: &mut JNIEnv<'j>,
context: &JObject<'j>,
direction: DeviceDirection,
) -> JResult<Vec<AudioDeviceInfo>> {
let audio_manager = get_system_service(env, context, Context::AUDIO_SERVICE)?;
let devices = get_devices(env, &audio_manager, android_device_flags(direction))?;
let length = env.get_array_length(&devices)?;
(0..length)
.map(|index| {
let device = env.get_object_array_element(&devices, index)?;
let id = call_method_no_args_ret_int(env, &device, "getId")?;
let address = call_method_no_args_ret_string(env, &device, "getAddress")?;
let address = String::from(env.get_string(&address)?);
let product_name =
call_method_no_args_ret_char_sequence(env, &device, "getProductName")?;
let product_name = String::from(env.get_string(&product_name)?);
let device_type =
FromPrimitive::from_i32(call_method_no_args_ret_int(env, &device, "getType")?)
.unwrap_or(AudioDeviceType::Unsupported);
let is_source = call_method_no_args_ret_bool(env, &device, "isSource")?;
let is_sink = call_method_no_args_ret_bool(env, &device, "isSink")?;
let direction = crate::device_description::direction_from_caps(is_source, is_sink);
let channel_counts =
call_method_no_args_ret_int_array(env, &device, "getChannelCounts")?;
let sample_rates = call_method_no_args_ret_int_array(env, &device, "getSampleRates")?;
let formats = call_method_no_args_ret_int_array(env, &device, "getEncodings")?
.into_iter()
.filter_map(SampleFormat::from_encoding)
.collect::<Vec<_>>();
Ok(AudioDeviceInfo {
id,
address,
product_name,
device_type,
direction,
channel_counts,
sample_rates,
formats,
})
})
.collect::<Result<Vec<_>, _>>()
}
|