diff --git a/hiddenapi/stubs/src/main/java/com/android/internal/util/XmlUtils.java b/hiddenapi/stubs/src/main/java/com/android/internal/util/XmlUtils.java deleted file mode 100644 index 3e35527e6..000000000 --- a/hiddenapi/stubs/src/main/java/com/android/internal/util/XmlUtils.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.android.internal.util; - -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; - -public class XmlUtils { - @SuppressWarnings("rawtypes") - public static final HashMap readMapXml(InputStream in) throws XmlPullParserException, IOException { - throw new UnsupportedOperationException("STUB"); - } -} diff --git a/legacy/src/main/java/de/robv/android/xposed/XSharedPreferences.java b/legacy/src/main/java/de/robv/android/xposed/XSharedPreferences.java index 47cd192ee..e3976013c 100644 --- a/legacy/src/main/java/de/robv/android/xposed/XSharedPreferences.java +++ b/legacy/src/main/java/de/robv/android/xposed/XSharedPreferences.java @@ -6,8 +6,6 @@ import android.os.Environment; import android.preference.PreferenceManager; -import com.android.internal.util.XmlUtils; - import org.lsposed.lspd.util.Utils.Log; import org.matrix.vector.impl.core.VectorServiceClient; import org.matrix.vector.impl.utils.VectorMetaDataReader; @@ -18,6 +16,8 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.nio.file.AccessDeniedException; import java.nio.file.ClosedWatchServiceException; import java.nio.file.Path; @@ -43,6 +43,7 @@ public final class XSharedPreferences implements SharedPreferences { private static final String TAG = "XSharedPreferences"; private static final HashMap sWatcherKeyInstances = new HashMap<>(); private static final Object sContent = new Object(); + private static final Method sReadMapXmlMethod; private static Thread sWatcherDaemon = null; private static WatchService sWatcher; @@ -55,6 +56,19 @@ public final class XSharedPreferences implements SharedPreferences { private long mFileSize; private WatchKey mWatchKey; + static { + Method method = null; + try { + // Find the class and method once during class initialization + Class xmlUtils = Class.forName("com.android.internal.util.XmlUtils"); + method = xmlUtils.getDeclaredMethod("readMapXml", InputStream.class); + method.setAccessible(true); + } catch (Exception e) { + Log.e(TAG, "Failed to find com.android.internal.util.XmlUtils.readMapXml", e); + } + sReadMapXmlMethod = method; + } + private static void initWatcherDaemon() { sWatcherDaemon = new Thread() { @Override @@ -304,6 +318,22 @@ public void run() { }.start(); } + private Map performReadMapXml(InputStream str) throws XmlPullParserException, IOException { + try { + if (sReadMapXmlMethod == null) throw new IOException("Internal API not found"); + return (Map) sReadMapXmlMethod.invoke(null, str); + } catch (InvocationTargetException e) { + // Unwrap and throw the real error + Throwable cause = e.getCause(); + if (cause instanceof XmlPullParserException) throw (XmlPullParserException) cause; + if (cause instanceof IOException) throw (IOException) cause; + if (cause instanceof RuntimeException) throw (RuntimeException) cause; + throw new RuntimeException(cause); + } catch (IllegalAccessException e) { + throw new IOException("Access denied to internal API", e); + } + } + @SuppressWarnings({"rawtypes", "unchecked"}) private void loadFromDiskLocked() { if (mLoaded) { @@ -315,7 +345,7 @@ private void loadFromDiskLocked() { try { result = SELinuxHelper.getAppDataFileService().getFileInputStream(mFilename, mFileSize, mLastModified); if (result.stream != null) { - map = XmlUtils.readMapXml(result.stream); + map = performReadMapXml(result.stream); result.stream.close(); } else { // The file is unchanged, keep the current values