最近在研究xposed,有个需求要作到清除其余应用数据,xposed功能足够强大,应该能够实现这个功能,下面是基于android4.4.4研究的思路。java
google只能开放了清楚缓存的API,清除数据的API隐藏了,而调用清理数据的方法在“设置”中的“应用”里,找到设置功能的源码,代码位置 com.android.settings.applications.InstalledAppDetails ,点击事件在这linux
调用了initiateClearUserData,看看这里面怎么实现的android
调用了ActivityManager的clearApplicationUserData,参数是该应用的包名和一个ClearUserDataObserver的实例缓存
IPackageDataObserver是有AIDL生成的,位于android.content.pm包内,咱们能够新建一个相同的包名,把AIDL放在这里。app
(注:有些应用详情里该按钮不是清除数据,是管理空间,清除数据的按钮在应用自定义的界面里,可是最终实现清除数据仍是调用的clearApplicationUserData)socket
clearApplicationUserData是隐藏方法,直接调用了ActivityManagerNative的方法ide
ActivityManagerNative:学习
这里直接使用反射或者Xposed的callmethod调用这两个方法都会报错,缺乏权限ui
android.permission.CLEAR_APP_USER_DATA
这里并无实现具体的方法,真正的实如今ActivityManagerService中,参考http://www.jianshu.com/p/18517a4ef8e1google
ActivityManagerService:
该方法上面部分是获取pid、uid,给IPackageManager的对象赋值和权限检测,下面执行清除数据。最开始的思路是直接hook AppGlobals.getPackageManager()的clearApplicationUserData,可是仍旧报缺乏权限错误。。。继续分析:
AppGlobals:
ActivityThread:
到这里遇到IPackageManager.aidl生成的Stub类,PackageManagerService继承了IPackageManager.Stub
PackageManagerService:
又是权限检测,跳过,进入clearApplicationUserDataLI
int retCode = mInstaller.clearUserData(packageName, userId);
进入Installer方法
该类大概是建立本地socket,执行linux命令行,进行各类应用的安装、移动、卸载、清除数据等
可是hook此方法,仍旧报错,空指针异常,并且hook connect也链接不上
Class installCls = XposedHelpers.findClass("com.android.server.pm.Installer",lpp.classLoader); Object installObj = XposedHelpers.newInstance(installCls); boolean lean = (boolean) XposedHelpers.callMethod(installObj,"ping"); boolean bo = (boolean) XposedHelpers.callMethod(installObj,"connect"); XposedBridge.log("lean:"+lean+"--bo:"+bo);
实例化Installer出的问题.查了资料,Installer在系统启动时由其余类调用,启动完成后用findAndHookMethod没法hook到。因而实现Xposed另外一接口XposedHookZygoteInit
@Override public void initZygote(StartupParam startupParam) throws Throwable { Class installCls = XposedHelpers.findClass("com.android.server.pm.Installer",null); XposedHelpers.findAndHookMethod(installCls, "writeCommand",String.class, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { String string = (String) param.args[0]; XposedBridge.log("string:"+string); if(string.contains("com.google.android.gms")) param.args[0] = "rmuserdata com.google.android.gms 0"; } }); }
以google play service为例,这种状况下能够清除此app的数据。可是这种方法不可控,必须放在initZygote中,并且Installer不能经过反射实例化,只能另想办法。
郁闷两天后,想到既然从ActivityManager、PackageManagerService等类中不能调用是由于权限限制,那就hook检测权限的方法,让个人应用经过权限检测。最开始打算之外部调用的方式(在非Xposed中,例如activity,以反射的方式调用清除数据的方法,Xposed hook权限检测方法)从 ActivityManagerService入手,由于PackageManagerService的构造方法须要传多个参数,包括Installer的对象。ActivityManagerService里检测权限的是checkComponentPermission方法,可是经过反射获取ActivityManagerService对象时又报错,FileNotFoundException,引起异常的位置是mBatteryStatsService = new BatteryStatsService(new File( systemDir, "batterystats.bin").toString());
batterystats.bin文件位于/data/system/下,但即便我得到了root权限依然触发异常,不知道什么缘由。这样只能在handleLoadPackage中调用清除数据,在Xposed外部设置个合适方法触发清理数据,好比得到IMEI、杀掉某个进程等,经过hook这些方法,而后调用清除数据的方法:
XposedHelpers.findAndHookMethod("android.app.ActivityManager", lpp.classLoader, "killBackgroundProcesses",String.class, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { String process = (String) param.args[0]; XposedBridge.log("process:"+process); if("com.google.android.gsf".equals(process)){ ActivityManager manager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); XposedHelpers.callMethod(manager,"clearApplicationUserData",packageName,clearDataUserData); } } });
这是以杀死com.google.android.gsf为例。
权限检测这里有两部分,就是ActivityManagerService 的checkComponentPermission了:
XposedHelpers.findAndHookMethod("com.android.server.am.ActivityManagerService", lpp.classLoader, "checkComponentPermission", String.class, int.class, int.class, int.class, boolean.class, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { if(Manifest.permission.CLEAR_APP_USER_DATA.equals(param.args[0])) { int re = (int) param.getResult(); XposedBridge.log("ActivityManagerService re:"+re); param.setResult(0);//PackageManager.PERMISSION_GRANTED } } });