/* ** DroidPlugin Project ** ** Copyright(c) 2015 Andy Zhang <zhangyong232@gmail.com> ** ** This file is part of DroidPlugin. ** ** DroidPlugin is free software: you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation, either ** version 3 of the License, or (at your option) any later version. ** ** DroidPlugin is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with DroidPlugin. If not, see <http://www.gnu.org/licenses/lgpl.txt> ** **/ package com.morgoo.droidplugin.hook.handle; import android.content.Context; import android.content.pm.ProviderInfo; import android.net.Uri; import android.net.Uri.Builder; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; import android.text.TextUtils; import com.morgoo.droidplugin.core.Env; import com.morgoo.droidplugin.hook.BaseHookHandle; import com.morgoo.droidplugin.hook.HookedMethodHandler; import java.lang.reflect.Method; /** * Created by Andy Zhang(zhangyong232@gmail.com) on 2015/3/6. */ public class IContentProviderInvokeHandle extends BaseHookHandle { private final ProviderInfo mStubProvider; private final ProviderInfo mTargetProvider; private final boolean mLocalProvider; public IContentProviderInvokeHandle(Context hostContext, ProviderInfo stubProvider, ProviderInfo targetProvider, boolean localProvider) { super(hostContext); mStubProvider = stubProvider; mTargetProvider = targetProvider; mLocalProvider = localProvider; } @Override protected void init() { sHookedMethodHandlers.put("query", new query(mHostContext)); sHookedMethodHandlers.put("getType", new getType(mHostContext)); sHookedMethodHandlers.put("insert", new insert(mHostContext)); sHookedMethodHandlers.put("bulkInsert", new bulkInsert(mHostContext)); sHookedMethodHandlers.put("delete", new delete(mHostContext)); sHookedMethodHandlers.put("update", new update(mHostContext)); sHookedMethodHandlers.put("openFile", new openFile(mHostContext)); sHookedMethodHandlers.put("openAssetFile", new openAssetFile(mHostContext)); sHookedMethodHandlers.put("applyBatch", new applyBatch(mHostContext)); sHookedMethodHandlers.put("call", new call(mHostContext)); sHookedMethodHandlers.put("createCancellationSignal", new createCancellationSignal(mHostContext)); sHookedMethodHandlers.put("canonicalize", new canonicalize(mHostContext)); sHookedMethodHandlers.put("uncanonicalize", new uncanonicalize(mHostContext)); sHookedMethodHandlers.put("getStreamTypes", new getStreamTypes(mHostContext)); sHookedMethodHandlers.put("openTypedAssetFile", new openTypedAssetFile(mHostContext)); } private class MyHandler extends ReplaceCallingPackageHookedMethodHandler { public MyHandler(Context hostContext) { super(hostContext); } private int indexFirstUri(Object[] args) { if (args != null && args.length > 0) { for (int i = 0; i < args.length; i++) { if (args[i] instanceof Uri) { return i; } } } return -1; } @Override protected boolean beforeInvoke(Object receiver, Method method, Object[] args) throws Throwable { // if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR2) { // final int index = 0; // if (args != null && args.length > index && args[index] instanceof String) { // String pkg = (String) args[index]; // if (!TextUtils.equals(pkg, mHostContext.getPackageName())) { // args[index] = mHostContext.getPackageName(); // } // } // } if (!mLocalProvider && mStubProvider != null) { final int index = indexFirstUri(args); if (index >= 0) { Uri uri = (Uri) args[index]; String authority = uri.getAuthority(); if (!TextUtils.equals(authority, mStubProvider.authority)) { Uri.Builder b = new Builder(); b.scheme(uri.getScheme()); b.authority(mStubProvider.authority); b.path(uri.getPath()); b.query(uri.getQuery()); b.appendQueryParameter(Env.EXTRA_TARGET_AUTHORITY, authority); b.fragment(uri.getFragment()); args[index] = b.build(); } } } return super.beforeInvoke(receiver, method, args); } } private class query extends MyHandler { public query(Context context) { super(context); } } private class getType extends MyHandler { public getType(Context context) { super(context); } } private class insert extends MyHandler { public insert(Context context) { super(context); } } private class bulkInsert extends MyHandler { public bulkInsert(Context context) { super(context); } } private class delete extends MyHandler { public delete(Context context) { super(context); } } private class update extends MyHandler { public update(Context context) { super(context); } } private class openFile extends MyHandler { public openFile(Context context) { super(context); } } private class openAssetFile extends MyHandler { public openAssetFile(Context context) { super(context); } } private class applyBatch extends MyHandler { public applyBatch(Context context) { super(context); } } private class call extends MyHandler { public call(Context context) { super(context); } } private class createCancellationSignal extends MyHandler { public createCancellationSignal(Context context) { super(context); } } private class canonicalize extends MyHandler { public canonicalize(Context context) { super(context); } } private class uncanonicalize extends MyHandler { public uncanonicalize(Context context) { super(context); } } private class getStreamTypes extends MyHandler { public getStreamTypes(Context context) { super(context); } } private class openTypedAssetFile extends MyHandler { public openTypedAssetFile(Context context) { super(context); } } }