diff --git a/metadata/de.robv.android.xposed.installer/get_rid_of_AndroidHiddenAPI_jar.patch b/metadata/de.robv.android.xposed.installer/get_rid_of_AndroidHiddenAPI_jar.patch new file mode 100644 index 0000000000..e808206267 --- /dev/null +++ b/metadata/de.robv.android.xposed.installer/get_rid_of_AndroidHiddenAPI_jar.patch @@ -0,0 +1,278 @@ +From b58a6014d8a49bd17af182ea05862d8bb205959b Mon Sep 17 00:00:00 2001 +From: relan +Date: Sun, 15 Oct 2017 21:52:28 +0300 +Subject: [PATCH] Add FileUtil class + +Exact copy of android.os.FileUtils functions (from AOSP 7.1.2), only Slog +is replaced with Log. + +Use the new FileUtil class to delete directories + +Stop using reflection. + +Add FileUtils.setPermissions() methods + +Those functions can set different permissions for owner and everyone else. +For example FileUtils.setPermissions(path, 7, 1) will mean Unix mode 0711: +read, write, execute for owner; only execute for group and others. + +There is no need to set group permissions specifically. When a new app is +being installed, Android creates a new Unix user and group for it. Since +groups aren't shared, they don't actually participate in access rights +checking: when we access our file, "owner" permissions are in effect; when +another app accesses our file, "other" permissions are used. + +Use the new FileUtil.setPermissions() methods + +--- + app/build.gradle | 1 - + .../robv/android/xposed/installer/XposedApp.java | 28 ++++----- + .../installer/installation/FlashDirectly.java | 2 +- + .../android/xposed/installer/util/AssetUtil.java | 13 ++-- + .../android/xposed/installer/util/FileUtil.java | 69 +++++++++++++++++++++ + .../android/xposed/installer/util/ModuleUtil.java | 5 +- + 7 files changed, 90 insertions(+), 28 deletions(-) + delete mode 100644 app/libs/AndroidHiddenAPI.jar + create mode 100644 app/src/main/java/de/robv/android/xposed/installer/util/FileUtil.java + +diff --git a/app/build.gradle b/app/build.gradle +index d3d07e7..fad9889 100644 +--- a/app/build.gradle ++++ b/app/build.gradle +@@ -33,5 +33,4 @@ dependencies { + implementation 'eu.chainfire:libsuperuser:1.0.0.201608240809' + implementation 'com.squareup.picasso:picasso:2.5.2' + implementation 'de.psdev.licensesdialog:licensesdialog:1.8.1' +- compileOnly fileTree(dir: 'libs', include: ['*.jar']) + } +diff --git a/app/src/main/java/de/robv/android/xposed/installer/XposedApp.java b/app/src/main/java/de/robv/android/xposed/installer/XposedApp.java +index abb8211..1fe78c1 100644 +--- a/app/src/main/java/de/robv/android/xposed/installer/XposedApp.java ++++ b/app/src/main/java/de/robv/android/xposed/installer/XposedApp.java +@@ -11,7 +11,6 @@ import android.net.Uri; + import android.os.Build; + import android.os.Bundle; + import android.os.Environment; +-import android.os.FileUtils; + import android.os.Handler; + import android.preference.PreferenceManager; + import android.support.v4.content.FileProvider; +@@ -20,10 +19,10 @@ import android.util.Log; + import java.io.File; + import java.io.FileInputStream; + import java.io.IOException; +-import java.lang.reflect.Method; + + import de.robv.android.xposed.installer.util.AssetUtil; + import de.robv.android.xposed.installer.util.DownloadsUtil; ++import de.robv.android.xposed.installer.util.FileUtil; + import de.robv.android.xposed.installer.util.InstallZipUtil; + import de.robv.android.xposed.installer.util.InstallZipUtil.XposedProp; + import de.robv.android.xposed.installer.util.NotificationUtil; +@@ -124,26 +123,21 @@ public class XposedApp extends Application implements ActivityLifecycleCallbacks + } + + private void createDirectories() { +- FileUtils.setPermissions(BASE_DIR, 00711, -1, -1); +- mkdirAndChmod("conf", 00771); +- mkdirAndChmod("log", 00777); ++ FileUtil.setPermissions(BASE_DIR, 7, 1); ++ mkdirAndChmod("conf", 7, 1); ++ mkdirAndChmod("log", 7, 7); + + if (Build.VERSION.SDK_INT >= 24) { +- try { +- Method deleteDir = FileUtils.class.getDeclaredMethod("deleteContentsAndDir", File.class); +- deleteDir.invoke(null, new File(BASE_DIR_LEGACY, "bin")); +- deleteDir.invoke(null, new File(BASE_DIR_LEGACY, "conf")); +- deleteDir.invoke(null, new File(BASE_DIR_LEGACY, "log")); +- } catch (ReflectiveOperationException e) { +- Log.w(XposedApp.TAG, "Failed to delete obsolete directories", e); +- } ++ FileUtil.deleteContentsAndDir(new File(BASE_DIR_LEGACY, "bin")); ++ FileUtil.deleteContentsAndDir(new File(BASE_DIR_LEGACY, "conf")); ++ FileUtil.deleteContentsAndDir(new File(BASE_DIR_LEGACY, "log")); + } + } + +- private void mkdirAndChmod(String dir, int permissions) { +- dir = BASE_DIR + dir; +- new File(dir).mkdir(); +- FileUtils.setPermissions(dir, permissions, -1, -1); ++ private void mkdirAndChmod(String name, int owner, int other) { ++ File dir = new File(BASE_DIR + name); ++ dir.mkdir(); ++ FileUtil.setPermissions(dir, owner, other); + } + + public void reloadXposedProp() { +diff --git a/app/src/main/java/de/robv/android/xposed/installer/installation/FlashDirectly.java b/app/src/main/java/de/robv/android/xposed/installer/installation/FlashDirectly.java +index e230d3f..fad7f66 100644 +--- a/app/src/main/java/de/robv/android/xposed/installer/installation/FlashDirectly.java ++++ b/app/src/main/java/de/robv/android/xposed/installer/installation/FlashDirectly.java +@@ -46,7 +46,7 @@ public class FlashDirectly extends Flashable { + ZipEntry entry = zip.getEntry("META-INF/com/google/android/update-binary"); + File updateBinaryFile = new File(XposedApp.getInstance().getCacheDir(), "update-binary"); + try { +- AssetUtil.writeStreamToFile(zip.getInputStream(entry), updateBinaryFile, 0700); ++ AssetUtil.writeStreamToFile(zip.getInputStream(entry), updateBinaryFile, 7, 0); + } catch (IOException e) { + Log.e(XposedApp.TAG, "Could not extract update-binary", e); + triggerError(callback, FlashCallback.ERROR_INVALID_ZIP); +diff --git a/app/src/main/java/de/robv/android/xposed/installer/util/AssetUtil.java b/app/src/main/java/de/robv/android/xposed/installer/util/AssetUtil.java +index 63b2bc8..5b71de5 100644 +--- a/app/src/main/java/de/robv/android/xposed/installer/util/AssetUtil.java ++++ b/app/src/main/java/de/robv/android/xposed/installer/util/AssetUtil.java +@@ -2,7 +2,6 @@ package de.robv.android.xposed.installer.util; + + import android.content.res.AssetManager; + import android.os.Build; +-import android.os.FileUtils; + import android.util.Log; + + import java.io.File; +@@ -26,12 +25,13 @@ public class AssetUtil { + } + } + +- public static File writeAssetToFile(AssetManager assets, String assetName, File targetFile, int mode) { ++ public static File writeAssetToFile(AssetManager assets, String assetName, ++ File targetFile, int owner, int other) { + try { + if (assets == null) + assets = XposedApp.getInstance().getAssets(); + InputStream in = assets.open(assetName); +- writeStreamToFile(in, targetFile, mode);; ++ writeStreamToFile(in, targetFile, owner, other); + return targetFile; + } catch (IOException e) { + Log.e(XposedApp.TAG, "could not extract asset", e); +@@ -42,7 +42,8 @@ public class AssetUtil { + } + } + +- public static void writeStreamToFile(InputStream in, File targetFile, int mode) throws IOException { ++ public static void writeStreamToFile(InputStream in, File targetFile, ++ int owner, int other) throws IOException { + FileOutputStream out = new FileOutputStream(targetFile); + + byte[] buffer = new byte[1024]; +@@ -53,7 +54,7 @@ public class AssetUtil { + in.close(); + out.close(); + +- FileUtils.setPermissions(targetFile.getAbsolutePath(), mode, -1, -1); ++ FileUtil.setPermissions(targetFile.getAbsolutePath(), owner, other); + } + + public synchronized static void extractBusybox() { +@@ -61,7 +62,7 @@ public class AssetUtil { + return; + + AssetManager assets = null; +- writeAssetToFile(assets, getBinariesFolder() + "busybox-xposed", BUSYBOX_FILE, 00700); ++ writeAssetToFile(assets, getBinariesFolder() + "busybox-xposed", BUSYBOX_FILE, 7, 0); + } + + public synchronized static void removeBusybox() { +diff --git a/app/src/main/java/de/robv/android/xposed/installer/util/FileUtil.java b/app/src/main/java/de/robv/android/xposed/installer/util/FileUtil.java +new file mode 100644 +index 0000000..aacb87f +--- /dev/null ++++ b/app/src/main/java/de/robv/android/xposed/installer/util/FileUtil.java +@@ -0,0 +1,69 @@ ++/* ++ * Copyright (C) 2006 The Android Open Source Project ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++package de.robv.android.xposed.installer.util; ++ ++import android.util.Log; ++ ++import java.io.File; ++ ++import de.robv.android.xposed.installer.XposedApp; ++ ++public class FileUtil { ++ public static boolean setPermissions(String path, int owner, int other) { ++ return setPermissions(new File(path), owner, other); ++ } ++ ++ public static boolean setPermissions(File path, int owner, int other) { ++ if (!setPermissions(path, other, false) || !setPermissions(path, owner, true)) { ++ Log.w(XposedApp.TAG, "Failed to set permissions " + ++ owner + "/" + other + " for " + path.getPath()); ++ return false; ++ } ++ return true; ++ } ++ ++ private static boolean setPermissions(File path, int perm, boolean ownerOnly) { ++ return path.setReadable((perm & 4) != 0, ownerOnly) ++ && path.setWritable((perm & 2) != 0, ownerOnly) ++ && path.setExecutable((perm & 1) != 0, ownerOnly); ++ } ++ ++ public static boolean deleteContentsAndDir(File dir) { ++ if (deleteContents(dir)) { ++ return dir.delete(); ++ } else { ++ return false; ++ } ++ } ++ ++ public static boolean deleteContents(File dir) { ++ File[] files = dir.listFiles(); ++ boolean success = true; ++ if (files != null) { ++ for (File file : files) { ++ if (file.isDirectory()) { ++ success &= deleteContents(file); ++ } ++ if (!file.delete()) { ++ Log.w(XposedApp.TAG, "Failed to delete " + file); ++ success = false; ++ } ++ } ++ } ++ return success; ++ } ++} +diff --git a/app/src/main/java/de/robv/android/xposed/installer/util/ModuleUtil.java b/app/src/main/java/de/robv/android/xposed/installer/util/ModuleUtil.java +index 9aa8e1d..e38788b 100644 +--- a/app/src/main/java/de/robv/android/xposed/installer/util/ModuleUtil.java ++++ b/app/src/main/java/de/robv/android/xposed/installer/util/ModuleUtil.java +@@ -9,7 +9,6 @@ import android.content.pm.PackageManager; + import android.content.pm.PackageManager.NameNotFoundException; + import android.content.pm.ResolveInfo; + import android.graphics.drawable.Drawable; +-import android.os.FileUtils; + import android.util.Log; + import android.widget.Toast; + +@@ -223,8 +222,8 @@ public final class ModuleUtil { + modulesList.close(); + enabledModulesList.close(); + +- FileUtils.setPermissions(MODULES_LIST_FILE, 00664, -1, -1); +- FileUtils.setPermissions(XposedApp.ENABLED_MODULES_LIST_FILE, 00664, -1, -1); ++ FileUtil.setPermissions(MODULES_LIST_FILE, 6, 4); ++ FileUtil.setPermissions(XposedApp.ENABLED_MODULES_LIST_FILE, 6, 4); + + if (showToast) + showToast(R.string.xposed_module_list_updated); +-- +2.14.1 +