ContentProvider是内容提供者,对外提供数据。内部运行依赖Binde机制。想要自己写一个ContentProvider向外部提供数据,需要继承ContentProvider并重写一下六个方法,在ContentProvider中提供了增删改查的方法,一般这个增删改查会通过SqliteDataBase这个数据库的方式对外提供增删改查的功能。也可以不这么做。
@Override
public boolean onCreate() {
return false;
}
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
return null;
}
@Nullable
@Override
public String getType(@NonNull Uri uri) {
return null;
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
return null;
}
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
return 0;
}
需要在AndroidManifest.xml中去注册:
authorities 相当于是个地址
permission 用于控制权限
其它客户端查询,需要用到ContentResolver对象,ContentResolver是抽象类,它的实现是ContextImpl中的ApplicationContentResolver,是在ContextImpl的构造方法中创建的对象。
Uri bookUri = Uri.parse("content://com.sososeen09.knowledge.provider.book/book");
ContentValues values = new ContentValues();
values.put("_id", 6);
getContentResolver().insert(bookUri, values);
Cursor bookCursor = getContentResolver().query(bookUri, new String[]{"_id", "name"}, null, null, null);
Context的getContentResolver方法实际上获取的就是ContextImpl的ApplicationContentResolver类型的成员mContentResolver。
当ContentProvider所在进程还未创建时,第一次访问ContentProvider会触发ContentProvider所在进程的创建和ContentProvider对象的创建。通过ContentProvider的4个方法中的任何一个都会触发ContentProvider的启动过程。
源码分析
我们分析getContentResolver().query
方法触发的流程。
ContextWrapper的getContentResolver的方法如下,还是通过mBase来获取,这个mBase实际上是ContextImpl对象。
@Override
public ContentResolver getContentResolver() {
return mBase.getContentResolver();
}
来看一下ContextImpl的getContentResolver方法,直接返回了一个成员变量mContentResolver。
@Override
public ContentResolver getContentResolver() {
return mContentResolver;
}
这个mContentResolver实际上是ContentResolver的子类ApplicationContentResolver,该对象是在ContextImpl的构造方法中创建的。
private ContextImpl(ContextImpl container, ActivityThread mainThread,
LoadedApk packageInfo, IBinder activityToken, UserHandle user, int flags,
Display display, Configuration overrideConfiguration, int createDisplayWithId) {
...
mContentResolver = new ApplicationContentResolver(this, mainThread, user);
}
获取了ContentResolver对象之后,调用它的query方法。在ContentResolver的query方法中首先会调用acquireUnstableProvider来获取一个IContentProvider对象。
在这里要说一下,返回值是IContentProvider对象,它继承自IInterface,也就是说它的实现类会是一个Binder对象。这也是因此ContentProvider不是一个Binder对象,而且一般ContentProvider和客户端不再同一个进程中。它的增删改查方法的结果肯定是需要一个通过一个Binder对象来进行IPC过程的传输。在这里就是IContentProvider。在这里它的实现是ContentProviderNative的子类ContentProvider.Transport。ContentProvider.Transport对象运行在ContentProvider的同一个进程,在远程有个特代理是ContentProviderProxy。
acquireUnstableProvider方法由ApplicationContentResolver实现,在ApplicationContentResolver中还有一个重写的方法是acquireProvider,它们都是做一个中转,调用的是ActivityThread的acquireProvider方法。
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;
}
// There is a possible race here. Another thread may try to acquire
// the same provider at the same time. When this happens, we want to ensure
// that the first one wins.
// Note that we cannot hold the lock while acquiring and installing the
// provider since it might take a long time to run and it could also potentially
// be re-entrant in the case where the provider is in the same process.
IActivityManager.ContentProviderHolder holder = null;
try {
holder = ActivityManagerNative.getDefault().getContentProvider(
getApplicationThread(), auth, userId, stable);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
if (holder == null) {
Slog.e(TAG, "Failed to find provider info for " + auth);
return null;
}
// Install provider will increment the reference count for us, and break
// any ties in the race.
holder = installProvider(c, holder, holder.info,
true /*noisy*/, holder.noReleaseNeeded, stable);
return holder.provider;
}
可以看到,它首先调用acquireExistingProvider,查看是否有缓存的IContentProvider对象,如果有的话就直接返回这个缓存对象。缓存存放在mProviderMap这个Map集合中。
// The lock of mProviderMap protects the following variables.
final ArrayMap mProviderMap
= new ArrayMap();
如果当前没有缓存的话,就需要通过一个IPC过程调用AMS的getContentProvider方法来获取一个ContentProviderHolder,ContentProviderHolder实现了Parcelable接口,因此它可以被进程间传递,它就是客户端的ContentProvider的一个代理对象的包装类。之后调用installProvider方法还要修改ContentProvider的引用计数器。
AMS的getContentProvider方法又会调用getContentProviderImpl方法,在该方法中会判断所要请求的ContentProvider进程是否已经存在,如果不存在的话就会调用startProcessLocked方法来创建ContentProvider的进程并安装ContentProvider。
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;
...
boolean checkCrossUser = true;
checkTime(startTime, "getContentProviderImpl: getProviderByName");
// First check if this content provider has been published...
cpr = mProviderMap.getProviderByName(name, userId);
// If that didn't work, check if it exists for user 0 and then
// verify that it's a singleton provider before using it.
...
boolean providerRunning = cpr != null && cpr.proc != null && !cpr.proc.killed;
...
if (!providerRunning) {
...
ProcessRecord proc = getProcessRecordLocked(
cpi.processName, cpr.appInfo.uid, false);
if (proc != null && proc.thread != null && !proc.killed) {
...
proc.thread.scheduleInstallProvider(cpi);
}
} 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);
}
}
...
}
...
return cpr != null ? cpr.newHolder(conn) : null;
}
从方法可以看出,如果ContentProvider没有在运行,而且它所在的进程没有存在的话就会调用AMS自身的startProcessLocked方法来创建进程。AMS的startProcessLocked会调用Process的start方法,在该方法表明所要启动一个新进程,并且调用android.app.ActivityThread的main方法作为入口。
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
...
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
boolean isActivityProcess = (entryPoint == null);
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
checkTime(startTime, "startProcess: asking zygote to start proc");
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);
...
}
App进程启动的流程如下,这里我们就不细讲了。
最终ActivityThread的main方法会被调用,该方法中会创建ActivityThread对象,并创建主线程的Looper对象,调用ActivityThread的attach方法,并且传递的参数为false,表明不是系统进程。之后就开始消息循环了。
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("");
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
在ActivityThread的attach方法中,会通过一个IPC过程调用AMS的attachApplication方法。
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
...
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
...
} else {
...
}
...
}
AMS的attachApplication方法又会调用其attachApplicationLocked方法,在该方法中又会通过IPC过程调用ApplicationThread的bindApplication方法。
public final void bindApplication(String processName, ApplicationInfo appInfo,
List providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map services, Bundle coreSettings) {
if (services != null) {
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
setCoreSettings(coreSettings);
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableBinderTracking = enableBinderTracking;
data.trackAllocation = trackAllocation;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
sendMessage(H.BIND_APPLICATION, data);
}
AppBindData是一个JavaBean独享,用于ActivityThreadThread绑定的App的信息。
ApplicationThread的bindApplication方法是在Binder线程池中执行,因此通过一个Handler发送
H.BIND_APPLICATION消息切换到主线程。在Handler H的handleMessage方法中会从msg中取出AppBindData对象,并且调用ActivityThread的handleBindApplication方法。
在这里面做了5步操作:
- 创建ContextImpl对象
- 创建Instrumentation对象
- 创建Application对象
- 调用
installContentProviders(app, data.providers)
方法启动当前进程的ContentProvider并调用其onCreate方法 - 调用Application的onCreate方法
private void handleBindApplication(AppBindData data) {
...
// If the app is Honeycomb MR1 or earlier, switch its AsyncTask
// implementation to use the pool executor. Normally, we use the
// serialized executor as the default. This has to happen in the
// main thread so the main looper is set right.
if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
...
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
...
// Instrumentation info affects the class loader, so load it before
// setting up the app context.
final InstrumentationInfo ii;
if (data.instrumentationName != null) {
try {
ii = new ApplicationPackageManager(null, getPackageManager())
.getInstrumentationInfo(data.instrumentationName, 0);
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException(
"Unable to find instrumentation info for: " + data.instrumentationName);
}
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;
}
// 1 创建 ContextImpl对象
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
...
// 2 创建Instrumentation对象
// Continue loading instrumentation.
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();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate instrumentation "
+ data.instrumentationName + ": " + e.toString(), e);
}
final ComponentName component = new ComponentName(ii.packageName, ii.name);
mInstrumentation.init(this, instrContext, appContext, component,
data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
...
}
} else {
mInstrumentation = new Instrumentation();
}
...// 3 创建 Applcation对象
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
// 4 启动当前进程的ContentProvider,并调用其方法
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
installContentProviders(app, data.providers);
// For process that contains content providers, we want to
// ensure that the JIT is enabled "at some point".
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}
// Do this after providers, since instrumentation tests generally start their
// test thread at this point, and we don't want that racing.
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
... // 5 调用Application的onCreate方法
try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
...
}
}
我们来看一下ActivityThread的installContentProviders方法。在该方法中主要遍历当前进程的ProviderInfo信息,通过调用installProvider方法来构建一个IActivityManager.ContentProviderHolder对象。
private void installContentProviders(
Context context, List providers) {
final ArrayList results =
new ArrayList();
for (ProviderInfo cpi : providers) {
if (DEBUG_PROVIDER) {
StringBuilder buf = new StringBuilder(128);
buf.append("Pub ");
buf.append(cpi.authority);
buf.append(": ");
buf.append(cpi.name);
Log.i(TAG, buf.toString());
}
IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
if (cph != null) {
cph.noReleaseNeeded = true;
results.add(cph);
}
}
try {
ActivityManagerNative.getDefault().publishContentProviders(
getApplicationThread(), results);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
还记得我们之前说的吗,ContentProvider对象是无法跨进程调用的,因此需要一个Binder对象用于给客户端使用。ContentProviderHolder实现了Pacelable接口,可以在进程间传递数据。它实际上就是一个JavaBean对象,但是里面封装了IContentProvider,它实际上会作为一个Binder对象用于进程间方法的调用。我们前面也已经提了。IContentProvider的实现是ContentProviderNative的子类ContentProvider.Transport。ContentProvider.Transport对象运行在ContentProvider的同一个进程,在远程有个特代理是ContentProviderProxy。
public static class ContentProviderHolder implements Parcelable {
public final ProviderInfo info;
public IContentProvider provider;
public IBinder connection;
public boolean noReleaseNeeded;
...
}
我们来看一下ActivityThread的installProvider方法,可以看到首先通过类加载器创建了ContentProvider对象,然后调用了ContentProvider的attachInfo方法。
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);
} catch (PackageManager.NameNotFoundException e) {
// Ignore
}
}
...
try {
final java.lang.ClassLoader cl = c.getClassLoader();
localProvider = (ContentProvider)cl.
loadClass(info.name).newInstance();
provider = localProvider.getIContentProvider();
...
// XXX Need to create the correct context for this provider.
localProvider.attachInfo(c, info);
} catch (java.lang.Exception e) {
...
}
} else {
provider = holder.provider;
if (DEBUG_PROVIDER) Slog.v(TAG, "Installing external provider " + info.authority + ": "
+ info.name);
}
...
return retHolder;
}
我们再来看一下ContentProvider的attachInfo方法,该方法会调用3个参数的重载方法,在该方法中调用了ContextProvider的onCreate方法。
private void attachInfo(Context context, ProviderInfo info, boolean testing) {
mNoPerms = testing;
/*
* Only allow it to be set once, so after the content service gives
* this to us clients can't change it.
*/
if (mContext == null) {
mContext = context;
if (context != null) {
mTransport.mAppOpsManager = (AppOpsManager) context.getSystemService(
Context.APP_OPS_SERVICE);
}
mMyUid = Process.myUid();
if (info != null) {
setReadPermission(info.readPermission);
setWritePermission(info.writePermission);
setPathPermissions(info.pathPermissions);
mExported = info.exported;
mSingleUser = (info.flags & ProviderInfo.FLAG_SINGLE_USER) != 0;
setAuthorities(info.authority);
}
ContentProvider.this.onCreate();
}
}
我们上面的分析可知,ContentProvider的onCreate方法是在Application的onCreate方法之前调用的。当然了,还是要晚于Application的attachBaseContext方法。
ContentProvider创建完毕并启动之后还没有完事,会通过一个IPC过程调用AMS的publishContentProviders方法,此时传递ApplicationThread对象和创建完毕的ContentProviderHolder集合。publishContentProviders方法中也即是在AMS端存一下ContentProvider的记录,这里就不再细说了。
到此,ContentProvider所在的进程已经创建完毕,并且ContentProvider也已经全部启动起来。但是还没有完,调起ContentResolver发起query方法的那边还在等着返回结果呢。回到ContentResolver的query方法。注意此时客户端获取的IContentProvider对象是ContentProviderProxy,它是ContentProviderNative的内部类,通过IPC过程调用到ContentProviderNative.ContentProvider.Transport中。
# android.content.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);
if (unstableProvider == null) {
return null;
}
IContentProvider stableProvider = null;
Cursor qCursor = null;
try {
...
try {
qCursor = unstableProvider.query(mPackageName, uri, projection,
selection, selectionArgs, sortOrder, remoteCancellationSignal);
} catch (DeadObjectException e) {
// The remote process has died... but we only hold an unstable
// reference though, so we might recover!!! Let's try!!!!
// This is exciting!!1!!1!!!!1
unstableProviderDied(unstableProvider);
stableProvider = acquireProvider(uri);
if (stableProvider == null) {
return null;
}
qCursor = stableProvider.query(mPackageName, uri, projection,
selection, selectionArgs, sortOrder, remoteCancellationSignal);
}
if (qCursor == null) {
return null;
}
// Force query execution. Might fail and throw a runtime exception here.
qCursor.getCount();
long durationMillis = SystemClock.uptimeMillis() - startTime;
maybeLogQueryToEventLog(durationMillis, uri, projection, selection, sortOrder);
// Wrap the cursor object into CursorWrapperInner object.
final IContentProvider provider = (stableProvider != null) ? stableProvider
: acquireProvider(uri);
final CursorWrapperInner wrapper = new CursorWrapperInner(qCursor, provider);
stableProvider = null;
qCursor = null;
return wrapper;
...
}
再来看一下ContentProvider.Transport的query方法,由于ContentProvider.Transport是非静态内部类,因此持有ContentProvider的引用,所以内部调用了ContentProvider的query方法的返回值,返回的结果也会通过一个IPC过程返回到调用者那里。ContentProvider对外提供数据的方法,query、insert、delete、update方法也都是通过Transport进行调用的。
# android.content.ContentProvider.Transport
@Override
public Cursor query(String callingPkg, Uri uri, String[] projection,
String selection, String[] selectionArgs, String sortOrder,
ICancellationSignal cancellationSignal) {
validateIncomingUri(uri);
uri = getUriWithoutUserId(uri);
if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
// The caller has no access to the data, so return an empty cursor with
// the columns in the requested order. The caller may ask for an invalid
// column and we would not catch that but this is not a problem in practice.
// We do not call ContentProvider#query with a modified where clause since
// the implementation is not guaranteed to be backed by a SQL database, hence
// it may not handle properly the tautology where clause we would have created.
if (projection != null) {
return new MatrixCursor(projection, 0);
}
// Null projection means all columns but we have no idea which they are.
// However, the caller may be expecting to access them my index. Hence,
// we have to execute the query as if allowed to get a cursor with the
// columns. We then use the column names to return an empty cursor.
Cursor cursor = ContentProvider.this.query(uri, projection, selection,
selectionArgs, sortOrder, CancellationSignal.fromTransport(
cancellationSignal));
if (cursor == null) {
return null;
}
// Return an empty cursor for all columns.
return new MatrixCursor(cursor.getColumnNames(), 0);
}
final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.query(
uri, projection, selection, selectionArgs, sortOrder,
CancellationSignal.fromTransport(cancellationSignal));
} finally {
setCallingPackage(original);
}
}
总结
访问一个ContentProvider需要用到ContentResolver对象,它是一个抽象类,实际上用的是它的实现类ContextImpl的ApplicationContentResolver。
访问ContextProvider时一个IPC过程,由于ContentProvider不能跨进程访问。调用ContentResolver的query等方法首先需要从AMS端获取一个ContextProvider的代理对象,这个代理对象实现了IContentProvider接口,它用于代理远端的Binder对象ContextProvider.Trasnport。ContextProvider.Trasnport继承自ContentProviderNative,ContentProviderNative实现了IContentProvider接口。通过ContextProvider.Trasnport的本地代理对象,可以调用ContextProvider.Trasnport的query方法,Trasnport是ContextProvider的内部类,持有ContextProvider的引用,它再去调用ContextProvider的方法并通过IPC过程返回结果。
第一次访问ContentProvider的时候,如果它还没有创建,AMS会通过startProcessLock方法调用Process的start方法,通过Zygote去fork一个进程之后调用ActivityThread的main方法,在main方法中创建ActivityThread对象,并调用其attach方法,在此过程创建了Instrumentation对象、Application对象,并创建该进程中对应的ContentProvider并调用其onCreate方法,此后调用Application的onCreate方法,因此ContentProvider的onCreate方法早于Application的onCreate方法执行,这也是四大组件中唯一一个比较特别的。