debug: codecs

This commit is contained in:
Thibault Deckers 2021-11-09 16:51:09 +09:00
parent 6cc3faff2e
commit 5591e1d0e3
4 changed files with 121 additions and 0 deletions

View file

@ -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())
} }

View file

@ -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');

View 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;
}

View file

@ -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(),