feat: root installation (wip)

This commit is contained in:
Alberto Ponces
2022-08-14 19:40:34 +01:00
parent 6061d900ed
commit 9ce0f81a89
16 changed files with 231 additions and 69 deletions

View File

@@ -7,8 +7,8 @@ import 'package:revanced_manager/services/github_api.dart';
@lazySingleton
class ManagerAPI {
Dio dio = Dio();
GithubAPI githubAPI = GithubAPI();
final Dio dio = Dio();
final GithubAPI githubAPI = GithubAPI();
Future<String?> getPath() async {
final path = await p.getApplicationSupportDirectory();

View File

@@ -6,9 +6,10 @@ import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:injectable/injectable.dart';
import 'package:path_provider/path_provider.dart';
import 'package:revanced_manager/app/app.locator.dart';
import 'package:revanced_manager/models/application_info.dart';
import 'package:revanced_manager/models/patch.dart';
import 'package:revanced_manager/models/patched_application.dart';
import 'package:revanced_manager/services/github_api.dart';
import 'package:revanced_manager/services/root_api.dart';
import 'package:revanced_manager/ui/views/installer/installer_viewmodel.dart';
import 'package:revanced_manager/utils/string.dart';
import 'package:share_extend/share_extend.dart';
@@ -17,9 +18,10 @@ import 'package:share_extend/share_extend.dart';
class PatcherAPI {
static const platform = MethodChannel('app.revanced.manager/patcher');
final GithubAPI githubAPI = GithubAPI();
final RootAPI rootAPI = RootAPI();
final List<ApplicationWithIcon> _filteredPackages = [];
final Map<String, List<Patch>> _filteredPatches = <String, List<Patch>>{};
bool isRoot = false;
Directory? _tmpDir;
Directory? _workDir;
Directory? _cacheDir;
File? _patchBundleFile;
@@ -89,7 +91,9 @@ class PatcherAPI {
return _filteredPackages;
}
Future<List<Patch>?> getFilteredPatches(ApplicationInfo? selectedApp) async {
Future<List<Patch>?> getFilteredPatches(
PatchedApplication? selectedApp,
) async {
if (_patchBundleFile != null && selectedApp != null) {
if (_filteredPatches[selectedApp.packageName] == null ||
_filteredPatches[selectedApp.packageName]!.isEmpty) {
@@ -146,8 +150,8 @@ class PatcherAPI {
try {
_integrations = await downloadIntegrations();
if (_integrations != null) {
Directory tmpDir = await getTemporaryDirectory();
_workDir = tmpDir.createTempSync('tmp-');
_tmpDir = await getTemporaryDirectory();
_workDir = _tmpDir!.createTempSync('tmp-');
_inputFile = File('${_workDir!.path}/base.apk');
_patchedFile = File('${_workDir!.path}/patched.apk');
_outFile = File('${_workDir!.path}/out.apk');
@@ -256,15 +260,19 @@ class PatcherAPI {
return false;
}
Future<bool> installPatchedFile() async {
Future<bool> installPatchedFile(PatchedApplication patchedApp) async {
if (_outFile != null) {
try {
if (isRoot) {
// TBD
if (patchedApp.isRooted && !patchedApp.isFromStorage) {
return rootAPI.installApp(
patchedApp.packageName,
patchedApp.apkFilePath,
_outFile!.path,
);
} else {
await AppInstaller.installApk(_outFile!.path);
return true;
}
return true;
} on Exception {
return false;
}
@@ -280,11 +288,11 @@ class PatcherAPI {
bool sharePatchedFile(String appName, String version) {
if (_outFile != null) {
String path = _outFile!.parent.path;
String path = _tmpDir!.path;
String prefix = appName.toLowerCase().replaceAll(' ', '-');
String sharePath = '$path/$prefix-revanced_v$version.apk';
File share = _outFile!.copySync(sharePath);
ShareExtend.share(share.path, "file");
ShareExtend.share(share.path, 'file');
return true;
} else {
return false;

View File

@@ -0,0 +1,85 @@
import 'dart:io';
import 'package:injectable/injectable.dart';
import 'package:root/root.dart';
@lazySingleton
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";
bool deleteApp(String packageName) {
try {
File('$managerDirPath/$packageName.apk').deleteSync();
File('$serviceDDirPath/$packageName.sh').deleteSync();
File('$postFsDataDirPath/$packageName.sh').deleteSync();
return true;
} on Exception {
return false;
}
}
Future<bool> installApp(
String packageName,
String originalFilePath,
String patchedFilePath,
) async {
try {
Directory managerDir = Directory(managerDirPath);
managerDir.createSync();
String newPatchedFilePath = '$managerDirPath/$packageName.apk';
installServiceDScript(
packageName,
originalFilePath,
newPatchedFilePath,
);
installPostFsDataScript(
packageName,
originalFilePath,
newPatchedFilePath,
);
File(patchedFilePath).renameSync(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',
);
return true;
} on Exception {
return false;
}
}
Future<void> installServiceDScript(
String packageName,
String originalFilePath,
String patchedFilePath,
) async {
String content = '#!/system/bin/sh\n'
'while [ "\$(getprop sys.boot_completed | tr -d \'\r\')" != "1" ]; do sleep 1; done\n'
'sleep 1\n'
'chcon u:object_r:apk_data_file:s0 $patchedFilePath\n'
'mount -o bind $patchedFilePath $originalFilePath';
File scriptFile = File('$serviceDDirPath/$packageName.sh');
await scriptFile.writeAsString(content);
await Root.exec(cmd: 'chmod 744 ${scriptFile.path}');
}
Future<void> installPostFsDataScript(
String packageName,
String originalFilePath,
String patchedFilePath,
) async {
String content = '#!/system/bin/sh\n'
'while read line; do echo \$line | grep $originalFilePath | '
'awk \'{print \$2}\' | xargs umount -l; done< /proc/mounts';
File scriptFile = File('$postFsDataDirPath/$packageName.sh');
await scriptFile.writeAsString(content);
await Root.exec(cmd: 'chmod 744 ${scriptFile.path}');
}
}