ContentProvider是Android中的四大组件之一,它主要是用作进程间共享数据,虽然这个组件在平时用的很少,但是它的设计思想还是很值得学习的,下面就以调用query方法查询数据的过程为例来分析下ContentProvider的工作过程,在代码中的使用方式还是比较简单的,直接通过调用 getContentResolver方法获取一个ContentResolver对象,然后在调用ContentResolver对象的query方法(传入uri等查询参数)就会返回一个Cursor数据集,下面分析下这个调用过程是怎么样的,getContentResolver()会调用到ContextWrapper的getContentResolver方法:
@Override
public ContentResolver getContentResolver() {
return mBase.getContentResolver();
}
上述代码中mBase的实现类是ContextImpl,ContextImpl的getContentResolver方法如下:
private final ApplicationContentResolver mContentResolver;
@Override
public ContentResolver getContentResolver() {
return mContentResolver;
}
由上面的代码可以知道getContentResolver方法返回的对象是ApplicationContentResolver类型的mContentResolver,ApplicationContentResolver的父类是ContentResolver,query方法的具体实现是在父类中进行实现的,所以调用getContentResolver的query方法,最终是会调用到父类ContentResolver的query方法中的:
public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri,
@Nullable String[] projection, @Nullable Bundle queryArgs,
@Nullable CancellationSignal cancellationSignal) {
Preconditions.checkNotNull(uri, "uri");
//注释1
IContentProvider unstableProvider = acquireUnstableProvider(uri);
if (unstableProvider == null) {
return null;
}
......
//注释2
qCursor = unstableProvider.query(mPackageName, uri, projection,
queryArgs, remoteCancellationSignal);
......
}
在注释1处调用了acquireUnstableProvider方法返回一个IContentProvider类型的对象,这是一个binder代理对象,其真实实现是ContentProvider,然后在注释2处调用了unstableProvider的query方法返回一个结果集qCurso,下面跟下acquireUnstableProvider方法:
public final IContentProvider acquireUnstableProvider(Uri uri) {
if (!SCHEME_CONTENT.equals(uri.getScheme())) {//注释3
return null;
}
String auth = uri.getAuthority();
if (auth != null) {
return acquireUnstableProvider(mContext, uri.getAuthority());//注释4
}
return null;
}
在注释3处判断一下uri的scheme是否是“content”,如果不是就直接返回null,如果是就在注释4处调用其重载方法acquireUnstableProvider(Context c, String name),这个方法是一个抽象方法,具体实现是在子类ApplicationContentResolver类中:
private final ActivityThread mMainThread;
@Override
protected IContentProvider acquireUnstableProvider(Context c, String auth) {
//注释5
return mMainThread.acquireProvider(c,
ContentProvider.getAuthorityWithoutUserId(auth),
resolveUserIdFromAuthority(auth), false);
}
在注释5处调用了ActivityThread的acquireProvider方法,跟进去这个方法:
public final IContentProvider acquireProvider(
Context c, String auth, int userId, boolean stable) {
//注释6
final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
if (provider != null) {
return provider;
}
ContentProviderHolder holder = null;
try {
synchronized (getGetProviderLock(auth, userId)) {
//注释7
holder = ActivityManager.getService().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;
}
//注释8
holder = installProvider(c, holder, holder.info,
true /*noisy*/, holder.noReleaseNeeded, stable);
return holder.provider;
}
由注释6处可知,如果从缓存中查询到了相对应的provider就直接返回,否则就在注释7处AMS中去创建获取,注释8处会将AMS返回的provider缓存起来,下次在获取就不需要重新创建了,第一次启动provider是不存在的,就会走注释7处的代码,调用AMS的getContentProvider方法获取,在AMS的getContentProvider方法中会调用getContentProviderImpl方法,继续跟踪源码如下:
private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
String name, IBinder token, boolean stable, int userId) {
.........................
if (proc != null && proc.thread != null && !proc.killed) {
if (DEBUG_PROVIDER) Slog.d(TAG_PROVIDER,
"Installing in existing process " + proc);
if (!proc.pubProviders.containsKey(cpi.name)) {
checkTime(startTime, "getContentProviderImpl: scheduling install");
proc.pubProviders.put(cpi.name, cpr);
try {
//注释9
proc.thread.scheduleInstallProvider(cpi);
} catch (RemoteException e) {
}
}
} else {
checkTime(startTime, "getContentProviderImpl: before start process");
//注释10
proc = startProcessLocked(cpi.processName,
cpr.appInfo, false, 0, "content provider",
new ComponentName(cpi.applicationInfo.packageName,
cpi.name), false, false, false);
checkTime(startTime, "getContentProviderImpl: after start process");
if (proc == null) {
Slog.w(TAG, "Unable to launch app "
+ cpi.applicationInfo.packageName + "/"
+ cpi.applicationInfo.uid + " for provider "
+ name + ": process is bad");
return null;
}
}
.........................
}
如果ContentProvider所在的进程存在,就会执行注释9处的代码这种情况这里不进行展开分析了,如果所在的进程不存在,就会执行注释10处的代码去创建ContentProvider所在的进程,调用注释10处的startProcessLocked方法最终会调用到它的重载方法:
private final boolean startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) {
...................
final String entryPoint = "android.app.ActivityThread";
//注释11
return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids,
runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
startTime);
...................
}
继续跟踪注释11处startProcessLocked方法的调用,会调用到startProcess方法:
private ProcessStartResult startProcess(String hostingType, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
...................
//注释12
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
...................
}
在上述注释12处会调用Process的start方法,该方法的第一个参数entryPoint就是ActivityThread的全类名字符串 “android.app.ActivityThread”。 Process的start方法又会调用ZygoteProcess的start方法,在接着又会调用ZygoteProcess的startViaZygote方法:
private Process.ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
boolean startChildZygote,
String[] extraArgs)
throws ZygoteStartFailedEx {
ArrayList<String> argsForZygote = new ArrayList<String>();
//注释13
argsForZygote.add(processClass);
if (extraArgs != null) {
for (String arg : extraArgs) {
argsForZygote.add(arg);
}
}
synchronized(mLock) {
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}
由注释13可知,会将processClass( 就是"android.app.ActivityThread")添加到argsForZygote列表中,然后调用ZygoteProcess的zygoteSendArgsAndGetResult方法,并将argsForZygote作为zygoteSendArgsAndGetResult方法的参数:
@GuardedBy("mLock")
private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
try {
// Throw early if any of the arguments are malformed. This means we can
// avoid writing a partial response to the zygote.
int sz = args.size();
for (int i = 0; i < sz; i++) {
if (args.get(i).indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx("embedded newlines not allowed");
}
}
//注释14
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;
writer.write(Integer.toString(args.size()));
writer.newLine();
for (int i = 0; i < sz; i++) {
String arg = args.get(i);
writer.write(arg);
writer.newLine();
}
writer.flush();
// Should there be a timeout on this?
Process.ProcessStartResult result = new Process.ProcessStartResult();
// Always read the entire result from the input stream to avoid leaving
// bytes in the stream for future process starts to accidentally stumble
// upon.
result.pid = inputStream.readInt();
result.usingWrapper = inputStream.readBoolean();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}
在注释14处将argsForZygote参数信息写入到 zygoteState中,zygoteState是由openZygoteSocketIfNeeded方法返回的,看下openZygoteSocketIfNeeded方法:
@GuardedBy("mLock")
private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held");
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
try {
primaryZygoteState = ZygoteState.connect(mSocket);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
}
maybeSetApiBlacklistExemptions(primaryZygoteState, false);
maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
}
if (primaryZygoteState.matches(abi)) {
return primaryZygoteState;
}
// The primary zygote didn't match. Try the secondary.
if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
try {
secondaryZygoteState = ZygoteState.connect(mSecondarySocket);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
}
maybeSetApiBlacklistExemptions(secondaryZygoteState, false);
maybeSetHiddenApiAccessLogSampleRate(secondaryZygoteState);
}
if (secondaryZygoteState.matches(abi)) {
return secondaryZygoteState;
}
throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}
通过上面这个方法可知,ZygoteState通过mSocket连接Zygote进程进行通信(系统启动的时候,Zygote进程会有一个Socket等待着接收AMS发送的请求),Zygote进程收到AMS发送的socket消息会fock一个新的进程作为应用程序进程,然后会调用ZygoteInit类的zygoteInit方法,然后在去调用应用程序进程的入口方法启动该进程:
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
RuntimeInit.commonInit();
ZygoteInit.nativeZygoteInit();
//注释15
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
在注释15处调用了RuntimeInit的applicationInit方法,在applicationInit中又调用了findStaticMain方法:
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
try {
//注释16
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
//注释17
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
//注释18
return new MethodAndArgsCaller(m, argv);
}
在注释16处获取className对应的Class类,其中className就是AMS通过socket写给Zygote的,这个参数的值就是 “android.app.ActivityThread”,然后在注释17处获取main方法,也就是ActivityThread中的main方法,然后在注释18处去调用ActivityThread的main方法,这样应用程序的入口函数就被调用了,也就是说应用程序进程被创建并启动了。下面看下ActivityThread的main方法:
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
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("<pre-initialized>");
Looper.prepareMainLooper();
// Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
// It will be in the format "seq=114"
long startSeq = 0;
if (args != null) {
for (int i = args.length - 1; i >= 0; --i) {
if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
startSeq = Long.parseLong(
args[i].substring(PROC_START_SEQ_IDENT.length()));
}
}
}
//注释19
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
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);
//注释20
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
注释19处创建了ActivityThread实例,并调用其attach方法,注释20处开启主线程的消息循环,跟进去attach方法:
private void attach(boolean system, long startSeq) {
...................
final IActivityManager mgr = ActivityManager.getService();
try {
//注释21
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
...................
}
在注释21处,调用了AMS的attachApplication方法,并将ApplicationThread作为参数传递了给了AMS,AMS的attachApplication方法:
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
//注释22
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
Binder.restoreCallingIdentity(origId);
}
}
在注释22处又调用了AMS的attachApplicationLocked方法,在这个方法中又调用了thread的bindApplication方法,thread是IApplicationThread类型的,IApplicationThread的具体实现是ApplicationThread类,那么ApplicationThread的bindApplication具体实现是:
public final void bindApplication(String processName, ApplicationInfo appInfo,
List<ProviderInfo> 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,
String buildSerial, boolean autofillCompatibilityEnabled) {
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;
data.buildSerial = buildSerial;
data.autofillCompatibilityEnabled = autofillCompatibilityEnabled;
//注释23
sendMessage(H.BIND_APPLICATION, data);
}
}
在bindApplication方法中,将包名等App信息封装为AppBindData数据,在注释23处发送一个handler消息给H处理,H类中收到BIND_APPLICATION的消息,会调用ActivityThread的handleBindApplication方法:
private void handleBindApplication(AppBindData data) {
Application app;
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
try {
// If the app is being launched for full backup or restore, bring it up in
// a restricted environment with the base application class.
//注释24
app = data.info.makeApplication(data.restrictedBackupMode, null);
// Propagate autofill compat state
app.setAutofillCompatibilityEnabled(data.autofillCompatibilityEnabled);
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)) {
//注释25
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);
}
catch (Exception e) {
throw new RuntimeException(
"Exception thrown in onCreate() of "
+ data.instrumentationName + ": " + e.toString(), e);
}
try {
//注释26
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
} finally {
// If the app targets < O-MR1, or doesn't change the thread policy
// during startup, clobber the policy to maintain behavior of b/36951662
if (data.appInfo.targetSdkVersion < Build.VERSION_CODES.O_MR1
|| StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) {
StrictMode.setThreadPolicy(savedPolicy);
}
}
}
注释24处创建了Application,并在注释26处调用了Application的onCreate方法,说明进程已经创建并启动,注释25处调用installContentProviders来启动ContentProvider,代码如下:
private void installContentProviders(
Context context, List<ProviderInfo> providers) {
final ArrayList<ContentProviderHolder> results = new ArrayList<>();
//注释27
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());
}
//注释28
ContentProviderHolder cph = installProvider(context, null, cpi,
false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
if (cph != null) {
cph.noReleaseNeeded = true;
results.add(cph);
}
}
try {
//注释29
ActivityManager.getService().publishContentProviders(
getApplicationThread(), results);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
注释27处会遍历该进程中所有的ProviderInfo信息,在循环体中,根据ProviderInfo信息,通过注释28处的代码将每个Provider进行启动,注释29处将Provider发布到AMS中的ProviderMap里保存起来,下面看下注释28处的installProvider方法:
private ContentProviderHolder installProvider(Context context,
ContentProviderHolder holder, ProviderInfo info,
boolean noisy, boolean noReleaseNeeded, boolean stable) {
ContentProvider localProvider = null;
IContentProvider provider;
Context c = null;
//注释30
final java.lang.ClassLoader cl = c.getClassLoader();
localProvider = packageInfo.getAppFactory()
.instantiateProvider(cl, info.name);
provider = localProvider.getIContentProvider();
localProvider.attachInfo(c, info);
}
在注释30处创建了Provider,并在 localProvider.attachInfo方法中调用Provider的onCreate方法,说明Provider已经启动成功:
private void attachInfo(Context context, ProviderInfo info, boolean testing) {
ContentProvider.this.onCreate();
}
}
本文详细解析了Android中ContentProvider的启动流程,从调用getContentResolver开始,深入探讨了query方法的内部实现,包括如何通过binder代理对象调用ContentProvider的query方法,以及AMS在其中的作用。此外,还分析了ContentProvider所在进程的创建过程,涉及Zygote进程的通信机制和ActivityThread的初始化。
1150

被折叠的 条评论
为什么被折叠?



