fix: One more fix to root installations management

This commit is contained in:
Alberto Ponces 2022-09-14 09:59:56 +01:00
parent c92b889cd9
commit 6ef716b0e4
4 changed files with 101 additions and 49 deletions

View File

@ -31,18 +31,9 @@ class MainActivity : FlutterActivity() {
installerChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, INSTALLER_CHANNEL) installerChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, INSTALLER_CHANNEL)
mainChannel.setMethodCallHandler { call, result -> mainChannel.setMethodCallHandler { call, result ->
when (call.method) { when (call.method) {
"copyOriginalApk" -> {
val originalFilePath = call.argument<String>("originalFilePath")
val backupFilePath = call.argument<String>("backupFilePath")
if (originalFilePath != null && backupFilePath != null) {
File(originalFilePath).copyTo(File(backupFilePath), true)
result.success(null)
} else {
result.notImplemented()
}
}
"runPatcher" -> { "runPatcher" -> {
val patchBundleFilePath = call.argument<String>("patchBundleFilePath") val patchBundleFilePath = call.argument<String>("patchBundleFilePath")
val originalFilePath = call.argument<String>("originalFilePath")
val inputFilePath = call.argument<String>("inputFilePath") val inputFilePath = call.argument<String>("inputFilePath")
val patchedFilePath = call.argument<String>("patchedFilePath") val patchedFilePath = call.argument<String>("patchedFilePath")
val outFilePath = call.argument<String>("outFilePath") val outFilePath = call.argument<String>("outFilePath")
@ -53,6 +44,7 @@ class MainActivity : FlutterActivity() {
val resourcePatching = call.argument<Boolean>("resourcePatching") val resourcePatching = call.argument<Boolean>("resourcePatching")
val keyStoreFilePath = call.argument<String>("keyStoreFilePath") val keyStoreFilePath = call.argument<String>("keyStoreFilePath")
if (patchBundleFilePath != null && if (patchBundleFilePath != null &&
originalFilePath != null &&
inputFilePath != null && inputFilePath != null &&
patchedFilePath != null && patchedFilePath != null &&
outFilePath != null && outFilePath != null &&
@ -66,6 +58,7 @@ class MainActivity : FlutterActivity() {
runPatcher( runPatcher(
result, result,
patchBundleFilePath, patchBundleFilePath,
originalFilePath,
inputFilePath, inputFilePath,
patchedFilePath, patchedFilePath,
outFilePath, outFilePath,
@ -88,6 +81,7 @@ class MainActivity : FlutterActivity() {
fun runPatcher( fun runPatcher(
result: MethodChannel.Result, result: MethodChannel.Result,
patchBundleFilePath: String, patchBundleFilePath: String,
originalFilePath: String,
inputFilePath: String, inputFilePath: String,
patchedFilePath: String, patchedFilePath: String,
outFilePath: String, outFilePath: String,
@ -98,6 +92,7 @@ class MainActivity : FlutterActivity() {
resourcePatching: Boolean, resourcePatching: Boolean,
keyStoreFilePath: String keyStoreFilePath: String
) { ) {
val originalFile = File(originalFilePath)
val inputFile = File(inputFilePath) val inputFile = File(inputFilePath)
val patchedFile = File(patchedFilePath) val patchedFile = File(patchedFilePath)
val outFile = File(outFilePath) val outFile = File(outFilePath)
@ -119,6 +114,18 @@ class MainActivity : FlutterActivity() {
Thread( Thread(
Runnable { Runnable {
handler.post {
installerChannel.invokeMethod(
"update",
mapOf(
"progress" to 0.1,
"header" to "",
"log" to "Copying original apk"
)
)
}
originalFile.copyTo(inputFile, true)
handler.post { handler.post {
installerChannel.invokeMethod( installerChannel.invokeMethod(
"update", "update",

View File

@ -82,31 +82,23 @@ class PatcherAPI {
.toList(); .toList();
} }
Future<String> copyOriginalApk( Future<String> getOriginalFilePath(
String packageName, String packageName,
String originalFilePath, String originalFilePath,
) async { ) async {
bool hasRootPermissions = await _rootAPI.hasRootPermissions(); bool hasRootPermissions = await _rootAPI.hasRootPermissions();
if (hasRootPermissions) { if (hasRootPermissions) {
String originalRootPath = await _rootAPI.getOriginalFilePath(packageName); originalFilePath = await _rootAPI.getOriginalFilePath(
if (File(originalRootPath).existsSync()) { packageName,
originalFilePath = originalRootPath; originalFilePath,
}
}
String backupFilePath = '${_tmpDir.path}/$packageName.apk';
await patcherChannel.invokeMethod(
'copyOriginalApk',
{
'originalFilePath': originalFilePath,
'backupFilePath': backupFilePath,
},
); );
return backupFilePath; }
return originalFilePath;
} }
Future<void> runPatcher( Future<void> runPatcher(
String packageName, String packageName,
String inputFilePath, String originalFilePath,
List<Patch> selectedPatches, List<Patch> selectedPatches,
) async { ) async {
bool mergeIntegrations = selectedPatches.any( bool mergeIntegrations = selectedPatches.any(
@ -140,6 +132,7 @@ class PatcherAPI {
if (patchBundleFile != null) { if (patchBundleFile != null) {
_tmpDir.createSync(); _tmpDir.createSync();
Directory workDir = _tmpDir.createTempSync('tmp-'); Directory workDir = _tmpDir.createTempSync('tmp-');
File inputFile = File('${workDir.path}/base.apk');
File patchedFile = File('${workDir.path}/patched.apk'); File patchedFile = File('${workDir.path}/patched.apk');
_outFile = File('${workDir.path}/out.apk'); _outFile = File('${workDir.path}/out.apk');
Directory cacheDir = Directory('${workDir.path}/cache'); Directory cacheDir = Directory('${workDir.path}/cache');
@ -148,7 +141,11 @@ class PatcherAPI {
'runPatcher', 'runPatcher',
{ {
'patchBundleFilePath': patchBundleFile.path, 'patchBundleFilePath': patchBundleFile.path,
'inputFilePath': inputFilePath, 'originalFilePath': await getOriginalFilePath(
packageName,
originalFilePath,
),
'inputFilePath': inputFile.path,
'patchedFilePath': patchedFile.path, 'patchedFilePath': patchedFile.path,
'outFilePath': _outFile!.path, 'outFilePath': _outFile!.path,
'integrationsPath': mergeIntegrations ? integrationsFile!.path : '', 'integrationsPath': mergeIntegrations ? integrationsFile!.path : '',

View File

@ -2,6 +2,7 @@ import 'package:root/root.dart';
class RootAPI { class RootAPI {
final String _managerDirPath = '/data/adb/revanced-manager'; final String _managerDirPath = '/data/adb/revanced-manager';
final String _managerTmpDirPath = '/data/local/tmp/revanced-manager';
final String _postFsDataDirPath = '/data/adb/post-fs-data.d'; final String _postFsDataDirPath = '/data/adb/post-fs-data.d';
final String _serviceDDirPath = '/data/adb/service.d'; final String _serviceDDirPath = '/data/adb/service.d';
@ -10,6 +11,29 @@ class RootAPI {
return isRooted != null && isRooted; return isRooted != null && isRooted;
} }
Future<void> setPermissions(
String permissions,
ownerGroup,
seLinux,
String filePath,
) async {
if (permissions.isNotEmpty) {
await Root.exec(
cmd: 'chmod $permissions "$filePath"',
);
}
if (ownerGroup.isNotEmpty) {
await Root.exec(
cmd: 'chown $ownerGroup "$filePath"',
);
}
if (seLinux.isNotEmpty) {
await Root.exec(
cmd: 'chcon $seLinux "$filePath"',
);
}
}
Future<bool> isAppInstalled(String packageName) async { Future<bool> isAppInstalled(String packageName) async {
if (packageName.isNotEmpty) { if (packageName.isNotEmpty) {
String? res = await Root.exec( String? res = await Root.exec(
@ -76,6 +100,7 @@ class RootAPI {
await Root.exec( await Root.exec(
cmd: 'mkdir -p "$_managerDirPath/$packageName"', cmd: 'mkdir -p "$_managerDirPath/$packageName"',
); );
await setPermissions('0755', '', '', "$_managerDirPath/$packageName");
await saveOriginalFilePath(packageName, originalFilePath); await saveOriginalFilePath(packageName, originalFilePath);
await installServiceDScript(packageName); await installServiceDScript(packageName);
await installPostFsDataScript(packageName); await installPostFsDataScript(packageName);
@ -97,9 +122,7 @@ class RootAPI {
await Root.exec( await Root.exec(
cmd: 'echo \'$content\' > "$scriptFilePath"', cmd: 'echo \'$content\' > "$scriptFilePath"',
); );
await Root.exec( await setPermissions('0744', '', '', scriptFilePath);
cmd: 'chmod 744 "$scriptFilePath"',
);
} }
Future<void> installPostFsDataScript(String packageName) async { Future<void> installPostFsDataScript(String packageName) async {
@ -110,9 +133,7 @@ class RootAPI {
await Root.exec( await Root.exec(
cmd: 'echo \'$content\' > "$scriptFilePath"', cmd: 'echo \'$content\' > "$scriptFilePath"',
); );
await Root.exec( await setPermissions('0744', '', '', scriptFilePath);
cmd: 'chmod 744 "$scriptFilePath"',
);
} }
Future<void> installApk(String packageName, String patchedFilePath) async { Future<void> installApk(String packageName, String patchedFilePath) async {
@ -120,14 +141,11 @@ class RootAPI {
await Root.exec( await Root.exec(
cmd: 'cp "$patchedFilePath" "$newPatchedFilePath"', cmd: 'cp "$patchedFilePath" "$newPatchedFilePath"',
); );
await Root.exec( await setPermissions(
cmd: 'chmod 644 "$newPatchedFilePath"', '0644',
); 'system:system',
await Root.exec( 'u:object_r:apk_data_file:s0',
cmd: 'chown system:system "$newPatchedFilePath"', newPatchedFilePath,
);
await Root.exec(
cmd: 'chcon u:object_r:apk_data_file:s0 "$newPatchedFilePath"',
); );
} }
@ -144,17 +162,52 @@ class RootAPI {
); );
} }
Future<String> getOriginalFilePath(String packageName) async { Future<bool> isMounted(String packageName) async {
return '$_managerDirPath/$packageName/original.apk'; String? res = await Root.exec(
cmd: 'cat /proc/mounts | grep $packageName',
);
return res != null && res.isNotEmpty;
}
Future<String> getOriginalFilePath(
String packageName,
String originalFilePath,
) async {
bool isInstalled = await isAppInstalled(packageName);
if (isInstalled && await isMounted(packageName)) {
originalFilePath = '$_managerTmpDirPath/$packageName/original.apk';
await setPermissions(
'0644',
'shell:shell',
'u:object_r:apk_data_file:s0',
originalFilePath,
);
}
return originalFilePath;
} }
Future<void> saveOriginalFilePath( Future<void> saveOriginalFilePath(
String packageName, String packageName,
String originalFilePath, String originalFilePath,
) async { ) async {
String originalRootPath = '$_managerDirPath/$packageName/original.apk'; String originalRootPath = '$_managerTmpDirPath/$packageName/original.apk';
await Root.exec(
cmd: 'mkdir -p "$_managerTmpDirPath/$packageName"',
);
await setPermissions(
'0755',
'shell:shell',
'',
'$_managerTmpDirPath/$packageName',
);
await Root.exec( await Root.exec(
cmd: 'cp "$originalFilePath" "$originalRootPath"', cmd: 'cp "$originalFilePath" "$originalRootPath"',
); );
await setPermissions(
'0644',
'shell:shell',
'u:object_r:apk_data_file:s0',
originalFilePath,
);
} }
} }

View File

@ -105,15 +105,10 @@ class InstallerViewModel extends BaseViewModel {
update(0.0, 'Initializing...', 'Initializing installer'); update(0.0, 'Initializing...', 'Initializing installer');
if (_patches.isNotEmpty) { if (_patches.isNotEmpty) {
try { try {
update(0.1, '', 'Copying original apk');
String inputFilePath = await _patcherAPI.copyOriginalApk(
_app.packageName,
_app.apkFilePath,
);
update(0.1, '', 'Creating working directory'); update(0.1, '', 'Creating working directory');
await _patcherAPI.runPatcher( await _patcherAPI.runPatcher(
_app.packageName, _app.packageName,
inputFilePath, _app.apkFilePath,
_patches, _patches,
); );
} catch (e) { } catch (e) {