分分钟钟看懂ContentProvider启动源码流程

《分分钟钟看懂ContentProvider启动源码流程》 类图1

《分分钟钟看懂ContentProvider启动源码流程》 类图2

为了放大时序图,一些类缩小下:
CR:ContentResolver
ACR:ApplicationContentResolver
CPN:ContentProviderNative
CPR:ContentProviderProxy
AMN:ActivityManagerNative
AMP:ActivityManagerProxy
AMS:ActivityManagerService
ATP:ApplicationThreadProxy

《分分钟钟看懂ContentProvider启动源码流程》 时序图

《分分钟钟看懂ContentProvider启动源码流程》 时序图

  1. A应用发送信息给AMS(ActivityManagerService,进程system_server)要访问B应用的XXXContentProvider
  2. AMS检查B应用没有被启动过,则新开一个进程启动B应用
  3. 启动应用B后,AMS向B应用启动XXXContentProvider,并实行相应的onCreate,返回IActivityManager.ContentProviderHolder,其中实现IContentProvider接口的Transact
  4. AMS 把IActivityManager.ContentProviderHolder对象返回给A应用,A应用改造成代理ContentProviderProxy(即IContentProvider),此时A应用就可以调用增删改查等接口到B应用了。
    照着类图和时序图的步数来分析:
    在A应用进程处理:Step1、2、3、4、5、6、18、19
    在AMS system_server进程处理:Step7、10、11、12、17
    在B应用进程处理:Step8、9、13、14、15、16、20

Step1:
  ContentResolver contentResolver = Conext.getContentResolver();
返回是ApplicationContentResolver,定义在ContextImpl内部静态类。

Step2:
  Uri uri = Uri.parse(“content://cn.umbrella.providers.contact/item“);
Cursor cursor = contentResolver.query(uri, new String[]{“id”,”name”,”phone”}, null, null, “id asc”);
在ApplicationContentResolver.acquireProvider()调用ActivityThread类的acquireProvider函数进一步执行获取Content Provider接口的操作。

Step3、4、5:
  ActivityThread. acquireProvider:先本地查找,若有,则直接返回,没有则调用ActivityManagerNative.getDefault().getContentProvider(getApplicationThread(), auth, userId, stable)即ActivityManagerProxy到AMS的getContentProvider()。

Step6:
  在AMS. getContentProvider()调用getContentProviderImpl进一步处理,
在AMS中:ProviderMap mProviderMap成员变量是保存系统中的ContentProvider信息,boolean providerRunning = cpr != null && cpr.proc != null && !cpr.proc.killed先检查XXXContentProvider存在、宿主进程以及没有被杀的情况下,就直接返回。
  若不存在,则会通过AppGlobals.getPackageManage().resolveContentProvider和getApplicationInfo来分别获取XXXProvider应用程序的相关信息,并保存cpi和cpr变量中。接下来会判断mLaunchingProviders(系统中所有正在加载的Content Provider都保到这里面)是不是正在被其它应用程序加载XXXContentProvider,如果B应用进程已开启,但对应的contentprovider未初始化过,则会走proc.thread.scheduleInstallProvider(cpi),到B应用的ActivityThread的handleInstallProvider、installContentProviders初始化contentProvider,略过Step7-13步直接Step14。
  如果B应用进程未启动,则继续走Step7 调用startProcessLocked函数来启动新进程并加装XXXContentProvider,并且把这个正在加载的信息增加到mLaunchingProviders中去,同步等到XXXContentProvider初始化完,while循环cpr.provider判空,然后cpr.wait(),等到Step17步publishContentProviders会dst.notifyAll()过来。

Step7、8、9、10:
  ActivityManagerService.startProcessLocked、Process.start、ActivityThread.main、ActivityThread.attach、ActivityManagerService.attachApplication 新进程的创建完回到AMS的过程,可参考startService源码从AMS进程到service的新进程启动过程分析

Step11:
  AMS. attachApplicationLocked, 会对这个B应用进程记录块做一些初始化,并获得需要加装的ContentProvider列表,即包括XXXContentProvider,然后调用从参数传进来的IApplicationThread对象thread(即ApplicationThreadProxy)的bindApplication进入到B应用程序XXXContentProvider进程中的ApplicationThread对象的bindApplication函数中去。

Step12、13:
  ApplicationThread(ActivityThread 变量). bindApplication通过H(Handler)到ActivityThread主进程中handleBindApplication处理,调用installContentProviders函数来在初始化XXXContent Providers信息,以及Application等初始化工作。

Step14、15:
  ActivityThread.installContentProviders 先调用installContentProviders对XXXContentProvider的初始化attachInfo,并调用onCreate,并把ContextProvider的成员变量Transport(父类ContentProviderNative,是binder对象,并且实现了IContentProvider接口)然后调用ActivityManagerNative.getDefault().publishContentProviders(getApplicationThread(), results),到Step16.

Step16:
  ActivityManagerProxy. publishContentProviders(IApplicationThread caller, List<ContentProviderHolder> providers)通知AMS进程 ,B应用进程及XXXContentProvider都已初始化完毕,并把相应的IContentProvider给过去。

Step17 :
  AMS. publishContentProviders:会把B应用进程的的ContentProvider保存起来,并移除mLaunchingProviders里面相应的值,然后通知dst.notifyAll();到Step6的getContentProviderImpl,接着返回给A应用进程的ContentProviderHolder对象。

Step18:
  在AMS进程通过binder返回给A应用对象ContentProviderHolder,会把B应用进程的IContentProvider接口(即Transport)通过ContentProviderNative.asInterface(source.readStrongBinder())改造为ContentProviderProxy。

Step19、20:
  A应用进程拿到B应用进程的Transport后, ContentResolver.query()中调用ContentProviderProxy.query,这里面会BulkCursorToCursorAdaptor,包含CursorWindow等匿名共享内存方式读取数据。

附上一些关键的源码:

ContextImpl.java:
class ContextImpl extends Context {
    private final ApplicationContentResolver mContentResolver;
    @Override
    public ContentResolver getContentResolver() {
        return mContentResolver;
    }
    ...
    private static final class ApplicationContentResolver extends ContentResolver {
        private final ActivityThread mMainThread;
        private final UserHandle mUser;
        ...
        @Override
        protected IContentProvider acquireUnstableProvider(Context c, String auth) {
            return mMainThread.acquireProvider(c,
                    ContentProvider.getAuthorityWithoutUserId(auth),
                    resolveUserIdFromAuthority(auth), false);
        }
       ...
    }
}
ContentResolver.java:
public abstract class ContentResolver {
    public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,
            @Nullable String[] projection, @Nullable String selection,
            @Nullable String[] selectionArgs, @Nullable String sortOrder,
            @Nullable CancellationSignal cancellationSignal) {
        Preconditions.checkNotNull(uri, "uri");
        IContentProvider unstableProvider = acquireUnstableProvider(uri);
        ...
        try {
            qCursor = unstableProvider.query(mPackageName, uri, projection,
                    selection, selectionArgs, sortOrder, remoteCancellationSignal);
        } 
        ...
    }
}
ActivityThread.java:
public final class ActivityThread {

    public final IContentProvider acquireProvider(
            Context c, String auth, int userId, boolean stable) {
        final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
        if (provider != null) {
            return provider;
        }
        ...
        IActivityManager.ContentProviderHolder holder = null;
        try {
            holder = ActivityManagerNative.getDefault().getContentProvider(
                    getApplicationThread(), auth, userId, stable);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
        ...
        holder = installProvider(c, holder, holder.info,
                true /*noisy*/, holder.noReleaseNeeded, stable);
        return holder.provider;
    }
    
    public final IContentProvider acquireExistingProvider(
            Context c, String auth, int userId, boolean stable) {
        synchronized (mProviderMap) {
            final ProviderKey key = new ProviderKey(auth, userId);
            final ProviderClientRecord pr = mProviderMap.get(key);
            ...
            IContentProvider provider = pr.mProvider;
            IBinder jBinder = provider.asBinder();
            ...            
            return provider;
        }
    }
    private void installContentProviders(Context context, List<ProviderInfo> providers) {
        final ArrayList<IActivityManager.ContentProviderHolder> results =
            new ArrayList<IActivityManager.ContentProviderHolder>();
        for (ProviderInfo cpi : providers) {            
            IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
                    false, true , true );
            if (cph != null) {
                cph.noReleaseNeeded = true;
                results.add(cph);
            }
        }
        try {
            ActivityManagerNative.getDefault().publishContentProviders(
                getApplicationThread(), results);
        } catch (RemoteException ex) {
        }
    }
    private IActivityManager.ContentProviderHolder installProvider(Context context,
            IActivityManager.ContentProviderHolder holder, ProviderInfo info,
            boolean noisy, boolean noReleaseNeeded, boolean stable) {
        ContentProvider localProvider = null;
        IContentProvider provider;
        if (holder == null || holder.provider == null) {
            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 {
                try {
                    c = context.createPackageContext(ai.packageName,
                            Context.CONTEXT_INCLUDE_CODE);
                } 
            }            
            try {
                final java.lang.ClassLoader cl = c.getClassLoader();
                localProvider = (ContentProvider)cl.
                    loadClass(info.name).newInstance();
                provider = localProvider.getIContentProvider();            
                localProvider.attachInfo(c, info);
            } catch (java.lang.Exception e) {
            }
        } else {
            provider = holder.provider;
        }
        IActivityManager.ContentProviderHolder retHolder;
        synchronized (mProviderMap) {
            IBinder jBinder = provider.asBinder();
            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 IActivityManager.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 {
                ...
            }
        }
        return retHolder;
    }
    private void handleBindApplication(AppBindData data) {
        ...
        final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
        ...    
        if (ii != null) {
            final ApplicationInfo instrApp = new ApplicationInfo();
            ii.copyTo(instrApp);
            instrApp.initForUser(UserHandle.myUserId());
            final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                    appContext.getClassLoader(), false, true, false);
            final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
            try {
                final ClassLoader cl = instrContext.getClassLoader();
                mInstrumentation = (Instrumentation)
                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
            }
            final ComponentName component = new ComponentName(ii.packageName, ii.name);
            mInstrumentation.init(this, instrContext, appContext, component,
                    data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
        } else {
            mInstrumentation = new Instrumentation();
        }
        ...
        try {
            // If the app is being launched for full backup or restore, bring it up in
            // a restricted environment with the base application class.
            Application app = data.info.makeApplication(data.restrictedBackupMode, null);
            mInitialApplication = app;
            // don't bring up providers in restricted mode; they may depend on the
            // app's custom Application class
            if (!data.restrictedBackupMode) {
                if (!ArrayUtils.isEmpty(data.providers)) {
                    installContentProviders(app, data.providers);
                }
            }
            try {
                mInstrumentation.onCreate(data.instrumentationArgs);
            }
            try {
                mInstrumentation.callApplicationOnCreate(app);
            } 
        } 
    }
}
ActivityManagerNative.java:
public abstract class ActivityManagerNative extends Binder implements IActivityManager{
    static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
        return new ActivityManagerProxy(obj);
    }
    static public IActivityManager getDefault() {
        return gDefault.get();
    }
    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            IActivityManager am = asInterface(b);
            return am;
        }
    };
}
class ActivityManagerProxy implements IActivityManager{
    public ActivityManagerProxy(IBinder remote) {
        mRemote = remote;
    }
    public ContentProviderHolder getContentProvider(IApplicationThread caller,
            String name, int userId, boolean stable) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(name);
        data.writeInt(userId);
        data.writeInt(stable ? 1 : 0);
        mRemote.transact(GET_CONTENT_PROVIDER_TRANSACTION, data, reply, 0);
        reply.readException();
        int res = reply.readInt();
        ContentProviderHolder cph = null;
        if (res != 0) {
            cph = ContentProviderHolder.CREATOR.createFromParcel(reply);
        }
        data.recycle();
        reply.recycle();
        return cph;
    }
    public void publishContentProviders(IApplicationThread caller,
            List<ContentProviderHolder> providers) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeTypedList(providers);
        mRemote.transact(PUBLISH_CONTENT_PROVIDERS_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }
}
ActivityManagerService.java:
public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
    @Override
    public final ContentProviderHolder getContentProvider(
            IApplicationThread caller, String name, int userId, boolean stable) {
        ...
        // The incoming user check is now handled in checkContentProviderPermissionLocked() to deal
        // with cross-user grant.
        return getContentProviderImpl(caller, name, null, stable, userId);
    }
    private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
            String name, IBinder token, boolean stable, int userId) {
        ContentProviderRecord cpr;
        ContentProviderConnection conn = null;
        ProviderInfo cpi = null;

        synchronized(this) {
            long startTime = SystemClock.uptimeMillis();

            ProcessRecord r = null;
            ...
            // First check if this content provider has been published...
            cpr = mProviderMap.getProviderByName(name, userId);
            ...
            boolean providerRunning = cpr != null && cpr.proc != null && !cpr.proc.killed;
            if (providerRunning) {
                cpi = cpr.info;
                ...
                if (r != null && cpr.canRunHere(r)) {
                    // This provider has been published or is in the process
                    // of being published...  but it is also allowed to run
                    // in the caller's process, so don't make a connection
                    // and just let the caller instantiate its own instance.
                    ContentProviderHolder holder = cpr.newHolder(null);
                    // don't give caller the provider object, it needs
                    // to make its own.
                    holder.provider = null;
                    return holder;
                }
                ...
            }

            if (!providerRunning) {
                try {
                    cpi = AppGlobals.getPackageManager().
                        resolveContentProvider(name,
                            STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId);
                } catch (RemoteException ex) {
                }
                ...
                    try {
                        ApplicationInfo ai =
                            AppGlobals.getPackageManager().
                                getApplicationInfo(
                                        cpi.applicationInfo.packageName,
                                        STOCK_PM_FLAGS, userId);                        
                        ai = getAppInfoForUser(ai, userId);
                        cpr = new ContentProviderRecord(this, cpi, ai, comp, singleton);
                    } catch (RemoteException ex) {
                       ...
                    }
               ...
                final int N = mLaunchingProviders.size();
                int i;
                for (i = 0; i < N; i++) {
                    if (mLaunchingProviders.get(i) == cpr) {
                        break;
                    }
                }
                // If the provider is not already being launched, then get it
                // started.
                if (i >= N) {
                    ...
                    try {
                        ...
                        ProcessRecord proc = getProcessRecordLocked(
                                cpi.processName, cpr.appInfo.uid, false);
                        if (proc != null && proc.thread != null && !proc.killed) {
                            if (!proc.pubProviders.containsKey(cpi.name)) {
                                checkTime(startTime, "getContentProviderImpl: scheduling install");
                                proc.pubProviders.put(cpi.name, cpr);
                                try {
                                    proc.thread.scheduleInstallProvider(cpi);
                                } catch (RemoteException e) {
                                }
                            }
                        } else {
                            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);
                    }
                }
                ...
                mProviderMap.putProviderByName(name, cpr);
                conn = incProviderCountLocked(r, cpr, token, stable);
                if (conn != null) {
                    conn.waiting = true;
                }
            }
        }
        // Wait for the provider to be published...
        synchronized (cpr) {
            while (cpr.provider == null) {
               ...
                try {
                    if (conn != null) {
                        conn.waiting = true;
                    }
                    cpr.wait();
                } catch (InterruptedException ex) {
                } finally {
                    if (conn != null) {
                        conn.waiting = false;
                    }
                }
            }
        }
        return cpr != null ? cpr.newHolder(conn) : null;
    }
    
    @Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }
    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
        ...
            ProfilerInfo profilerInfo = profileFile == null ? null
                    : new ProfilerInfo(profileFile, profileFd, samplingInterval, profileAutoStop);
            thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                    profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                    app.instrumentationUiAutomationConnection, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(mConfiguration), app.compat,
                    getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked());
        ...
        return true;
    }
}
IActivityManager.java:
public interface IActivityManager extends IInterface {
    public static class ContentProviderHolder implements Parcelable {
        public final ProviderInfo info;
        public IContentProvider provider;
        public IBinder connection;
        public boolean noReleaseNeeded;
        ...
        public static final Parcelable.Creator<ContentProviderHolder> CREATOR
                = new Parcelable.Creator<ContentProviderHolder>() {
            @Override
            public ContentProviderHolder createFromParcel(Parcel source) {
                return new ContentProviderHolder(source);
            }

            @Override
            public ContentProviderHolder[] newArray(int size) {
                return new ContentProviderHolder[size];
            }
        };
        private ContentProviderHolder(Parcel source) {
            info = ProviderInfo.CREATOR.createFromParcel(source);
            provider = ContentProviderNative.asInterface(
                    source.readStrongBinder());
            connection = source.readStrongBinder();
            noReleaseNeeded = source.readInt() != 0;
        }
    }
}
    原文作者:umbrella1
    原文地址: https://www.jianshu.com/p/74014e1b18b0
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞