debug: codecs
This commit is contained in:
parent
6cc3faff2e
commit
5591e1d0e3
4 changed files with 121 additions and 0 deletions
|
@ -4,6 +4,8 @@ import android.content.ContentUris
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
|
import android.media.MediaCodecInfo
|
||||||
|
import android.media.MediaCodecList
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
|
@ -47,6 +49,7 @@ class DebugHandler(private val context: Context) : MethodCallHandler {
|
||||||
"safeExceptionInCoroutine" -> GlobalScope.launch(Dispatchers.IO) { safe(call, result) { _, _ -> throw TestException() } }
|
"safeExceptionInCoroutine" -> GlobalScope.launch(Dispatchers.IO) { safe(call, result) { _, _ -> throw TestException() } }
|
||||||
|
|
||||||
"getContextDirs" -> GlobalScope.launch(Dispatchers.IO) { safe(call, result, ::getContextDirs) }
|
"getContextDirs" -> GlobalScope.launch(Dispatchers.IO) { safe(call, result, ::getContextDirs) }
|
||||||
|
"getCodecs" -> safe(call, result, ::getCodecs)
|
||||||
"getEnv" -> safe(call, result, ::getEnv)
|
"getEnv" -> safe(call, result, ::getEnv)
|
||||||
|
|
||||||
"getBitmapFactoryInfo" -> GlobalScope.launch(Dispatchers.IO) { safe(call, result, ::getBitmapFactoryInfo) }
|
"getBitmapFactoryInfo" -> GlobalScope.launch(Dispatchers.IO) { safe(call, result, ::getBitmapFactoryInfo) }
|
||||||
|
@ -83,6 +86,40 @@ class DebugHandler(private val context: Context) : MethodCallHandler {
|
||||||
result.success(dirs)
|
result.success(dirs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getCodecs(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) {
|
||||||
|
val codecs = ArrayList<FieldMap>()
|
||||||
|
|
||||||
|
fun getFields(info: MediaCodecInfo): FieldMap {
|
||||||
|
val fields: FieldMap = hashMapOf(
|
||||||
|
"name" to info.name,
|
||||||
|
"isEncoder" to info.isEncoder,
|
||||||
|
"supportedTypes" to info.supportedTypes.joinToString(", "),
|
||||||
|
)
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
if (info.canonicalName != info.name) fields["canonicalName"] = info.canonicalName
|
||||||
|
if (info.isAlias) fields["isAlias"] to info.isAlias
|
||||||
|
if (info.isHardwareAccelerated) fields["isHardwareAccelerated"] to info.isHardwareAccelerated
|
||||||
|
if (info.isSoftwareOnly) fields["isSoftwareOnly"] to info.isSoftwareOnly
|
||||||
|
if (info.isVendor) fields["isVendor"] to info.isVendor
|
||||||
|
}
|
||||||
|
return fields
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
codecs.addAll(MediaCodecList(MediaCodecList.REGULAR_CODECS).codecInfos.map(::getFields))
|
||||||
|
} else {
|
||||||
|
@Suppress("deprecation")
|
||||||
|
val count = MediaCodecList.getCodecCount()
|
||||||
|
for (i in 0 until count) {
|
||||||
|
@Suppress("deprecation")
|
||||||
|
val info = MediaCodecList.getCodecInfoAt(i)
|
||||||
|
codecs.add(getFields(info))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.success(codecs)
|
||||||
|
}
|
||||||
|
|
||||||
private fun getEnv(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) {
|
private fun getEnv(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) {
|
||||||
result.success(System.getenv())
|
result.success(System.getenv())
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,16 @@ class AndroidDebugService {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<List<Map>> getCodecs() async {
|
||||||
|
try {
|
||||||
|
final result = await platform.invokeMethod('getCodecs');
|
||||||
|
if (result != null) return (result as List).cast<Map>();
|
||||||
|
} on PlatformException catch (e, stack) {
|
||||||
|
await reportService.recordError(e, stack);
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
static Future<Map> getEnv() async {
|
static Future<Map> getEnv() async {
|
||||||
try {
|
try {
|
||||||
final result = await platform.invokeMethod('getEnv');
|
final result = await platform.invokeMethod('getEnv');
|
||||||
|
|
72
lib/widgets/debug/android_codecs.dart
Normal file
72
lib/widgets/debug/android_codecs.dart
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
import 'package:aves/services/android_debug_service.dart';
|
||||||
|
import 'package:aves/widgets/common/identity/aves_expansion_tile.dart';
|
||||||
|
import 'package:aves/widgets/common/identity/highlight_title.dart';
|
||||||
|
import 'package:aves/widgets/viewer/info/common.dart';
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class DebugAndroidCodecSection extends StatefulWidget {
|
||||||
|
const DebugAndroidCodecSection({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_DebugAndroidCodecSectionState createState() => _DebugAndroidCodecSectionState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DebugAndroidCodecSectionState extends State<DebugAndroidCodecSection> with AutomaticKeepAliveClientMixin {
|
||||||
|
late Future<List<Map>> _loader;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_loader = AndroidDebugService.getCodecs();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
super.build(context);
|
||||||
|
|
||||||
|
return AvesExpansionTile(
|
||||||
|
title: 'Android Codecs',
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 8, right: 8, bottom: 8),
|
||||||
|
child: FutureBuilder<List<Map>>(
|
||||||
|
future: _loader,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasError) return Text(snapshot.error.toString());
|
||||||
|
if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink();
|
||||||
|
final codecs = snapshot.data!.map((codec) {
|
||||||
|
return codec.map((k, v) => MapEntry(k.toString(), v.toString()));
|
||||||
|
}).toList()
|
||||||
|
..sort((a, b) => compareAsciiUpperCase(a['supportedTypes'] ?? '', b['supportedTypes'] ?? ''));
|
||||||
|
final byEncoder = groupBy<Map<String, String>, bool>(codecs, (v) => v['isEncoder'] == 'true');
|
||||||
|
final decoders = byEncoder[false] ?? [];
|
||||||
|
final encoders = byEncoder[true] ?? [];
|
||||||
|
Widget _toCodecColumn(List<Map<String, String>> codecs) => Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: codecs
|
||||||
|
.expand((v) => [
|
||||||
|
InfoRowGroup(info: Map.fromEntries(v.entries.where((kv) => kv.key != 'isEncoder'))),
|
||||||
|
const Divider(),
|
||||||
|
])
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const HighlightTitle(title: 'Decoders'),
|
||||||
|
_toCodecColumn(decoders),
|
||||||
|
const HighlightTitle(title: 'Encoders'),
|
||||||
|
_toCodecColumn(encoders),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get wantKeepAlive => true;
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import 'package:aves/services/analysis_service.dart';
|
||||||
import 'package:aves/widgets/common/identity/aves_expansion_tile.dart';
|
import 'package:aves/widgets/common/identity/aves_expansion_tile.dart';
|
||||||
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
|
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
|
||||||
import 'package:aves/widgets/debug/android_apps.dart';
|
import 'package:aves/widgets/debug/android_apps.dart';
|
||||||
|
import 'package:aves/widgets/debug/android_codecs.dart';
|
||||||
import 'package:aves/widgets/debug/android_dirs.dart';
|
import 'package:aves/widgets/debug/android_dirs.dart';
|
||||||
import 'package:aves/widgets/debug/android_env.dart';
|
import 'package:aves/widgets/debug/android_env.dart';
|
||||||
import 'package:aves/widgets/debug/cache.dart';
|
import 'package:aves/widgets/debug/cache.dart';
|
||||||
|
@ -46,6 +47,7 @@ class _AppDebugPageState extends State<AppDebugPage> {
|
||||||
children: [
|
children: [
|
||||||
_buildGeneralTabView(),
|
_buildGeneralTabView(),
|
||||||
const DebugAndroidAppSection(),
|
const DebugAndroidAppSection(),
|
||||||
|
const DebugAndroidCodecSection(),
|
||||||
const DebugAndroidDirSection(),
|
const DebugAndroidDirSection(),
|
||||||
const DebugAndroidEnvironmentSection(),
|
const DebugAndroidEnvironmentSection(),
|
||||||
const DebugCacheSection(),
|
const DebugCacheSection(),
|
||||||
|
|
Loading…
Reference in a new issue