package android.taobao.atlas.runtime.newcomponent.provider;
import android.app.ContentProviderHolder;
import android.app.IActivityManager;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.pm.ProviderInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.taobao.atlas.hack.AndroidHack;
import android.taobao.atlas.hack.AtlasHacks;
import android.taobao.atlas.runtime.RuntimeVariables;
import android.taobao.atlas.runtime.newcomponent.BridgeUtil;
import android.util.Log;
import java.util.HashMap;
/**
* Created by guanjie on 2017/4/10.
*/
public class ContentProviderBridge extends ContentProvider{
public static final String METHOD_INSTALLPROVIDER = "atlas_install_provider";
public static final String PROVIDER_INFO_KEY = "info";
public static final String PROVIDER_HOLDER_KEY = "holder";
private HashMap<String,Object> providerRecord = new HashMap<>();
public static Object getContentProvider(ProviderInfo info){
String targetProcessName = info.processName!=null ? info.processName : RuntimeVariables.androidApplication.getPackageName();
String currentProcessName = RuntimeVariables.getProcessName(RuntimeVariables.androidApplication);
if(info.multiprocess || targetProcessName.equals(RuntimeVariables.getProcessName(RuntimeVariables.androidApplication))){
return transactProviderInstall(currentProcessName,info);
}else{
return transactProviderInstall(info.processName,info);
}
}
public static void completeRemoveProvider(){
}
public static void removeContentProvider(){
}
private static Uri accquireRemoteBridgeToken(String processName){
return Uri.parse("content://"+ BridgeUtil.getBridgeName(BridgeUtil.TYPE_PROVIDERBRIDGE,processName));
}
private static Object transactProviderInstall(String processName,ProviderInfo info){
Bundle extras = new Bundle();
extras.putParcelable(PROVIDER_INFO_KEY,info);
ContentResolver contentResolver = RuntimeVariables.androidApplication.getContentResolver();
Bundle bundle = contentResolver.call(accquireRemoteBridgeToken(processName),METHOD_INSTALLPROVIDER,"",extras);
Object holder = bundle.getParcelable(PROVIDER_HOLDER_KEY);
return holder;
}
@Override
public boolean onCreate() {
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
return null;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
}
@Override
public Bundle call(String method, String arg, Bundle extras) {
Log.e("ContentProviderBridge","call");
if(method.equals(METHOD_INSTALLPROVIDER)){
ProviderInfo info = extras.getParcelable(PROVIDER_INFO_KEY);
if(info==null){
return null;
}
Object holder = providerRecord.get(info.authority);
if(holder==null){
//install contentprovider
Object original = null;
if(Build.VERSION.SDK_INT>25 || (Build.VERSION.SDK_INT==25&&Build.VERSION.PREVIEW_SDK_INT>0)) {
original = new ContentProviderHolder(null);
}else{
original = new IActivityManager.ContentProviderHolder(null);
}
try {
Object activityThread = AndroidHack.getActivityThread();
if(activityThread!=null) {
Object newHolder = AtlasHacks.ActivityThread_installProvider.invoke(
activityThread,RuntimeVariables.androidApplication,original,info,false,true,true);
holder = newHolder;
providerRecord.put(info.authority,holder);
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
Bundle result = new Bundle();
if(Build.VERSION.SDK_INT>25 || (Build.VERSION.SDK_INT==25&&Build.VERSION.PREVIEW_SDK_INT>0)) {
result.putParcelable(PROVIDER_HOLDER_KEY, (ContentProviderHolder)holder);
}else{
result.putParcelable(PROVIDER_HOLDER_KEY, (IActivityManager.ContentProviderHolder)holder);
}
return result;
}
return super.call(method, arg, extras);
}
}