revanced-manager/lib/services/root_api.dart

149 lines
4.4 KiB
Dart
Raw Normal View History

2022-08-14 20:40:34 +02:00
import 'package:root/root.dart';
class RootAPI {
final String _managerDirPath = '/data/adb/revanced_manager';
final String _postFsDataDirPath = '/data/adb/post-fs-data.d';
final String _serviceDDirPath = '/data/adb/service.d';
2022-08-14 20:40:34 +02:00
Future<bool> hasRootPermissions() async {
bool? isRooted = await Root.isRooted();
return isRooted != null && isRooted;
}
2022-08-25 01:51:47 +02:00
Future<bool> isAppInstalled(String packageName) async {
if (packageName.isNotEmpty) {
String? res = await Root.exec(
cmd: 'ls "$_managerDirPath/$packageName"',
);
if (res != null && res.isNotEmpty) {
res = await Root.exec(
cmd: 'ls "$_serviceDDirPath/$packageName.sh"',
);
return res != null && res.isNotEmpty;
}
}
return false;
}
Future<List<String>> getInstalledApps() async {
2022-08-14 20:40:34 +02:00
try {
String? res = await Root.exec(
2022-08-25 01:51:47 +02:00
cmd: 'ls "$_managerDirPath"',
);
2022-08-25 01:51:47 +02:00
if (res != null) {
List<String> apps = res.split('\n');
List<String> toRemove = [];
2022-08-25 01:51:47 +02:00
for (String packageName in apps) {
bool isInstalled = await isAppInstalled(packageName);
if (!isInstalled) {
toRemove.add(packageName);
2022-08-25 01:51:47 +02:00
}
}
apps.removeWhere((a) => toRemove.contains(a));
return apps;
2022-08-25 01:51:47 +02:00
}
2022-08-14 20:40:34 +02:00
} on Exception {
2022-08-25 01:51:47 +02:00
return List.empty();
2022-08-14 20:40:34 +02:00
}
2022-08-25 01:51:47 +02:00
return List.empty();
2022-08-14 20:40:34 +02:00
}
Future<void> deleteApp(String packageName, String originalFilePath) async {
await Root.exec(
cmd: 'am force-stop "$packageName"',
);
await Root.exec(
cmd: 'su -mm -c "umount -l $originalFilePath"',
);
await Root.exec(
2022-08-18 16:33:33 +02:00
cmd: 'rm -rf "$_managerDirPath/$packageName"',
);
await Root.exec(
2022-08-18 16:33:33 +02:00
cmd: 'rm -rf "$_serviceDDirPath/$packageName.sh"',
);
await Root.exec(
2022-08-18 16:33:33 +02:00
cmd: 'rm -rf "$_postFsDataDirPath/$packageName.sh"',
);
}
2022-08-14 20:40:34 +02:00
Future<bool> installApp(
String packageName,
String originalFilePath,
String patchedFilePath,
) async {
try {
2022-08-14 22:32:03 +02:00
await Root.exec(
2022-08-18 16:33:33 +02:00
cmd: 'mkdir -p "$_managerDirPath/$packageName"',
2022-08-14 20:40:34 +02:00
);
installServiceDScript(packageName);
installPostFsDataScript(packageName);
installApk(packageName, patchedFilePath);
mountApk(packageName, originalFilePath, patchedFilePath);
2022-08-14 20:40:34 +02:00
return true;
} on Exception {
return false;
}
}
Future<void> installServiceDScript(String packageName) async {
2022-08-14 20:40:34 +02:00
String content = '#!/system/bin/sh\n'
'while [ "\$(getprop sys.boot_completed | tr -d \'"\'"\'\\\\r\'"\'"\')" != "1" ]; do sleep 1; done\n'
2022-08-18 16:33:33 +02:00
'base_path=$_managerDirPath/$packageName/base.apk\n'
'stock_path=\$(pm path $packageName | grep base | sed \'"\'"\'s/package://g\'"\'"\')\n'
'[ ! -z \$stock_path ] && mount -o bind \$base_path \$stock_path';
2022-08-18 16:33:33 +02:00
String scriptFilePath = '$_serviceDDirPath/$packageName.sh';
2022-08-14 22:32:03 +02:00
await Root.exec(
cmd: 'echo \'$content\' > "$scriptFilePath"',
);
await Root.exec(
cmd: 'chmod 744 "$scriptFilePath"',
);
}
Future<void> installPostFsDataScript(String packageName) async {
String content = '#!/system/bin/sh\n'
'stock_path=\$(pm path $packageName | grep base | sed \'"\'"\'s/package://g\'"\'"\')\n'
'[ ! -z \$stock_path ] && umount -l \$stock_path';
2022-08-18 16:33:33 +02:00
String scriptFilePath = '$_postFsDataDirPath/$packageName.sh';
await Root.exec(
cmd: 'echo \'$content\' > "$scriptFilePath"',
);
await Root.exec(
cmd: 'chmod 744 "$scriptFilePath"',
2022-08-14 22:32:03 +02:00
);
2022-08-14 20:40:34 +02:00
}
Future<void> installApk(String packageName, String patchedFilePath) async {
2022-08-18 16:33:33 +02:00
String newPatchedFilePath = '$_managerDirPath/$packageName/base.apk';
await Root.exec(
cmd: 'cp "$patchedFilePath" "$newPatchedFilePath"',
);
await Root.exec(
cmd: 'chmod 644 "$newPatchedFilePath"',
);
await Root.exec(
cmd: 'chown system:system "$newPatchedFilePath"',
);
await Root.exec(
cmd: 'chcon u:object_r:apk_data_file:s0 "$newPatchedFilePath"',
);
}
Future<void> mountApk(
2022-08-14 20:40:34 +02:00
String packageName,
String originalFilePath,
String patchedFilePath,
) async {
2022-08-18 16:33:33 +02:00
String newPatchedFilePath = '$_managerDirPath/$packageName/base.apk';
await Root.exec(
cmd: 'am force-stop "$packageName"',
);
await Root.exec(
cmd: 'su -mm -c "umount -l $originalFilePath"',
);
2022-08-14 22:32:03 +02:00
await Root.exec(
cmd: 'su -mm -c "mount -o bind $newPatchedFilePath $originalFilePath"',
2022-08-14 22:32:03 +02:00
);
2022-08-14 20:40:34 +02:00
}
}