ContentProvider

778 阅读7分钟

Replugin中Client进程通过Server常驻进程ContentProvider对外提供Binder, 进而完成Client与常驻进程的通信.

Replugin源码阅读---框架初始化

IPC学习---AIDL简单概念

Replugin初始化时, 在PmBase.init中如果是Client进程, 则会调用initForClient方法对非常驻进程进行初始化, 方法调用链

上面流程图中Client进程通过getContentResolver.query获取cursor, 然后获取常驻进程的Binder

ContentProvider获取流程
  • 1、通过getContentResolver获取ContentResolver
  • 2、getContentResolver返回ContextImpl内部类ApplicationContentResolver对象
  • 3、ContentResolver中通过AMS和ActivityThread最终获得IContentResolver接口对象
  • 3.1、首先判断URI是否符合标准
  • 3.2、通过ContextImpl的内部类ApplicationContentResolver发送消息到调用者的ActivityThread中查看是否有被调用的ContentProvider的缓存, 如果有直接返回, 如果没有调用AMS的getContentProvider方法
  • 3.3、AMS的getContentProvider方法又调用了getContentProviderImpl方法, 在这个方法中, 判断了provider在AMS当中是否存在缓存, 接着判断了multiprocess属性是否为true, 如果为true代表该provider允许在调用者进程中创建实例, 但是系统默认是false, 然后判断provider的进程是否已经被创建, 如果没有被创建则调用AMS中的startProcessLocked方法通过Process.start方法创建这个provider所属的进程
  • 3.4、进程被创建后执行该进程的ActivityThread中的main方法, 在main方法中会开启消息循环, 然后调用attach方法, 在attach方法中通过调用AMS中的attachApplication方法, 又转到AMS的attachApplicationLocked中, 在这里通过ActivityThread的bindApplication方法调回到ActivityThread中, 在这里初始化一些信息后发送一条消息到ActivityThread中的Handler, 然后Handler调用handleBindApplication方法, 在这个方法中创建了Application方法, 然后调用installContentProviders方法
  • 3.5、在installContentProvider方法中分两步:
  • 3.5.1、开启for循环来加载所有需要在这个进程创建的provider, for循环中调用了installProviders方法, 在installProvider方法中加载ContentProvider类, 通过加载的ContentProvider.getIContentProvider获取IContentProvider接口对象, 这个接口对象是一个Binder对象, 返回的是一个叫Transport类型的对象, 这个对象继承于ContentProviderNative, 而ContentProviderNative继承于Binder并实现了IContentProvider接口, 也就是说在这里被加载完的ContentProvider返回的是一个Binder类型的IContentProvider接口对象, 所以它可以跨进程调用
  • 3.5.2、加载ContentProvider类后调用AMS的publishContentProviders方法通知AMS, ContentProvider已经加载完成, 并返回这个Binder类型的IContentProvider接口对象, 然后就可以对该进程中的Provider进行操作了

<provider
	android:name=".MyContentProvider"
	android:authorities="com.example.content.provider"
    android:multiprocess="false"
    android:process=":remote"
    android:exported="true"/>

**multiprocess: ** 为true表示每个调用者进程都会创建一个ContentProvider, 默认为false

**process: **表示ContentProvider所在的进程

**exported: **为true表示允许其他应用访问应用中的ContentProvider(跨进程访问), 默认为false

1、**android:process=":remote"、android:multiprocess="true": **ContentProvider不会随着应用的启动而加载, 当调用ContentProvider的时候才会加载, 并且ContentProvider是在调用者的进程中初始化, 这时候可能定义ContentProvider的remote进程还没有启动

2、**android:process=":remote"、android:multiprocess="false": ** ContentProvider不会随着应用的启动而加载, 当调用到ContentProvider时才会加载, 并且ContentProvider是在"remote"进程中初始化

1. Context.getContentResolver
private ContextImpl(ContextImpl container, ActivityThread mainThread,
            		LoadedApk packageInfo, String splitName,
            		IBinder activityToken, UserHandle user, int flags,
            		ClassLoader classLoader) {
	mContentResolver = new ApplicationContentResolver(this, mainThread);   
}

public ContentResolver getContentResolver() {
    return mContentResolver;
}
2.ApplicationContentResolver.query
public final Cursor query(final Uri uri, String[] projection, Bundle queryArgs,
            			  CancellationSignal cancellationSignal) {
	// 1.获取IContentProvider接口对象
    IContentProvider unstableProvider = acquireUnstableProvider(uri);
    IContentProvider stableProvider = null;
    Cursor qCursor = null;
    // 2.通过获取的IContentProvider查询数据, 并返回Cursor对象, 在这里会线程阻塞
	qCursor = unstableProvider.query(mPackageName, uri, projection,
                        queryArgs, remoteCancellationSignal);
    qCursor.getCount();
    long durationMillis = SystemClock.uptimeMillis() - startTime;
    maybeLogQueryToEventLog(durationMillis, uri, projection, queryArgs);
    final IContentProvider provider = (stableProvider != null) ? stableProvider
                    : acquireProvider(uri);
    // 5.将返回的cursor包装成CursorWrapperInner
    final CursorWrapperInner wrapper = new CursorWrapperInner(qCursor, provider);
    stableProvider = null;
    qCursor = null;
    return wrapper;
}
3 ApplicationContentResolver.acquireUnstableProvider
ApplicationContentResolver.acquireUnstableProvider()
--->ActivityThread.acquireProvider()
4 ActivityThread.acquireProvider
public final IContentProvider acquireProvider(
            Context c, String auth, int userId, boolean stable) {
    // 1.查看是否有缓存的IContentProvider, 如果有, 直接返回
    IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
    if (provider != null) {
        return provider;
	}
    ContentProviderHolder holder = null;
    // 2.拿到ActivityManagerService对象, 然后通过AMS获取被调用的provider的信息
	holder = ActivityManager.getService().getContentProvider(
                        getApplicationThread(), auth, userId, stable);
    if (holder == null) {
        return null;
    }
    // 3.拿到目标ContentProvider信息并保存
    holder = installProvider(c, holder, holder.info,
                true /*noisy*/, holder.noReleaseNeeded, stable);
    // 4.返回该ContentProvider
    return holder.provider;
}
5.AMS.getContentProvider
@Override
public final ContentProviderHolder getContentProvider(
            IApplicationThread caller, String name, int userId, boolean stable) {
    // 进入该方法
    return getContentProviderImpl(caller, name, null, stable, userId);
}
6.AMS.getContentProviderImpl
private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
            String name, IBinder token, boolean stable, int userId) {
    // 1.用来保存provider的信息
    ContentProviderRecord cpr;
    ContentProviderConnection conn = null;
    ProviderInfo cpi = null;
    synchronized(this) {
        long startTime = SystemClock.uptimeMillis();
		// 2.获取调用者的进程信息
        ProcessRecord r = null;
        if (caller != null) {
            r = getRecordForAppLocked(caller);
        }
        boolean checkCrossUser = true;
        // 3.查看provider的信息是否被加载过, 是否存在缓存
        cpr = mProviderMap.getProviderByName(name, userId);
        if (cpr == null && userId != UserHandle.USER_SYSTEM) {
        	cpr = mProviderMap.getProviderByName(name, UserHandle.USER_SYSTEM);
            if (cpr != null) {
                cpi = cpr.info;
                if (isSingleton(cpi.processName, cpi.applicationInfo,
                            cpi.name, cpi.flags)
                            && isValidSingletonCall(r.uid, cpi.applicationInfo.uid)) {
                    userId = UserHandle.USER_SYSTEM;
                    checkCrossUser = false;
                } else {
                    cpr = null;
                    cpi = null;
                }
            }
        }
        // 4.如果是第一次调用, providerRunning一定为false
        boolean providerRunning = cpr != null && cpr.proc != null && !cpr.proc.killed;
        if (providerRunning) {
        	// 5.如果有缓存
            cpi = cpr.info;
            String msg;
			// 6.判断provider的multiprocess是否为true, 如果是true, provider则会在调用者
            //   的进程中初始化, 如果multiprocess为false, 则默认系统只有一个该provider
            if (r != null && cpr.canRunHere(r)) {
                ContentProviderHolder holder = cpr.newHolder(null);
                holder.provider = null;
                return holder;
            }
        }
		// 7.如果没有缓存
        if (!providerRunning) {
			// 8.通过PMS得到provider所在应用程序的信息
            cpi = AppGlobals.getPackageManager().
                        resolveContentProvider(name,
                            STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId);
            if (cpi == null) {
                return null;
            }
            ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
            // 10.判断provider这个类是否是第一次加载
            cpr = mProviderMap.getProviderByClass(comp, userId);
            final boolean firstClass = cpr == null;
            if (firstClass) {
                final long ident = Binder.clearCallingIdentity();
                try {
                	// 11.获取provider的Application信息
                    ApplicationInfo ai =
                            AppGlobals.getPackageManager().
                                getApplicationInfo(
                                        cpi.applicationInfo.packageName,
                                        STOCK_PM_FLAGS, userId);
                    ai = getAppInfoForUser(ai, userId);
                    cpr = new ContentProviderRecord(this, cpi, ai, comp, singleton);
                } finally {
                    Binder.restoreCallingIdentity(ident);
                }
            }
			/** 
             * 12.判断provider的multiprocess是否为true, 如果是true, provider则会在调用者
             *    的进程中初始化, multiprocess默认为false, 默认系统只有一个该provider
             */
            if (r != null && cpr.canRunHere(r)) {
                return cpr.newHolder(null);
            }
			/**
             * 13.系统中所有的provider都会存储在mLaunchingProviders的ArrayList中, 默认情况下
             *    系统只能有一个该provider的实例, 这里是看一下是否有其他的应用已经实例了该provider,
             *    如果是肯定会存在mLaunchingProviders, 那么i也就肯定小于N
             */
            final int N = mLaunchingProviders.size();
            int i;
            for (i = 0; i < N; i++) {
                if (mLaunchingProviders.get(i) == cpr) {
                    break;
                }
            }
			// 14.执行到这里说明没有其他应用实例该provider
            if (i >= N) {
                final long origId = Binder.clearCallingIdentity();
                try {
					//15.查看provider所属进程是否已经存在
                    ProcessRecord proc = getProcessRecordLocked(
                                cpi.processName, cpr.appInfo.uid, false);
                    //16.判断该进程是否已经启动
                    if (proc != null && proc.thread != null && !proc.killed) {
                        if (!proc.pubProviders.containsKey(cpi.name)) {
                            proc.pubProviders.put(cpi.name, cpr);
							//16.使用ApplicationThread发送加载provider的消息
                            proc.thread.scheduleInstallProvider(cpi);
                        }
                    } else {
                    	//17如果进程没有创建则创建一个新进程
                        proc = startProcessLocked(cpi.processName,
                                    cpr.appInfo, false, 0, "content provider",
                                    new ComponentName(cpi.applicationInfo.packageName,
                                            cpi.name), false, false, false);
                    }
                    cpr.launchingApp = proc;
                    mLaunchingProviders.add(cpr);
                } finally {
                    Binder.restoreCallingIdentity(origId);
                }
            }
            //18.存入provider信息
            if (firstClass) {
                mProviderMap.putProviderByClass(comp, cpr);
            }
            mProviderMap.putProviderByName(name, cpr);
            conn = incProviderCountLocked(r, cpr, token, stable);
            if (conn != null) {
                conn.waiting = true;
            }
		}
    }
    //19.将provider的信息封装在ContentProviderHolder并返回
    return cpr != null ? cpr.newHolder(conn) : null;
}
7.ActivityThread.handleBindApplication

如果multiprocess为false, 为ContentProvider新创建一个进程, 进程创建之后调用ActivityThread.handleBindApplication方法

private void handleBindApplication(AppBindData data) {
	//1.创建上下文对象
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
	final InstrumentationInfo ii;
    //2.准备初始化
    if (data.instrumentationName != null) {
        ii = new ApplicationPackageManager(null, getPackageManager())
                        .getInstrumentationInfo(data.instrumentationName, 0);
        mInstrumentationPackageName = ii.packageName;
        mInstrumentationAppDir = ii.sourceDir;
        mInstrumentationSplitAppDirs = ii.splitSourceDirs;
        mInstrumentationLibDir = getInstrumentationLibrary(data.appInfo, ii);
        mInstrumentedAppDir = data.info.getAppDir();
        mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
        mInstrumentedLibDir = data.info.getLibDir();
    } else {
        ii = null;
    }
    // Continue loading instrumentation.
    if (ii != null) {
        ApplicationInfo instrApp;
		//3.创建Application的数据
        instrApp = getPackageManager().getApplicationInfo(ii.packageName, 0,
                        UserHandle.myUserId());
        if (instrApp == null) {
            instrApp = new ApplicationInfo();
        }
        ii.copyTo(instrApp);
        instrApp.initForUser(UserHandle.myUserId());
        //4.LoadedApk对象是APK文件在内存中的表示, 例如Apk文件的相关信息, Apk文件的代码和资源,
        //  甚至代码里面的Activity, Service等四大组件的信息都可以通过此对象获取.  
        final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                    appContext.getClassLoader(), false, true, false);
        final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);

        final ClassLoader cl = instrContext.getClassLoader();
        mInstrumentation = (Instrumentation)
                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
        final ComponentName component = new ComponentName(ii.packageName, ii.name);
        //5.初始化Instrumentation
        mInstrumentation.init(this, instrContext, appContext, component,
                    data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
    } else {
        mInstrumentation = new Instrumentation();
        mInstrumentation.basicInit(this);
    }
    Application app;
    try {
		// 6.通过创建Application并回调Application的attach方法
        app = data.info.makeApplication(data.restrictedBackupMode, null);
        app.setAutofillCompatibilityEnabled(data.autofillCompatibilityEnabled);
        mInitialApplication = app;
        if (!data.restrictedBackupMode) {
        	if (!ArrayUtils.isEmpty(data.providers)) {
            	//7.加载provider
            	installContentProviders(app, data.providers);
                mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
            }
        }
        mInstrumentation.onCreate(data.instrumentationArgs);
        mInstrumentation.callApplicationOnCreate(app);
    } finally {
    }  
}
8.ActivityThread.installContentProviders
private void installContentProviders(
            Context context, List<ProviderInfo> providers) {
    final ArrayList<ContentProviderHolder> results = new ArrayList<>();

    for (ProviderInfo cpi : providers) {
    	// 1.加载ContentProvider
        ContentProviderHolder cph = installProvider(context, null, cpi,
                    false, true, true);
        if (cph != null) {
            cph.noReleaseNeeded = true;
            // 2.ContentProviderHolder存储进results
            results.add(cph);
        }
    }
    // 3.通知AMS, ContentProvider已经加载完成, 并将results发送给AMS进行管理
    ActivityManager.getService().publishContentProviders(
                getApplicationThread(), results);
}
9.ActivityThread.installProvider
private ContentProviderHolder installProvider(Context context,
            ContentProviderHolder holder, ProviderInfo info,
            boolean noisy, boolean noReleaseNeeded, boolean stable) {
    ContentProvider localProvider = null;
    IContentProvider provider;
    if (holder == null || holder.provider == null) {
		//1.创建Context
        Context c = null;
        ApplicationInfo ai = info.applicationInfo;
        if (context.getPackageName().equals(ai.packageName)) {
            c = context;
        } else if (mInitialApplication != null &&
                    mInitialApplication.getPackageName().equals(ai.packageName)) {
            c = mInitialApplication;
        } else {
            c = context.createPackageContext(ai.packageName,
                            Context.CONTEXT_INCLUDE_CODE);
        }
        try {
        	//2.创建provider
            final java.lang.ClassLoader cl = c.getClassLoader();
            LoadedApk packageInfo = peekPackageInfo(ai.packageName, true);
            if (packageInfo == null) {
                packageInfo = getSystemContext().mPackageInfo;
            }
            localProvider = packageInfo.getAppFactory()
                        .instantiateProvider(cl, info.name);
            provider = localProvider.getIContentProvider();
            localProvider.attachInfo(c, info);
        } catch (java.lang.Exception e) {
        }
    } else {
        provider = holder.provider;
    }
    ContentProviderHolder retHolder;
    synchronized (mProviderMap) {
    IBinder jBinder = provider.asBinder();
    //3.保持provider信息
    if (localProvider != null) {
        ComponentName cname = new ComponentName(info.packageName, info.name);
        ProviderClientRecord pr = mLocalProvidersByName.get(cname);
        if (pr != null) {
            provider = pr.mProvider;
        } else {
            holder = new ContentProviderHolder(info);
            holder.provider = provider;
            holder.noReleaseNeeded = true;
            pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
            mLocalProviders.put(jBinder, pr);
            mLocalProvidersByName.put(cname, pr);
        }
        retHolder = pr.mHolder;
    } else {
        ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
        if (prc != null) {
            if (!noReleaseNeeded) {
                incProviderRefLocked(prc, stable);
                ActivityManager.getService().removeContentProvider(
                                    holder.connection, stable);
            }
        } else {
            ProviderClientRecord client = installProviderAuthoritiesLocked(
                            provider, localProvider, holder);
            if (noReleaseNeeded) {
                prc = new ProviderRefCount(holder, client, 1000, 1000);
            } else {
                prc = stable
                                ? new ProviderRefCount(holder, client, 1, 0)
                                : new ProviderRefCount(holder, client, 0, 1);
            }
            mProviderRefCountMap.put(jBinder, prc);
        }
        retHolder = prc.holder;
    }
    return retHolder;
}
10.ContentProvider.getIContentProvider
public IContentProvider getIContentProvider() {
    return mTransport;
}
private Transport mTransport = new Transport();

class Transport extends ContentProviderNative{}

abstract public class ContentProviderNative extends Binder implements IContentProvider {}

public interface IContentProvider extends IInterface {}

public interface IInterface
{
    public IBinder asBinder();
}
11.AMS.publishContentProviders
public final void publishContentProviders(IApplicationThread caller,
            List<ContentProviderHolder> providers) {
    synchronized (this) {
        final ProcessRecord r = getRecordForAppLocked(caller);
        final long origId = Binder.clearCallingIdentity();

        final int N = providers.size();
        for (int i = 0; i < N; i++) {
            ContentProviderHolder src = providers.get(i);
            //1.ContentProviderHolder与ContentPRoviderRecord进行映射
            ContentProviderRecord dst = r.pubProviders.get(src.info.name);
            if (dst != null) {
                ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
                mProviderMap.putProviderByClass(comp, dst);
                String names[] = dst.info.authority.split(";");
                for (int j = 0; j < names.length; j++) {
                	//1.缓存ContentProviderRecord
                    mProviderMap.putProviderByName(names[j], dst);
                }
                int launchingCount = mLaunchingProviders.size();
                int j;
                boolean wasInLaunchingProviders = false;
                    for (j = 0; j < launchingCount; j++) {
                        if (mLaunchingProviders.get(j) == dst) {
                            mLaunchingProviders.remove(j);
                            wasInLaunchingProviders = true;
                            j--;
                            launchingCount--;
                        }
                    }
                if (wasInLaunchingProviders) {
                    mHandler.removeMessages(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r);
                }
                synchronized (dst) {
                    dst.provider = src.provider;
                    dst.proc = r;
                    dst.notifyAll();
                }
                updateOomAdjLocked(r, true);
                maybeUpdateProviderUsageStatsLocked(r, src.info.packageName,
                            src.info.authority);
            }
        }
        Binder.restoreCallingIdentity(origId);
    }
}