Merge branch 'main' of http://git.zhenbs.com:9999/2-group-android/DevCheck-lib
This commit is contained in:
commit
bca6640cc3
@ -13,8 +13,11 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.pm.PackageManager
|
||||
import android.media.MediaCodecInfo
|
||||
import android.media.MediaCodecList
|
||||
import android.os.Build
|
||||
import androidx.core.app.ActivityCompat
|
||||
import kotlin.text.compareTo
|
||||
|
||||
/**
|
||||
* 蓝牙信息工具类
|
||||
@ -73,7 +76,11 @@ class BluetoothInfo(private val context: Context) {
|
||||
val offloadedFiltering: Boolean, // 硬件过滤
|
||||
val offloadedScanBatching: Boolean, // 批量扫描
|
||||
val multipleAdvertisement: Boolean, // 多广播
|
||||
val lowEnergyExtended: Boolean // 扩展LE
|
||||
val lowEnergyExtended: Boolean, // 扩展LE
|
||||
val lowLatencyAudio: Boolean, // 低延迟音频
|
||||
val proAudio: Boolean, // 专业音频
|
||||
val midiSupport: Boolean, // MIDI支持
|
||||
val supportedCodecs: List<String> // 支持的编解码器
|
||||
)
|
||||
|
||||
// ==================== 基本信息 ====================
|
||||
@ -305,6 +312,7 @@ class BluetoothInfo(private val context: Context) {
|
||||
*/
|
||||
fun getBluetoothFeatures(): BluetoothFeatures {
|
||||
val adapter = bluetoothAdapter
|
||||
val pm = context.packageManager
|
||||
|
||||
return BluetoothFeatures(
|
||||
version = getBluetoothVersion(),
|
||||
@ -336,15 +344,15 @@ class BluetoothInfo(private val context: Context) {
|
||||
} else false,
|
||||
|
||||
leAudioSupport = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
context.packageManager.hasSystemFeature("android.hardware.bluetooth.le.audio")
|
||||
pm.hasSystemFeature("android.hardware.bluetooth.le.audio")
|
||||
} else false,
|
||||
|
||||
leAudioBroadcast = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
context.packageManager.hasSystemFeature("android.hardware.bluetooth.le.audio.broadcast_source")
|
||||
pm.hasSystemFeature("android.hardware.bluetooth.le.audio.broadcast_source")
|
||||
} else false,
|
||||
|
||||
leAudioUnicast = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
context.packageManager.hasSystemFeature("android.hardware.bluetooth.le.audio.unicast_client")
|
||||
pm.hasSystemFeature("android.hardware.bluetooth.le.audio.unicast_client")
|
||||
} else false,
|
||||
|
||||
// 其他特性
|
||||
@ -362,10 +370,40 @@ class BluetoothInfo(private val context: Context) {
|
||||
|
||||
lowEnergyExtended = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
adapter?.isLeExtendedAdvertisingSupported == true
|
||||
} else false
|
||||
} else false,
|
||||
// 音频和MIDI特性
|
||||
lowLatencyAudio = pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY),
|
||||
proAudio = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_PRO)
|
||||
} else false,
|
||||
midiSupport = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
pm.hasSystemFeature(PackageManager.FEATURE_MIDI)
|
||||
} else false,
|
||||
|
||||
// 支持的编解码器
|
||||
supportedCodecs = getSupportedCodecs()
|
||||
)
|
||||
}
|
||||
|
||||
private fun getSupportedAudioCodecs(): List<MediaCodecInfo> {
|
||||
val codecList = MediaCodecList(MediaCodecList.ALL_CODECS)
|
||||
return codecList.codecInfos.filter { codecInfo ->
|
||||
!codecInfo.isEncoder && // 解码器(如果你要编码器,改成 true)
|
||||
codecInfo.supportedTypes.any { it.startsWith("audio/") }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取支持的蓝牙音频编解码器
|
||||
*/
|
||||
@SuppressLint("MissingPermission")
|
||||
private fun getSupportedCodecs(): List<String> {
|
||||
return getSupportedAudioCodecs().flatMap { codecInfo ->
|
||||
codecInfo.supportedTypes.map { it }
|
||||
}.distinct().sorted()
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取蓝牙版本(根据支持的特性推断)
|
||||
|
||||
@ -2,6 +2,7 @@ package com.xyzshell.andinfo.libs
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
// import androidx.security.state.SecurityStateManagerCompat
|
||||
@ -548,6 +549,29 @@ class BuildInfo(private val context: Context) {
|
||||
val googleServicesFrameworkVersion: String?
|
||||
get() = getPackageVersion("com.google.android.gsf")
|
||||
|
||||
/**
|
||||
* GSF ID(Google Services Framework ID)
|
||||
* 设备的唯一标识符
|
||||
*/
|
||||
val googleServicesFrameworkId: String?
|
||||
get() = getGSFId(context)
|
||||
|
||||
|
||||
private fun getGSFId(context: Context): String? {
|
||||
return try {
|
||||
val uri = Uri.parse("content://com.google.android.gsf.gservices")
|
||||
val params = arrayOf("android_id")
|
||||
context.contentResolver.query(uri, null, null, params, null)?.use { cursor ->
|
||||
if (cursor.moveToFirst() && cursor.columnCount >= 2) {
|
||||
cursor.getString(1)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 获取包版本名称
|
||||
*/
|
||||
|
||||
@ -2,6 +2,7 @@ package com.xyzshell.andinfo.libs
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.graphics.ImageFormat
|
||||
import android.hardware.camera2.CameraCharacteristics
|
||||
import android.hardware.camera2.CameraManager
|
||||
import android.hardware.camera2.CameraMetadata
|
||||
@ -9,12 +10,14 @@ import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Range
|
||||
import android.util.Size
|
||||
import android.util.SizeF
|
||||
import com.xyzshell.andinfo.R
|
||||
import com.xyzshell.andinfo.libs.camera.models.CameraCapability
|
||||
import com.xyzshell.andinfo.libs.camera.models.CameraFacing
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.math.sqrt
|
||||
|
||||
/**
|
||||
@ -92,6 +95,7 @@ class CameraInfo(private val context: Context) {
|
||||
val maxFrameRate: Int?, // 最大帧率
|
||||
val supportsHighSpeedVideo: Boolean, // 是否支持高速视频
|
||||
val supports4K: Boolean, // 是否支持4K录制
|
||||
val streamConfigurations: List<String>?, // 视频-型材 ; 视频采集流配置列表 (格式: 宽x高 @ 帧率 Hz, 格式)
|
||||
val supports8K: Boolean // 是否支持8K录制
|
||||
)
|
||||
|
||||
@ -636,6 +640,56 @@ class CameraInfo(private val context: Context) {
|
||||
return resolution?.contains("7680") == true
|
||||
}
|
||||
|
||||
// ==================== 视频能力 ====================
|
||||
|
||||
/**
|
||||
* 获取支持的视频流配置 (分辨率@帧率)
|
||||
*/
|
||||
fun getStreamConfigurations(characteristics: CameraCharacteristics): List<String>? {
|
||||
val map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP) ?: return null
|
||||
val configs = mutableMapOf<Size, MutableSet<Int>>()
|
||||
|
||||
// 遍历所有支持的尺寸
|
||||
val outputSizes = map.getOutputSizes(ImageFormat.YUV_420_888) ?: map.getOutputSizes(ImageFormat.PRIVATE)
|
||||
outputSizes?.forEach { size ->
|
||||
// 获取该尺寸下的最小帧间隔(纳秒),从而计算出最大帧率
|
||||
val minFrameDuration = map.getOutputMinFrameDuration(ImageFormat.YUV_420_888, size)
|
||||
if (minFrameDuration > 0) {
|
||||
val maxFps = (1_000_000_000.0 / minFrameDuration).roundToInt()
|
||||
if (!configs.containsKey(size)) {
|
||||
configs[size] = mutableSetOf()
|
||||
}
|
||||
configs[size]?.add(maxFps)
|
||||
}
|
||||
}
|
||||
|
||||
// 检查高速视频配置
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
map.highSpeedVideoSizes.forEach { size ->
|
||||
map.getHighSpeedVideoFpsRangesFor(size).forEach { range ->
|
||||
if (!configs.containsKey(size)) {
|
||||
configs[size] = mutableSetOf()
|
||||
}
|
||||
// 通常高速视频会使用固定的高帧率
|
||||
configs[size]?.add(range.upper)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 格式化输出
|
||||
return configs.map { (size, fpsSet) ->
|
||||
val resolutionName = when {
|
||||
size.width == 7680 && size.height == 4320 -> "8K UHD"
|
||||
size.width == 3840 && size.height == 2160 -> "4K UHD"
|
||||
size.width == 1920 && size.height == 1080 -> "1080p"
|
||||
size.width == 1280 && size.height == 720 -> "720p"
|
||||
else -> "${size.width}x${size.height}"
|
||||
}
|
||||
val fpsString = fpsSet.sortedDescending().joinToString("/")
|
||||
"$resolutionName @ $fpsString Hz"
|
||||
}.sortedDescending() // 按分辨率排序
|
||||
}
|
||||
|
||||
// ==================== 综合信息 ====================
|
||||
|
||||
/**
|
||||
@ -693,6 +747,7 @@ class CameraInfo(private val context: Context) {
|
||||
maxFrameRate = getMaxFrameRate(characteristics),
|
||||
supportsHighSpeedVideo = supportsHighSpeedVideo(characteristics),
|
||||
supports4K = supports4K(characteristics),
|
||||
streamConfigurations = getStreamConfigurations(characteristics),
|
||||
supports8K = supports8K(characteristics)
|
||||
)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user