{"type":"rich","version":"1.0","provider_name":"phorkie","provider_url":"https:\/\/p.cweiske.de\/","title":"Android 4.1 + xposed 52: prevent clearApplicationUserData","author_name":"Christian Weiske","cache_age":86400,"width":900,"height":900,"html":"<!-- embedding all files of https:\/\/p.cweiske.de\/663 -->\n<link rel=\"stylesheet\" href=\"https:\/\/p.cweiske.de\/css\/embed.css\"\/>\n<div class=\"phork\" id=\"663\">\n    <div class=\"phork-file\">\n <div class=\"phork-content\">\n  \n<div class=\"document\">\n\n\n<p>It did not work. FF3 still crashes.<\/p>\n<\/div>\n\n <\/div>\n <div class=\"phork-meta\">\n  <a href=\"https:\/\/p.cweiske.de\/663\/rev-raw\/3a9df5f3175384b6a0661267fb59f51021109d83\/README.rst\" style=\"float: right\">view raw source<\/a>\n  <a href=\"https:\/\/p.cweiske.de\/663#README.rst\">README.rst<\/a>\n <\/div>\n<\/div>\n    <div class=\"phork-file\">\n <div class=\"phork-content\">\n  <style type=\"text\/css\">\/**\n * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2014 Benny Baumann\n * (http:\/\/qbnz.com\/highlighter\/ and http:\/\/geshi.org\/)\n *\/\n.java .de1, .java .de2 {font: normal normal 1em\/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;}\n.java  {font-family:monospace;}\n.java .imp {font-weight: bold; color: red;}\n.java li, .java .li1 {color: #DDD;}\n.java .ln {width:1px;text-align:right;margin:0;padding:0 2px;vertical-align:top;}\n.java .kw1 {color: #000000; font-weight: bold;}\n.java .kw2 {color: #000066; font-weight: bold;}\n.java .kw3 {color: #003399;}\n.java .kw4 {color: #000066; font-weight: bold;}\n.java .co1 {color: #666666; font-style: italic;}\n.java .co2 {color: #006699;}\n.java .co3 {color: #008000; font-style: italic; font-weight: bold;}\n.java .coMULTI {color: #666666; font-style: italic;}\n.java .es0 {color: #000099; font-weight: bold;}\n.java .br0 {color: #009900;}\n.java .sy0 {color: #339933;}\n.java .st0 {color: #0000ff;}\n.java .nu0 {color: #cc66cc;}\n.java .me1 {color: #006633;}\n.java .me2 {color: #006633;}\n.java span.xtra { display:block; }\n<\/style><div class=\"code\"><table class=\"java\"><tbody><tr class=\"li1\"><td class=\"ln\"><pre class=\"de1\">1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n40\n41\n42\n43\n44\n45\n46\n47\n48\n49\n50\n51\n52\n53\n54\n55\n56\n57\n58\n59\n60\n61\n62\n63\n64\n65\n66\n67\n68\n69\n70\n71\n72\n73\n<\/pre><\/td><td class=\"de1\"><pre class=\"de1\"><span class=\"kw1\">import<\/span> <span class=\"co2\">java.lang.reflect.Method<\/span><span class=\"sy0\">;<\/span>\n&#160;\n<span class=\"kw1\">import<\/span> <span class=\"co2\">de.robv.android.xposed.IXposedHookCmdInit<\/span><span class=\"sy0\">;<\/span>\n<span class=\"kw1\">import<\/span> <span class=\"co2\">de.robv.android.xposed.XC_MethodHook<\/span><span class=\"sy0\">;<\/span>\n<span class=\"kw1\">import<\/span> <span class=\"co2\">de.robv.android.xposed.XposedBridge<\/span><span class=\"sy0\">;<\/span>\n<span class=\"kw1\">import<\/span> <span class=\"co2\">de.robv.android.xposed.XposedHelpers<\/span><span class=\"sy0\">;<\/span>\n<span class=\"kw1\">import<\/span> <span class=\"co2\">de.robv.android.xposed.callbacks.XC_LoadPackage<\/span><span class=\"sy0\">;<\/span>\n&#160;\n<span class=\"kw1\">public<\/span> <span class=\"kw1\">class<\/span> Mypackage <span class=\"co2\">implements<\/span> IXposedHookCmdInit\n<span class=\"br0\">&#123;<\/span>\n&#160; &#160; @Override\n&#160; &#160; <span class=\"kw1\">public<\/span> <span class=\"kw4\">void<\/span> initCmdApp<span class=\"br0\">&#40;<\/span>StartupParam startupParam<span class=\"br0\">&#41;<\/span> <span class=\"kw1\">throws<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+throwable\"><span class=\"kw3\">Throwable<\/span><\/a> <span class=\"br0\">&#123;<\/span>\n&#160; &#160; &#160; &#160; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"sy0\">!<\/span>startupParam.<span class=\"me1\">startClassName<\/span>.<span class=\"me1\">equals<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;com.android.commands.pm.Pm&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; <span class=\"kw1\">return<\/span><span class=\"sy0\">;<\/span>\n&#160; &#160; &#160; &#160; <span class=\"br0\">&#125;<\/span>\n&#160; &#160; &#160; &#160; <span class=\"co1\">\/\/XposedBridge.log(&quot;startup:&quot; + startupParam.startClassName);<\/span>\n&#160;\n&#160; &#160; &#160; &#160; <span class=\"coMULTI\">\/*<\/span>\n<span class=\"coMULTI\">&#160; &#160; &#160; &#160; &#160;Final Fantasy 3 has a native library lib__57d5__.so that tries to clear the data<\/span>\n<span class=\"coMULTI\">&#160; &#160; &#160; &#160; &#160;for all apk files in \/data\/app\/. We do not know why.<\/span>\n&#160;\n<span class=\"coMULTI\">&#160; &#160; &#160; &#160; &#160;It fails to do this for root-owned packages like this xposed module.<\/span>\n<span class=\"coMULTI\">&#160; &#160; &#160; &#160; &#160;See<\/span>\n<span class=\"coMULTI\">&#160; &#160; &#160; &#160; &#160;https:\/\/forum.xda-developers.com\/xposed\/framework-xposed-rom-modding-modifying-t1574401\/page170#1700<\/span>\n&#160;\n<span class=\"coMULTI\">&#160; &#160; &#160; &#160; &#160;We simply prevent it from doing that.<\/span>\n&#160;\n<span class=\"coMULTI\">&#160; &#160; &#160; &#160; &#160;https:\/\/android.googlesource.com\/platform\/frameworks\/base\/+\/refs\/tags\/android-4.1.2_r1\/core\/java\/android\/app\/ActivityManagerNative.java#2880<\/span>\n&#160;\n<span class=\"coMULTI\">&#160; &#160; &#160; &#160; &#160;public boolean clearApplicationUserData(<\/span>\n<span class=\"coMULTI\">&#160; &#160; &#160; &#160; &#160; &#160; &#160;String packageName, IPackageDataObserver observer, final int userId<\/span>\n<span class=\"coMULTI\">&#160; &#160; &#160; &#160; &#160;)<\/span>\n<span class=\"coMULTI\">&#160; &#160; &#160; &#160; &#160;*\/<\/span>\n&#160; &#160; &#160; &#160; XposedHelpers.<span class=\"me1\">findAndHookMethod<\/span><span class=\"br0\">&#40;<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; <span class=\"st0\">&quot;android.app.ActivityManagerProxy&quot;<\/span>,\n&#160; &#160; &#160; &#160; &#160; &#160; <span class=\"kw2\">null<\/span>,\n&#160; &#160; &#160; &#160; &#160; &#160; <span class=\"st0\">&quot;clearApplicationUserData&quot;<\/span>,\n&#160; &#160; &#160; &#160; &#160; &#160; <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+string\"><span class=\"kw3\">String<\/span><\/a>.<span class=\"kw1\">class<\/span>,\n&#160; &#160; &#160; &#160; &#160; &#160; <span class=\"st0\">&quot;android.content.pm.IPackageDataObserver&quot;<\/span>,\n&#160; &#160; &#160; &#160; &#160; &#160; <span class=\"kw4\">int<\/span>.<span class=\"kw1\">class<\/span>,\n&#160; &#160; &#160; &#160; &#160; &#160; <span class=\"kw1\">new<\/span> XC_MethodHook<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; @Override\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; <span class=\"kw1\">protected<\/span> <span class=\"kw4\">void<\/span> beforeHookedMethod<span class=\"br0\">&#40;<\/span>MethodHookParam param<span class=\"br0\">&#41;<\/span> <span class=\"kw1\">throws<\/span> <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+throwable\"><span class=\"kw3\">Throwable<\/span><\/a> <span class=\"br0\">&#123;<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+string\"><span class=\"kw3\">String<\/span><\/a> packageName <span class=\"sy0\">=<\/span> <span class=\"br0\">&#40;<\/span><a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+string\"><span class=\"kw3\">String<\/span><\/a><span class=\"br0\">&#41;<\/span> param.<span class=\"me1\">args<\/span><span class=\"br0\">&#91;<\/span><span class=\"nu0\">0<\/span><span class=\"br0\">&#93;<\/span><span class=\"sy0\">;<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; XposedBridge.<span class=\"me1\">log<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;clearApplicationUserData: &quot;<\/span> <span class=\"sy0\">+<\/span> packageName<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"sy0\">!<\/span>packageName.<span class=\"me1\">equals<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;mypackage&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; <span class=\"kw1\">return<\/span><span class=\"sy0\">;<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; <span class=\"br0\">&#125;<\/span>\n&#160;\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; param.<span class=\"me1\">setResult<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw2\">true<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n&#160;\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; <span class=\"co1\">\/\/we do not have direct access to IPackageDataObserver, so we have to dance<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+object\"><span class=\"kw3\">Object<\/span><\/a> observer <span class=\"sy0\">=<\/span> param.<span class=\"me1\">args<\/span><span class=\"br0\">&#91;<\/span><span class=\"nu0\">1<\/span><span class=\"br0\">&#93;<\/span><span class=\"sy0\">;<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; <span class=\"kw1\">if<\/span><span class=\"br0\">&#40;<\/span>observer <span class=\"sy0\">!=<\/span> <span class=\"kw2\">null<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; Class<span class=\"sy0\">&lt;?&gt;<\/span> iPackageDataObserverClass <span class=\"sy0\">=<\/span> <span class=\"kw1\">Class<\/span>.<span class=\"me1\">forName<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;android.content.pm.IPackageDataObserver&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; Class<span class=\"sy0\">&lt;?&gt;<\/span><span class=\"br0\">&#91;<\/span><span class=\"br0\">&#93;<\/span> paramTypes <span class=\"sy0\">=<\/span> <span class=\"br0\">&#123;<\/span><a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+string\"><span class=\"kw3\">String<\/span><\/a>.<span class=\"kw1\">class<\/span>, <span class=\"kw4\">boolean<\/span>.<span class=\"kw1\">class<\/span><span class=\"br0\">&#125;<\/span><span class=\"sy0\">;<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+method\"><span class=\"kw3\">Method<\/span><\/a> onRemoveCompletedMethod <span class=\"sy0\">=<\/span> iPackageDataObserverClass.<span class=\"me1\">getMethod<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;onRemoveCompleted&quot;<\/span>, paramTypes<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; <a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+object\"><span class=\"kw3\">Object<\/span><\/a><span class=\"br0\">&#91;<\/span><span class=\"br0\">&#93;<\/span> params <span class=\"sy0\">=<\/span> <span class=\"br0\">&#123;<\/span>packageName, <span class=\"kw2\">true<\/span><span class=\"br0\">&#125;<\/span><span class=\"sy0\">;<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; <span class=\"kw1\">try<\/span> <span class=\"br0\">&#123;<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; onRemoveCompletedMethod.<span class=\"me1\">invoke<\/span><span class=\"br0\">&#40;<\/span>observer, params<span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; <span class=\"co1\">\/\/observer.onRemoveCompleted(packageName, true);<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; <span class=\"br0\">&#125;<\/span> <span class=\"kw1\">catch<\/span> <span class=\"br0\">&#40;<\/span><a href=\"http:\/\/www.google.com\/search?hl=en&amp;q=allinurl%3Adocs.oracle.com+javase+docs+api+exception\"><span class=\"kw3\">Exception<\/span><\/a> e<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; XposedBridge.<span class=\"me1\">log<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;Observer no longer exists.&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; <span class=\"br0\">&#125;<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; <span class=\"br0\">&#125;<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; <span class=\"co1\">\/\/end dance<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; <span class=\"br0\">&#125;<\/span>\n&#160; &#160; &#160; &#160; &#160; &#160; <span class=\"br0\">&#125;<\/span>\n&#160; &#160; &#160; &#160; <span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span>\n&#160;\n&#160; &#160; <span class=\"br0\">&#125;<\/span>\n<span class=\"br0\">&#125;<\/span>\n&#160;<\/pre><\/td><\/tr><\/tbody><\/table><\/div>\n <\/div>\n <div class=\"phork-meta\">\n  <a href=\"https:\/\/p.cweiske.de\/663\/rev-raw\/3a9df5f3175384b6a0661267fb59f51021109d83\/xposed.java\" style=\"float: right\">view raw source<\/a>\n  <a href=\"https:\/\/p.cweiske.de\/663#xposed.java\">xposed.java<\/a>\n <\/div>\n<\/div>\n<\/div>\n"}
