Skip to content

Commit

Permalink
More resource hooking for Nougat
Browse files Browse the repository at this point in the history
Make sure to create the ResourcesKey correctly and put the ResourcesImpl
instead of the Resources object into the map. This is required to let
the object receive updates on config changes.
  • Loading branch information
rovo89 committed Oct 8, 2017
1 parent 6ce9e80 commit 0cd9730
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 24 deletions.
80 changes: 57 additions & 23 deletions app/src/main/java/android/app/AndroidAppHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
Expand All @@ -19,6 +20,7 @@
import static de.robv.android.xposed.XposedHelpers.findMethodExactIfExists;
import static de.robv.android.xposed.XposedHelpers.getObjectField;
import static de.robv.android.xposed.XposedHelpers.newInstance;
import static de.robv.android.xposed.XposedHelpers.setFloatField;

/**
* Contains various methods for information about the current app.
Expand All @@ -44,20 +46,23 @@ private AndroidAppHelper() {}
}

@SuppressWarnings({ "unchecked", "rawtypes" })
private static Map<Object, WeakReference<Resources>> getActiveResources(ActivityThread activityThread) {
if (Build.VERSION.SDK_INT <= 18) {
return (Map) getObjectField(activityThread, "mActiveResources");
} else {
private static Map<Object, WeakReference> getResourcesMap(ActivityThread activityThread) {
if (Build.VERSION.SDK_INT >= 24) {
Object resourcesManager = getObjectField(activityThread, "mResourcesManager");
return (Map) getObjectField(resourcesManager, "mResourceImpls");
} else if (Build.VERSION.SDK_INT >= 19) {
Object resourcesManager = getObjectField(activityThread, "mResourcesManager");
return (Map) getObjectField(resourcesManager, "mActiveResources");
} else {
return (Map) getObjectField(activityThread, "mActiveResources");
}
}

/* For SDK 15 & 16 */
private static Object createResourcesKey(String resDir, float scale, boolean isThemeable) {
private static Object createResourcesKey(String resDir, float scale) {
try {
if (HAS_IS_THEMEABLE)
return newInstance(CLASS_RESOURCES_KEY, resDir, scale, isThemeable);
return newInstance(CLASS_RESOURCES_KEY, resDir, scale, false);
else
return newInstance(CLASS_RESOURCES_KEY, resDir, scale);
} catch (Throwable t) {
Expand All @@ -66,13 +71,13 @@ private static Object createResourcesKey(String resDir, float scale, boolean isT
}
}

/* For SDK 17 & 18 & 23+ */
private static Object createResourcesKey(String resDir, int displayId, Configuration overrideConfiguration, float scale, boolean isThemeable) {
/* For SDK 17 & 18 & 23 */
private static Object createResourcesKey(String resDir, int displayId, Configuration overrideConfiguration, float scale) {
try {
if (HAS_THEME_CONFIG_PARAMETER)
return newInstance(CLASS_RESOURCES_KEY, resDir, displayId, overrideConfiguration, scale, isThemeable, null);
return newInstance(CLASS_RESOURCES_KEY, resDir, displayId, overrideConfiguration, scale, false, null);
else if (HAS_IS_THEMEABLE)
return newInstance(CLASS_RESOURCES_KEY, resDir, displayId, overrideConfiguration, scale, isThemeable);
return newInstance(CLASS_RESOURCES_KEY, resDir, displayId, overrideConfiguration, scale, false);
else
return newInstance(CLASS_RESOURCES_KEY, resDir, displayId, overrideConfiguration, scale);
} catch (Throwable t) {
Expand All @@ -82,12 +87,12 @@ else if (HAS_IS_THEMEABLE)
}

/* For SDK 19 - 22 */
private static Object createResourcesKey(String resDir, int displayId, Configuration overrideConfiguration, float scale, IBinder token, boolean isThemeable) {
private static Object createResourcesKey(String resDir, int displayId, Configuration overrideConfiguration, float scale, IBinder token) {
try {
if (HAS_THEME_CONFIG_PARAMETER)
return newInstance(CLASS_RESOURCES_KEY, resDir, displayId, overrideConfiguration, scale, isThemeable, null, token);
return newInstance(CLASS_RESOURCES_KEY, resDir, displayId, overrideConfiguration, scale, false, null, token);
else if (HAS_IS_THEMEABLE)
return newInstance(CLASS_RESOURCES_KEY, resDir, displayId, overrideConfiguration, scale, isThemeable, token);
return newInstance(CLASS_RESOURCES_KEY, resDir, displayId, overrideConfiguration, scale, false, token);
else
return newInstance(CLASS_RESOURCES_KEY, resDir, displayId, overrideConfiguration, scale, token);
} catch (Throwable t) {
Expand All @@ -96,22 +101,51 @@ else if (HAS_IS_THEMEABLE)
}
}

/* For SDK 24+ */
private static Object createResourcesKey(String resDir, String[] splitResDirs, String[] overlayDirs, String[] libDirs, int displayId, Configuration overrideConfiguration, CompatibilityInfo compatInfo) {
try {
return newInstance(CLASS_RESOURCES_KEY, resDir, splitResDirs, overlayDirs, libDirs, displayId, overrideConfiguration, compatInfo);
} catch (Throwable t) {
XposedBridge.log(t);
return null;
}
}

/** @hide */
public static void addActiveResource(String resDir, float scale, boolean isThemeable, Resources resources) {
addActiveResource(resDir, resources);
}

/** @hide */
public static void addActiveResource(String resDir, Resources resources) {
ActivityThread thread = ActivityThread.currentActivityThread();
if (thread == null)
if (thread == null) {
return;
}

Object resourcesKey;
if (Build.VERSION.SDK_INT <= 16)
resourcesKey = createResourcesKey(resDir, scale, isThemeable);
else if (Build.VERSION.SDK_INT <= 18 || Build.VERSION.SDK_INT >= 23)
resourcesKey = createResourcesKey(resDir, Display.DEFAULT_DISPLAY, null, scale, isThemeable);
else
resourcesKey = createResourcesKey(resDir, Display.DEFAULT_DISPLAY, null, scale, null, isThemeable);

if (resourcesKey != null)
getActiveResources(thread).put(resourcesKey, new WeakReference<>(resources));
if (Build.VERSION.SDK_INT >= 24) {
CompatibilityInfo compatInfo = (CompatibilityInfo) newInstance(CompatibilityInfo.class);
setFloatField(compatInfo, "applicationScale", resources.hashCode());
resourcesKey = createResourcesKey(resDir, null, null, null, Display.DEFAULT_DISPLAY, null, compatInfo);
} else if (Build.VERSION.SDK_INT == 23) {
resourcesKey = createResourcesKey(resDir, Display.DEFAULT_DISPLAY, null, resources.hashCode());
} else if (Build.VERSION.SDK_INT >= 19) {
resourcesKey = createResourcesKey(resDir, Display.DEFAULT_DISPLAY, null, resources.hashCode(), null);
} else if (Build.VERSION.SDK_INT >= 17) {
resourcesKey = createResourcesKey(resDir, Display.DEFAULT_DISPLAY, null, resources.hashCode());
} else {
resourcesKey = createResourcesKey(resDir, resources.hashCode());
}

if (resourcesKey != null) {
if (Build.VERSION.SDK_INT >= 24) {
Object resImpl = getObjectField(resources, "mResourcesImpl");
getResourcesMap(thread).put(resourcesKey, new WeakReference<>(resImpl));
} else {
getResourcesMap(thread).put(resourcesKey, new WeakReference<>(resources));
}
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public static XModuleResources createInstance(String path, XResources origRes) {
else
res = new XModuleResources(assets, null, null);

AndroidAppHelper.addActiveResource(path, res.hashCode(), false, res);
AndroidAppHelper.addActiveResource(path, res);
return res;
}

Expand Down

0 comments on commit 0cd9730

Please sign in to comment.