have some problems with static values used as flags.
for example I need to hook 2 methods in different FRAMEWORK classes during initZygote. (no problem with system apps during handleLoadPackage)
I hook method in first class, set static value and waiting when another method of another class will be triggered.
once another method is invoked, flag always has it's initial state.
it looks like each hook method processed in different class instances.
i tried volatile type, tried to synchronize - nothing help.
unreliable remedy:
1. register broadcast receiver inside hook method.
2. send action to own service
3. send broadcast from own service.
4. catch broadcast with receiver.
BUT it is not battery cost efficient solution in my case. And mostly I receive broadcast message when hooking method already processed and returned value. Otherwise I need to wait when service will process request and send broadcast. But it is not usable.
is there any solution?
Code:
public class XMain implements IXposedHookInitPackageResources, IXposedHookZygoteInit, IXposedHookLoadPackage
{
private static boolean isNeedToRun = false;
public void initZygote(StartupParam startupParam) throws Throwable
{
findAndHookMethod("com.class1", null, "method1", int.class, new XC_MethodHook()
{
@Override
protected void beforeHookedMethod(final MethodHookParam param) throws Throwable
{
isNeedToRun = true;
}
});
findAndHookMethod("com.class2", null, "method2", int.class, new XC_MethodHook()
{
@Override
protected void beforeHookedMethod(final MethodHookParam param) throws Throwable
{
if (isNeedToRun) param.setResult(null); // always FALSE even if previous hook set as TRUE
}
});
}
}
Why do you think that using a broadcast receiver is not battery efficient?
GermainZ said:
Why do you think that using a broadcast receiver is not battery efficient?
Click to expand...
Click to collapse
I do not want to invoke service and send broadcast very often (several thousands times during normal battery one cycle charge)
I just want use easiest way by storing flag inside class and worried that users will find the module in the list of gluttonous applications.
Falseclock said:
Code:
if (isNeedToRun) param.setResult(null); // always FALSE even if previous hook set as TRUE
Click to expand...
Click to collapse
You're probably not considering the fact that different processes will each have its own "isNeededToRun" variable.
Whenever new processes (system_process, apps, etc.) are forked from zygote, each of them will have its own independent state which includes this static variable. From then on they will be completely separate things even if it's a variable with the same name, don't get confused by that.
Try adding a Log.i(...) call to write something in both methods, and then check the logcat for the pid in which the messages are logged. I bet you'll see that different pids are writing and reading, and you can't expect them to be doing it in the same global variable.
Tungstwenty said:
You're probably not considering the fact that different processes will each have its own "isNeededToRun" variable.
Whenever new processes (system_process, apps, etc.) are forked from zygote, each of them will have its own independent state which includes this static variable. From then on they will be completely separate things even if it's a variable with the same name, don't get confused by that.
Try adding a Log.i(...) call to write something in both methods, and then check the logcat for the pid in which the messages are logged. I bet you'll see that different pids are writing and reading, and you can't expect them to be doing it in the same global variable.
Click to expand...
Click to collapse
Yes, I realized this. But under handleLoadPackage everything work perfect.
Any suggestion to solve situation?
Falseclock said:
Yes, I realized this. But under handleLoadPackage everything work perfect.
Any suggestion to solve situation?
Click to expand...
Click to collapse
handleLoadPackage is executed after the fork, in the new process. Not sure what exactly you hooked when you tried that way, but probably both callbacks were executed in the same app/process.
You have the typical problem that requires some kind of inter-process communication (IPC). Most common examples for IPC in Android are broadcasts and services. Files might also be an option (especially with observers), but probably not when you need to change the value very frequently.
I'm searching a way to invoke super methods within a before hook.
This is needed for Android's activity lifecycle, like onCreate onResume onPause onDestroy etc
Is it seems not possible at the moment, so i think Xposed has to be extended :-/
It's not possible directly via reflection. You can call it as a static method (assuming it is static), or get an instance of the super class and call the method you want.
I'm using most time the reflection methods, not the wrapper of xposed. So finding the methods in the super class is not the problem, but executing with the context of the hooked class does not work, because not the method of the super class is invoked :crying:
Hello,
I'm building an xposed module and i want to hook a method only if certain process (app) called this method. I can get the process pid and uid using Binder, but I can't find a way to get the package name.
How can I get it?
Thanks, Gidi
You can get it the usual way if you have a context. It might be a better idea to do something like this, depending on what you're trying to do:
Java:
public class XposedMod implements IXposedHookLoadPackage {
private int mHookedAppUid; // You can use this field to directly compare the UID.
[user=439709]@override[/user]
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("package"))
return;
mHookedAppUid = lpparam.appInfo.uid;
}
}
GermainZ said:
You can get it the usual way if you have a context. It might be a better idea to do something like this, depending on what you're trying to do:
Java:
public class XposedMod implements IXposedHookLoadPackage {
private int mHookedAppUid; // You can use this field to directly compare the UID.
[user=439709]@override[/user]
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("package"))
return;
mHookedAppUid = lpparam.appInfo.uid;
}
}
Click to expand...
Click to collapse
Thanks, but i still can't find a good way to get it.
for my example, i'm trying to hook the method sendTextMessage from android.telephony.SmsManager
if i do it using handleLoadPackage, it doesn't seems to work, but if i do it using initZygote it does work (i'm able to hook the method)
and since i don't have a Context, i can't do it in the usual way, and it seems i'm doing something wrong, since i can't use the other way too...
any idea?
You should use handleLoadPackage for the app you want (e.g. AOSP SMS app), it's independent from the initZygote hook and only there to store the UID.
Otherwise, you can try AndroidAppHelper.currentApplication() to get a context. This may not always return a context, though.
Currently I'm reading off a SQLITE database and storing the results in memory for further processing, lets call this Object X.
I put Object X is lets say in Class A, so I basically have a static reference to it.
Is it possible in any way to maintain the same copy of Object X in all of the process that I hook to?
Currently, Object X will become null as a package loads via my class that implements IXposedHookLoadPackage (it appears that it has its own version of Object X for every package loaded).
jasonpohzh said:
Is it possible in any way to maintain the same copy of Object X in all of the process that I hook to?
Click to expand...
Click to collapse
In short: No. Every process has its own memory. Whatever you set up in initZygote() will be cloned for the application processes, but any changes you do in one process won't be reflected in the other processes (including the main/Zygote process). You have to use some kind of IPC (inter-process communication) for that, like broadcasts or simply a file.
com.android.server.*
I know that these classes have to be hooked in handleLoadPackage for lpparam.packageName == "android", but sometimes there are several processes ("system:ui" for example) that contain this package and hooks fail even from handleLoadPackage.
Now I'm using this code, is it correct?
Code:
if (lpparam.packageName.equals("android") && lpparam.processName.equals("android")) { ... }
Resource hooks
They are just not working. Well, most of them. Using fwd or DrawableLoader doesn't matter. No errors shown in log. It's not just a problem with some packages. Status bar icons, action bar icons, etc, etc - I can't replace 90% of them, exact same hooks were working on Kit Kat.
For example, png drawable is used only in manifest and in actionbar ( actionbar.setIcon(iconResId) ). With a hook this icon is replaced in launcher, but not in actionbar.
Code:
Starting Xposed binary version 60, compiled for SDK 21
Phone: HTC One (HTC), Android version 5.0.2 (SDK 21)
ROM: LRX22G release-keys
Build fingerprint: htc/htc_europe/m7:5.0.2/LRX22G/482424.2:user/release-keys
Platform: armeabi-v7a, 32-bit binary, system server: yes
SELinux enabled: yes, enforcing: no
Mikanoshi said:
Resource hooks
They are just not working. Well, most of them. Using fwd or DrawableLoader doesn't matter. No errors shown in log. It's not just a problem with some packages. Status bar icons, action bar icons, etc, etc - I can't replace 90% of them, exact same hooks were working on Kit Kat.
For example, png drawable is used only in manifest and in actionbar ( actionbar.setIcon(iconResId) ). With a hook this icon is replaced in launcher, but not in actionbar.
Click to expand...
Click to collapse
Noticed that as well. Some resources can be replaced, others it's like they're just silently ignored. I'm guessing maybe the ART optimizations are the culprit?
There's a thread about it here. I'm sure @rovo89 will chime in when he's had time to take a look. As a workaround, you could always find the method that's setting the original drawable and replace it there; that seems to work for me in most cases.
Mikanoshi said:
com.android.server.*
I know that these classes have to be hooked in handleLoadPackage for lpparam.packageName == "android", but sometimes there are several processes ("system:ui" for example) that contain this package and hooks fail even from handleLoadPackage.
Now I'm using this code, is it correct?
Code:
if (lpparam.packageName.equals("android") && lpparam.processName.equals("android")) { ... }
Click to expand...
Click to collapse
So you're saying that there are situations with lpparam.packageName == "android" and lpparam.processName <> "android"? That would explain a couple of other issues. If you could find out a good way to reproduce this, it could be quite helpful.
Depending on the situation, I will have to see how to handle it. Checking for package name "android" is a pretty common pattern to ensure you're in the system server (which I even recommend myself!), so ideally it should stay correct even without the additional checks you suggested.
rovo89 said:
So you're saying that there are situations with lpparam.packageName == "android" and lpparam.processName <> "android"? That would explain a couple of other issues. If you could find out a good way to reproduce this, it could be quite helpful.
Depending on the situation, I will have to see how to handle it. Checking for package name "android" is a pretty common pattern to ensure you're in the system server (which I even recommend myself!), so ideally it should stay correct even without the additional checks you suggested.
Click to expand...
Click to collapse
I've seen only "system:ui" process name, it tries to search for classes in XposedBridge.jar only and of course fails.
Occurrences are very inconsistent, I install modules from Eclipse and then soft reboot like 50 times a day, and this bug happens 2 or 3 times. Not a big problem though, it just clutters Xposed log
I also have a lot of problems with installing apk via adb, it either throws an excpetion and doesn't install
Code:
ActivityManager: java.lang.UnsatisfiedLinkError: No implementation found for java.lang.String android.os.SystemProperties.native_get(java.lang.String) (tried Java_android_os_SystemProperties_native_1get and Java_android_os_SystemProperties_native_1get__Ljava_lang_String_2)
ActivityManager: at android.os.SystemProperties.native_get(Native Method)
ActivityManager: at android.os.SystemProperties.get(SystemProperties.java:52)
ActivityManager: at com.htc.customization.HtcCustomizationManager.<init>(HtcCustomizationManager.java:65)
ActivityManager: at com.htc.customization.HtcCustomizationManager.<clinit>(HtcCustomizationManager.java:60)
ActivityManager: at android.os.Environment$UserEnvironment.getCustomizationReader(Environment.java:523)
ActivityManager: at android.os.Environment$UserEnvironment.isDynamicSwitchSupported(Environment.java:534)
ActivityManager: at android.os.Environment$UserEnvironment.<init>(Environment.java:222)
ActivityManager: at android.os.Environment.initForCurrentUser(Environment.java:142)
ActivityManager: at android.os.Environment.<clinit>(Environment.java:136)
ActivityManager: at android.os.Environment.getLegacyExternalStorageDirectory(Environment.java:726)
ActivityManager: at android.os.Debug.<clinit>(Debug.java:96)
ActivityManager: at android.ddm.DdmHandleHello.handleHELO(DdmHandleHello.java:164)
ActivityManager: at android.ddm.DdmHandleHello.handleChunk(DdmHandleHello.java:91)
ActivityManager: at org.apache.harmony.dalvik.ddmc.DdmServer.dispatch(DdmServer.java:171)
ActivityManager: java.lang.UnsatisfiedLinkError: android.os.Debug
ActivityManager: at android.ddm.DdmHandleHello.handleFEAT(DdmHandleHello.java:176)
ActivityManager: at android.ddm.DdmHandleHello.handleChunk(DdmHandleHello.java:93)
ActivityManager: at org.apache.harmony.dalvik.ddmc.DdmServer.dispatch(DdmServer.java:171)
ActivityManager: java.lang.UnsatisfiedLinkError: android.os.Debug
ActivityManager: at android.ddm.DdmHandleProfiling.handleMPRQ(DdmHandleProfiling.java:215)
ActivityManager: at android.ddm.DdmHandleProfiling.handleChunk(DdmHandleProfiling.java:106)
ActivityManager: at org.apache.harmony.dalvik.ddmc.DdmServer.dispatch(DdmServer.java:171)
or installs but fails to launch until (soft) reboot:
Code:
I/ActivityManager(15637): Process name.mikanoshi.icecontrol (pid 27200) has died
I/ActivityManager(15637): Start proc name.mikanoshi.icecontrol for activity name.mikanoshi.icecontrol/.Settings: pid=27233 uid=10343 gids={50343, 9997} abi=armeabi-v7a
I/art(27233): Late-enabling -Xcheck:jni
W/art(27233): Failed to find OatDexFile for DexFile /data/app/name.mikanoshi.icecontrol-2/base.apk ( canonical path /data/app/name.mikanoshi.icecontrol-2/base.apk) with checksum 0x7991961b in OatFile /data/dalvik-cache/arm/[email protected]@[email protected]@classes.dex
D/Process(15637): killProcessQuiet, pid=27233
No idea if Lollipop or Xposed problem
rovo89 said:
So you're saying that there are situations with lpparam.packageName == "android" and lpparam.processName <> "android"? That would explain a couple of other issues. If you could find out a good way to reproduce this, it could be quite helpful.
Depending on the situation, I will have to see how to handle it. Checking for package name "android" is a pretty common pattern to ensure you're in the system server (which I even recommend myself!), so ideally it should stay correct even without the additional checks you suggested.
Click to expand...
Click to collapse
Yes, I can confirm this seems to be the case. Haven't got a chance to debug which process comes with packageName == "android" apart from "android" process itself, but when that happens, classLoader cannot find classes that are typically available within "android" package, which is logical. The other process that has packageName "android" is something else with no access to those classes.
Oh, and rarely soft reboot after module activation ends like this
Code:
E/Xposed(10834): Error -32 while adding app service user.xposed.app
E/Xposed(10822): Zygote service is not running, Xposed cannot work without it
I would like to concentrate on the bigger issues first. Yours can probably be solved by another reboot.
So after some research, grepping the AOSP code and so on, it seems that the "system:ui" process is only used by the PackageManagerService. Maybe more will follow in the future. For some reason, the process seems to be called "android:ui" though once it has been started. It's running with UID 1000, but in the system_app SELinux context.
I would like to understand some more things about this before making a decision. It seems that there can now indeed be processes with package name "android" that aren't the system_server. Without breaking existing modules, I think I could only block handleLoadPackage() for these. Maybe it would also make sense to add a new handleLoadSystemServer() method. That would avoid the need for checks, especially if only system services are hooked. For backward-compatiblity, handleLoadPackage() could still be called for package "android", but modules would produce error messaages if they don't check the process name. Or there could be a compatiblity break at this point, requiring all modules that hook system services to adopt the new API.
I don't mind checks Almost every module that hooks system classes requires an update for 5.0 anyway.
Huge issues for me now are broken resource hooks and problems with installing apks (sometimes it takes 3-5 tries to install and then soft reboot just to test interface changes).
Most likely, this is the reason why the ChooserActivity runs in the "android:ui" process now:
https://github.com/android/platform...40#diff-30afe08a44bf548c7cc9116a473f8bdfL2798
It used to declare multiprocess=true, which meant that the activity was started in the caller's process. Now it's started in a separate process, where ":ui" is relative to the package name, not the applications's default process name (that would be "system").
There are also other activities with similar attributes defined, even in KitKat. If someone has a bit of time at their hands, they could try to check whether handleLoadPackage() is also called for package == "android" and process != "android" on KitKat ROMs for those other activities. It wouldn't be as noticable as it is on Lollipop because the system services that most modules hook there were available with the boot class path.
Anyway, now we know that there are legitimate usages of the "android" package for other things than the system_server. These usages are very limited though. The activities use the boot classloader, so hooking methods from initZygote() would (still) work for them. What if I set the packageName for these apps to "system" instead? So modules checking for "android" as package name could be sure it's the system_server then. Modules which need to do something for the android:ui process could simply check for "system" as package name. Any complaints?
Good solution... Ship it
But I believe majority of actively developed modules are already fixed for this specific case.
rovo89 said:
Most likely, this is the reason why the ChooserActivity runs in the "android:ui" process now:
https://github.com/android/platform...40#diff-30afe08a44bf548c7cc9116a473f8bdfL2798
It used to declare multiprocess=true, which meant that the activity was started in the caller's process. Now it's started in a separate process, where ":ui" is relative to the package name, not the applications's default process name (that would be "system").
There are also other activities with similar attributes defined, even in KitKat. If someone has a bit of time at their hands, they could try to check whether handleLoadPackage() is also called for package == "android" and process != "android" on KitKat ROMs for those other activities. It wouldn't be as noticable as it is on Lollipop because the system services that most modules hook there were available with the boot class path.
Anyway, now we know that there are legitimate usages of the "android" package for other things than the system_server. These usages are very limited though. The activities use the boot classloader, so hooking methods from initZygote() would (still) work for them. What if I set the packageName for these apps to "system" instead? So modules checking for "android" as package name could be sure it's the system_server then. Modules which need to do something for the android:ui process could simply check for "system" as package name. Any complaints?
Click to expand...
Click to collapse
Great idea, no complaints here.
Whike fixing this, maybe you can try to look why appInfo is null for "android" package.
pyler said:
Whike fixing this, maybe you can try to look why appInfo is null for "android" package.
Click to expand...
Click to collapse
That's very simple to answer: https://github.com/rovo89/XposedBri...de/robv/android/xposed/XposedBridge.java#L245
There's simply no ApplicationInfo object (yet), it's constructed later when the PackageManagerService is running. I could construct a fake object, but there are hardly any fields that could be filled with proper values.
atleast flags field could be filled, or not? just do copy of real object for android, which any normal app can get.
since we talk about this, is this doable or Xposed starts too soon for these values?
rovo89 said:
What if I set the packageName for these apps to "system" instead?
Click to expand...
Click to collapse
Old modules which use "android" are incompatible...
To be compatible i have then to check "system" and "android" - this is not better than check for package& process name
system is for *:ui processes and we mostly care about android only.
pyler said:
system is for *:ui processes and we mostly care about android only.
Click to expand...
Click to collapse
Who is "we" and whats the source of "mostly"
I have to say that i'm using "android" for <21 and so it seems i have to use different package names depending on Xposed version
pyler said:
atleast flags field could be filled, or not? just do copy of real object for android, which any normal app can get.
since we talk about this, is this doable or Xposed starts too soon for these values?
Click to expand...
Click to collapse
"real object for android" => you mean the one that I said doesn't exist at the time the system_server is starting up, as the PackageManagerService is not running yet?
No idea about your other suggestion, I'm currently looking mainly into crashes etc., API extensions have to wait...
defim said:
I have to say that i'm using "android" for <21 and so it seems i have to use different package names depending on Xposed version
Click to expand...
Click to collapse
I was talking about "other things than the system_server", i.e. the process for ChooserActivity etc. This process is hardly used, I'm not even sure if it existed in previous versions. Only for this process, the package name is faked to be "system". The system_server, which is way more widely used, will keep package name "android". So I don't expect a single module to break.
If no update for older modules is needed its great :good:
can i use it on samsung device running cm 12
can i use it on samsung device running cm 12