getContentResolver()
我们在Application或者Activity里调用bindService()的时候,其实调用的是Context中的抽象方法:
public abstract ContentResolver getContentResolver();
复制代码
真正的是现在ContextImpl中:
private final ApplicationContentResolver mContentResolver;
...
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);
}
...
@Override
public ContentResolver getContentResolver() {
return mContentResolver;
}
复制代码
在构造方法中通过ActivityThread构造了ApplicationContentResolver类型的对象。这个对象是ActivityThread和UserHandle的包装类。
private static final class ApplicationContentResolver extends ContentResolver {
private final ActivityThread mMainThread;
private final UserHandle mUser;
...
}
复制代码
获取到ContentResolver之后就可以进行query、insert、delete、update操作。
query()
public final Cursor query(final Uri uri, String[] projection,
String selection, String[] selectionArgs, String sortOrder,
CancellationSignal cancellationSignal) {
//1、获取IContentProvider接口对象
IContentProvider unstableProvider = acquireUnstableProvider(uri);
if (unstableProvider == null) {
return null;
}
IContentProvider stableProvider = null;
Cursor qCursor = null;
try {
....
try {
//2、通过获取的IContentProvider查询数据,并返回Cursor对象,在这里会线程阻塞
qCursor = unstableProvider.query(mPackageName, uri, projection,
selection, selectionArgs, sortOrder, remoteCancellationSignal);
} catch (DeadObjectException e) {
//在第2步调用过程中,远程进程已经死亡,试图恢复连接
unstableProviderDied(unstableProvider);
//连接后重新获取provider
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);
// 将返回的Cursor对象包装成CursorWrapperInner
CursorWrapperInner wrapper = new CursorWrapperInner(qCursor,
stableProvider != null ? stableProvider : acquireProvider(uri));
stableProvider = null;
qCursor = null;
return wrapper;
} catch (RemoteException e) {
return null;
} finally {
if (qCursor != null) {
qCursor.close();
}
if (cancellationSignal != null) {
cancellationSignal.setRemote(null);
}
if (unstableProvider != null) {
releaseUnstableProvider(unstableProvider);
}
if (stableProvider != null) {
releaseProvider(stableProvider);
}
}
}
复制代码
通过acquireUnstableProvider方法获取了IContentProvider对象:
//常量
public static final String SCHEME_CONTENT = "content";
//获取IContentProvider
public final IContentProvider acquireUnstableProvider(Uri uri) {
//这里判断uri的scheme是否是content,就是我们写的uri是否是以
//content://开头的
if (!SCHEME_CONTENT.equals(uri.getScheme())) {
return null;
}
//判断authorities是否为空
String auth = uri.getAuthority();
if (auth != null) {
//如果不为空直接return了acquireUnstableProvider方法
return acquireUnstableProvider(mContext, uri.getAuthority());
}
return null;
}
复制代码
看看acquireUnstableProvider()方法实现:
protected abstract IContentProvider acquireUnstableProvider(Context c, String name);
复制代码
是抽象方法,具体实现在刚刚创建的ApplicationContentResolver:
@Override
protected IContentProvider acquireUnstableProvider(Context c, String auth) {
return mMainThread.acquireProvider(c,
ContentProvider.getAuthorityWithoutUserId(auth),
resolveUserIdFromAuthority(auth), false);
}
复制代码
看看ActivityThread中的具体实现:
public final IContentProvider acquireProvider(
Context c, String auth, int userId, boolean stable) {
//1.查看是否有缓存的IContentProvider,命中直接返回
final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
if (provider != null) {
return provider;
}
//通过AMS获取了被调用provider的信息
IActivityManager.ContentProviderHolder holder = null;
try {
holder = ActivityManagerNative.getDefault().getContentProvider(
getApplicationThread(), auth, userId, stable);
} catch (RemoteException ex) {
}
if (holder == null) {
Slog.e(TAG, "Failed to find provider info for " + auth);
return null;
}
// 加载provider并保存
holder = installProvider(c, holder, holder.info,
true /*noisy*/, holder.noReleaseNeeded, stable);
//返回holder.provider
return holder.provider;
}
复制代码
ActivityManagerNative.getDefault()返回的是AMS的代理类,最终会通过BInder机制调用到AMS:
@Override
public final ContentProviderHolder getContentProvider(
IApplicationThread caller, String name, int userId, boolean stable) {
//如果IApplicationThread 为空直接抛异常了
enforceNotIsolatedCaller("getContentProvider");
if (caller == null) {
String msg = "null IApplicationThread when getting content provider "
+ name;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
//返回getContentProviderImpl方法
return getContentProviderImpl(caller, name, null, stable, userId);
}
复制代码
在AMS中,看getContentProviderImpl方法:
private final ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
String name, IBinder token, boolean stable, int userId) {
//用来保存provider的信息
ContentProviderRecord cpr;
ContentProviderConnection conn = null;
ProviderInfo cpi = null;
synchronized(this) {
long startTime = SystemClock.elapsedRealtime();
//获取调用者的进程信息
ProcessRecord r = null;
if (caller != null) {
r = getRecordForAppLocked(caller);
if (r == null) {
throw new SecurityException(
"Unable to find app for caller " + caller
+ " (pid=" + Binder.getCallingPid()
+ ") when getting content provider " + name);
}
}
boolean checkCrossUser = true;
checkTime(startTime, "getContentProviderImpl: getProviderByName");
// 查看provider信息是否被加载过,是否存在缓存
cpr = mProviderMap.getProviderByName(name, userId);
// If that didn't work, check if it exists for user and then
// verify that it's a singleton provider before using it.
if (cpr == null && userId != UserHandle.USER_OWNER) {
cpr = mProviderMap.getProviderByName(name, UserHandle.USER_OWNER);
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_OWNER;
checkCrossUser = false;
} else {
cpr = null;
cpi = null;
}
}
}
//这里如果是第一次调用肯定是不会命中缓存
boolean providerRunning = cpr != null;
if (providerRunning) {
//如果命中缓存
cpi = cpr.info;
String msg;
checkTime(startTime, "getContentProviderImpl: before checkContentProviderPermission");
if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, checkCrossUser))
!= null) {
throw new SecurityException(msg);
}
checkTime(startTime, "getContentProviderImpl: after checkContentProviderPermission");
//判断provider的multiprocess是否为true,如果是true,provider则会在调用者的进程中初始化,
//multiprocess默认为false,默认系统只有一个该provider
if (r != null && cpr.canRunHere(r)) {
ContentProviderHolder holder = cpr.newHolder(null);
holder.provider = null;
return holder;
}
....
}
boolean singleton;
//没有命中缓存
if (!providerRunning) {
try {
checkTime(startTime, "getContentProviderImpl: before resolveContentProvider");
//通过PackageManagerService得到provider所在应用程序的信息
cpi = AppGlobals.getPackageManager().
resolveContentProvider(name,
STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId);
checkTime(startTime, "getContentProviderImpl: after resolveContentProvider");
} catch (RemoteException ex) {
}
if (cpi == null) {
return null;
}
.....
//检查权限
if ((msg = checkContentProviderPermissionLocked(cpi, r, userId, !singleton))
!= null) {
throw new SecurityException(msg);
}
....
ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
checkTime(startTime, "getContentProviderImpl: before getProviderByClass");
//判断provider这个类是否是第一次加载
cpr = mProviderMap.getProviderByClass(comp, userId);
checkTime(startTime, "getContentProviderImpl: after getProviderByClass");
final boolean firstClass = cpr == null;
if (firstClass) {
final long ident = Binder.clearCallingIdentity();
try {
checkTime(startTime, "getContentProviderImpl: before getApplicationInfo");
//获取provider的Application信息
ApplicationInfo ai =
AppGlobals.getPackageManager().
getApplicationInfo(
cpi.applicationInfo.packageName,
STOCK_PM_FLAGS, userId);
checkTime(startTime, "getContentProviderImpl: after getApplicationInfo");
if (ai == null) {
Slog.w(TAG, "No package info for content provider "
+ cpi.name);
return null;
}
ai = getAppInfoForUser(ai, userId);
//创建provider的信息
cpr = new ContentProviderRecord(this, cpi, ai, comp, singleton);
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
} finally {
Binder.restoreCallingIdentity(ident);
}
}
checkTime(startTime, "getContentProviderImpl: now have ContentProviderRecord");
//判断provider的multiprocess是否为true,如果是true,provider则会在调用者的进程中初始化,
//multiprocess默认为false,默认系统只有一个该provider
if (r != null && cpr.canRunHere(r)) {
// If this is a multiprocess provider, then just return its
// info and allow the caller to instantiate it. Only do
// this if the provider is the same user as the caller's
// process, or can run as root (so can be in any process).
return cpr.newHolder(null);
}
if (DEBUG_PROVIDER) {
RuntimeException e = new RuntimeException("here");
Slog.w(TAG, "LAUNCHING REMOTE PROVIDER (myuid " + (r != null ? r.uid : null)
+ " pruid " + cpr.appInfo.uid + "): " + cpr.info.name, e);
}
//因为multiprocess所以会继续走到这里,系统中所有的provider都会存储在mLaunchingProviders
//的ArrayList中,以为默认系统只能有一个该provider的实例,这里是看一下是否有其他的应用已经
//实例了该provider,如果是肯定会存在mLaunchingProviders,那么i也就肯定小于N
final int N = mLaunchingProviders.size();
int i;
for (i=; i= N) {
final long origId = Binder.clearCallingIdentity();
try {
....
//查看provider所属进程是否已经存在
ProcessRecord proc = getProcessRecordLocked(
cpi.processName, cpr.appInfo.uid, false);
//判断该进程是否已经启动了
if (proc != null && proc.thread != null) {
if (DEBUG_PROVIDER) {
Slog.d(TAG, "Installing in existing process " + proc);
}
checkTime(startTime, "getContentProviderImpl: scheduling install");
proc.pubProviders.put(cpi.name, cpr);
try {
//使用ApplicationThread发送一条消息,加载provider,一会再分析
proc.thread.scheduleInstallProvider(cpi);
} catch (RemoteException e) {
}
} else {
//如果进程没有创建则创建一个新的进程
proc = startProcessLocked(cpi.processName,
cpr.appInfo, false, , "content provider",
new ComponentName(cpi.applicationInfo.packageName,
cpi.name), false, false, false);
if (proc == null) {
Slog.w(TAG, "Unable to launch app "
+ cpi.applicationInfo.packageName + "/"
+ cpi.applicationInfo.uid + " for provider "
+ name + ": process is bad");
return null;
}
}
//将该provider的信息保存到mLaunchingProviders中
cpr.launchingApp = proc;
mLaunchingProviders.add(cpr);
} finally {
Binder.restoreCallingIdentity(origId);
}
}
checkTime(startTime, "getContentProviderImpl: updating data structures");
//存入provider的信息
if (firstClass) {
mProviderMap.putProviderByClass(comp, cpr);
}
mProviderMap.putProviderByName(name, cpr);
conn = incProviderCountLocked(r, cpr, token, stable);
if (conn != null) {
conn.waiting = true;
}
}
}
.....
//返回provider的信息封装成ContentProviderHolder返回
return cpr != null ? cpr.newHolder(conn) : null;
}
复制代码
- 首先判断了被调用的provider是否之前已经存在,然后判断了multiprocess属性是否为true,如果为true将允许在调用者的进程中实例该provider,还判断了该provider所属进程是否已经被创建,如果创建直接使用ApplicationThread发送消息加载provider,如果没有创建则先创建一个进程
- 创建新进程调用了AMS中的方法startProcessLocked
- 真正创建进程的是通过Process的start的方法
- 创建被创建后会调用该进程的ActivityThread的main方法
- 然后接着调用ActivityThread.attach方法
- 在attach中会调用ActivityManagerService.attachApplication
- 在AMS的attachApplication方法中会获取需要在本进程中加载的provider,
- AMS会调用ActivityThread.bindApplication方法
- bindApplication方法中会发送一个消息到ActivityThread中的Handler里
- ActivityThread中的Handler中调用了 handleBindApplication,我们从这里开始
private void handleBindApplication(AppBindData data) {
....
//创建上下文对象
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
....
//准备初始化的数据
if (data.instrumentationName != null) {
InstrumentationInfo ii = null;
try {
ii = appContext.getPackageManager().
getInstrumentationInfo(data.instrumentationName, );
} catch (PackageManager.NameNotFoundException e) {
}
if (ii == null) {
throw new RuntimeException(
"Unable to find instrumentation info for: "
+ data.instrumentationName);
}
mInstrumentationPackageName = ii.packageName;
mInstrumentationAppDir = ii.sourceDir;
mInstrumentationSplitAppDirs = ii.splitSourceDirs;
mInstrumentationLibDir = ii.nativeLibraryDir;
mInstrumentedAppDir = data.info.getAppDir();
mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
mInstrumentedLibDir = data.info.getLibDir();
//准备创建Application的数据
ApplicationInfo instrApp = new ApplicationInfo();
instrApp.packageName = ii.packageName;
instrApp.sourceDir = ii.sourceDir;
instrApp.publicSourceDir = ii.publicSourceDir;
instrApp.splitSourceDirs = ii.splitSourceDirs;
instrApp.splitPublicSourceDirs = ii.splitPublicSourceDirs;
instrApp.dataDir = ii.dataDir;
instrApp.nativeLibraryDir = ii.nativeLibraryDir;
//LoadedApk对象是APK文件在内存中的表示。 //Apk文件的相关信息,诸如Apk文件的代码和资源,甚至代码里面的Activity,Service等四大组件的信息我们都可以通过此对象获取
LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
//创建新进程的Context
ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
try {
//创建Instrumentation对象
java.lang.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);
}
//初始化Instrumentation
mInstrumentation.init(this, instrContext, appContext,
new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher,
data.instrumentationUiAutomationConnection);
....
} else {
mInstrumentation = new Instrumentation();
}
....
try {
//通过创建Application并回调Application的attach方法
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
if (!data.restrictedBackupMode) {
List providers = data.providers;
if (providers != null) {
//加载provider
installContentProviders(app, providers);
// For process that contains content providers, we want to
// ensure that the JIT is enabled "at some point".
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, *);
}
}
try {
//回调Application的OnCreate方法
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 {
StrictMode.setThreadPolicy(savedPolicy);
}
}
复制代码
加载ContentProvider的方法installContentProviders():
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 {
//通知AMS,ContentProvider已经加载完成
ActivityManagerNative.getDefault().publishContentProviders(
getApplicationThread(), results);
} catch (RemoteException ex) {
}
}
复制代码
真正加载provider的方法installProvider:
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
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 {
//加载provider
final java.lang.ClassLoader cl = c.getClassLoader();
localProvider = (ContentProvider)cl.
loadClass(info.name).newInstance();
//调用了getIContentProvider
provider = localProvider.getIContentProvider();
if (provider == null) {
return null;
}
//调用了provider的onCreate方法
localProvider.attachInfo(c, info);
} catch (java.lang.Exception e) {
if (!mInstrumentation.onException(null, e)) {
throw new RuntimeException(
"Unable to get provider " + info.name
+ ": " + e.toString(), e);
}
return null;
}
} else {
provider = holder.provider;
}
IActivityManager.ContentProviderHolder retHolder;
synchronized (mProviderMap) {
//调用了asBinder方法
IBinder jBinder = provider.asBinder();
//下面就是将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 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 {
ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
if (prc != null) {
if (!noReleaseNeeded) {
incProviderRefLocked(prc, stable);
try {
ActivityManagerNative.getDefault().removeContentProvider(
holder.connection, stable);
} catch (RemoteException e) {
//do nothing content provider object is dead any way
}
}
} else {
ProviderClientRecord client = installProviderAuthoritiesLocked(
provider, localProvider, holder);
if (noReleaseNeeded) {
prc = new ProviderRefCount(holder, client, , );
} else {
prc = stable
? new ProviderRefCount(holder, client, , )
: new ProviderRefCount(holder, client, , );
}
mProviderRefCountMap.put(jBinder, prc);
}
retHolder = prc.holder;
}
}
return retHolder;
}
复制代码
方法主要是加载ContentProvider,然后通过加载的ContentProvider调用了getIContentProvider方法赋值给了一个IContentProvider类型的变量,这里有玄机哦!我们看一下ContentProvider中的getIContentProvider方法
//成员变量 mTransport
private Transport mTransport = new Transport();
//getIContentProvider方法
public IContentProvider getIContentProvider() {
return mTransport;
}
复制代码
class Transport extends ContentProviderNative {
....
}
复制代码
abstract public class ContentProviderNative extends Binder implements IContentProvider {
....
}
复制代码
继承于Binder实现了IContentProvider,那么也就是说在ActivityThread中初始化Application的时候,加载的ContentProvider返回的是一个Binder对象,那么也就可以理解为什么ContentProvider可以远程调用了吧。
installContentProviders方法中通过调用 ActivityManagerNative.getDefault().publishContentProviders,ContentProvider已经加载完成,然后到这里再回到第5步当中,所以说会阻塞线程。