parent
e2e9da9a43
commit
54c1571c40
@ -0,0 +1,209 @@ |
|||||||
|
--- |
||||||
|
Provider 的启动原理 |
||||||
|
--- |
||||||
|
|
||||||
|
1. 了解 ContentProvider 的生命周期 |
||||||
|
2. 熟悉 ContentProvider 的启动流程 |
||||||
|
3. 熟悉 Provider 启动过程中各方通信原理 |
||||||
|
|
||||||
|
```java |
||||||
|
ContextResolver resolver = context.getContentResolver(); |
||||||
|
resolver.insert(uri, contentValues); |
||||||
|
public ContextResolver getContextResolver(){ |
||||||
|
return mContextResolver; |
||||||
|
} |
||||||
|
private ContextImpl(ConntextImpl container, ...) { |
||||||
|
mContextResolver = new ApplicationContextResolver(this, ...); |
||||||
|
} |
||||||
|
public final Uri insert(Uri url, ContentValues values) { |
||||||
|
IContentProvider provider = acquireProvider(url); |
||||||
|
Uri createdRow = provider.insert(mPackageName, url, values); |
||||||
|
return createdRow; |
||||||
|
} |
||||||
|
protected IContentProvider acquireProvider(Context context, String auth) { |
||||||
|
return mMainThread.acquireProvider(context, ...); |
||||||
|
} |
||||||
|
IContentProvider acquireProvider(Context c, String auth, ...){ |
||||||
|
IContentProvider provider = acquireExistingProvider(c, ...); |
||||||
|
if(provider != null){ |
||||||
|
return provider; |
||||||
|
} |
||||||
|
IActivityManager.ContentProviderHolder holder = null; |
||||||
|
holder = ActivityManagerNative.getDefault().getContentProvider(getApplicationThread(), auth, userId, stable); |
||||||
|
holder = installProvider(c, holder, holder.info, ...); |
||||||
|
return holder.provider; |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
获取 ContentProvider 的过程小结: |
||||||
|
|
||||||
|
本地找 IContentProvider 对象 -> 找到直接返回,不然请求 AMS -> AMS 返回 holder,本地安装。 |
||||||
|
|
||||||
|
本地找: |
||||||
|
|
||||||
|
```java |
||||||
|
IContentProvider acquireExistingProvider (Context c, ...) { |
||||||
|
final ProviderKey key = new ProviderKey(auth, userId); |
||||||
|
final ProviderClientRecord pr = mProviderMap.get(key); |
||||||
|
if(pr == null){ |
||||||
|
return null; |
||||||
|
} |
||||||
|
IContentProvider provider = pr.mProvider; |
||||||
|
IBinder jBinder = provider.asBinder(); |
||||||
|
if(!jBinder.isBinderAlive()) { |
||||||
|
handleUnstableProvideDiedLocked(jBinder, true); |
||||||
|
return null; |
||||||
|
} |
||||||
|
return provider; |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
远程找: |
||||||
|
|
||||||
|
```java |
||||||
|
ContentProviderHolder getContentProvider(IApplicationThread caller, ...) { |
||||||
|
return getContentProviderImpl(caller, name, null, ...); |
||||||
|
} |
||||||
|
ContentProviderHolder getContentProviderImpl(IApplicationThread caller, ...) { |
||||||
|
// 如果 ContentProviderRecord 存在就直接返回 |
||||||
|
// ContentProviderRecord 不存在,就创建一个 |
||||||
|
// 如果 ContentProviderRecord 能跑在调用者进程,就直接返回,否则往下走 |
||||||
|
// 如果 provider 所在进程没启动,就启动进程,然后等待发布,完成的时候返回 |
||||||
|
// 如果 binder 对象还没发布就请求发布,然后等待,完成的时候返回 |
||||||
|
|
||||||
|
if(providerRunning){ |
||||||
|
// provider 存在 |
||||||
|
} |
||||||
|
if(!providerRunning){ |
||||||
|
// provider 不存在 |
||||||
|
} |
||||||
|
synchronized(cpr){ |
||||||
|
while(cpr.provider == null){ |
||||||
|
cpr.wait(); |
||||||
|
} |
||||||
|
} |
||||||
|
return cpr!=null?cpr.newHolder(conn):null; |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
```java |
||||||
|
if(providerRunning){ |
||||||
|
cpi = cpr.info; |
||||||
|
if(r!=null&&cpr.canRunHere(r)){ |
||||||
|
ContentProviderHolder holder = cpr.newHolder(null); |
||||||
|
holder.provider = null; |
||||||
|
return holder; |
||||||
|
} |
||||||
|
conn = incProviderCountLocked(r, cpr, token, stable); |
||||||
|
return cpr.newHolder(conn); |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
```java |
||||||
|
// 应用端安装 provider |
||||||
|
IActivityManager.ContentProviderHolder installProvider(Context context, ...) { |
||||||
|
Context c = context.createPackageContext(ai.packageName, ...); |
||||||
|
ContentProvider localProvider = cl.loadClass(info.name).newInstance(); |
||||||
|
IContentProvider provider = localProvider.getIContentProvider(); |
||||||
|
// 调用 provider#onCreate |
||||||
|
localProvider.attachInfo(c, info); |
||||||
|
|
||||||
|
ProviderClientRecord pr = mLocalProvidersByName.get(cname); |
||||||
|
holder = new IActivityManager.ContentProviderHolder(info); |
||||||
|
holder.provider = provider; |
||||||
|
pr = installProviderAuthoritiesLocked(provider, localProvider, holder); |
||||||
|
mLocalProviders.put(jBinder, pr); |
||||||
|
mLocalProvidersByName.put(cname, pr); |
||||||
|
return pr.mHolder; |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
provider 不存在的情况: |
||||||
|
|
||||||
|
```java |
||||||
|
if(!providerRunning) { |
||||||
|
cpr = new ContentProviderRecord(this, cpi, ai, comp, singleton); |
||||||
|
if(r!=null&&cpr.canRunHere(r)){ |
||||||
|
return cpr.newHolder(null); |
||||||
|
} |
||||||
|
if(i>=N){ |
||||||
|
ProcessRecord proc = getProcessRecordLocked(...); |
||||||
|
if(proc!=null&&proc.thread!=null){ |
||||||
|
proc.thread.scheduleInstallProvider(cpi); |
||||||
|
}else{ |
||||||
|
proc = startProcessLocked(cpi.processName, ...); |
||||||
|
} |
||||||
|
mLaunchingProviders.add(cpr); |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
应用启动时主动发布 provider 的 Binder 对象: |
||||||
|
|
||||||
|
```java |
||||||
|
boolean attachApplicationLocked(IApplicationThread thread, ...){ |
||||||
|
List<ProviderInfo> providers = generateApplicationProvidersLocked(app); |
||||||
|
if(providers != null && checkAppInLaunchingProvidersLocked(app)){ |
||||||
|
Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG); |
||||||
|
msg.obj = app; |
||||||
|
mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT); |
||||||
|
} |
||||||
|
// 让应用端初始化 provider |
||||||
|
thread.bindApplication(processName, appInfo, providers, ...); |
||||||
|
return true; |
||||||
|
} |
||||||
|
// 应用主线程执行 |
||||||
|
private void handleBindApplication(AppBindData data){ |
||||||
|
List<ProviderInfo> provider = data.providers; |
||||||
|
if(providers != null){ |
||||||
|
installContentProviders(app, providers); |
||||||
|
} |
||||||
|
} |
||||||
|
void installContentProviders(Context context, List<ProviderInfo> providers){ |
||||||
|
List<ContentProviderHolder> results = new ArrayList<ContentProviderHolder>(); |
||||||
|
for(ProviderInfo cpi: providers){ |
||||||
|
ContentProviderHolder cph = installProvider(context, ...); |
||||||
|
results.add(cph); |
||||||
|
} |
||||||
|
AMP.publishContentProviders(getApplicationThread(), results); |
||||||
|
} |
||||||
|
void publishContentProviders(IApplicationThread caller, providers){ |
||||||
|
final ProcessRecord r = getRecordForAppLocked(caller); |
||||||
|
for(int i=0;i<N;i++){ |
||||||
|
ContentProviderHolder src = providers.get(i); |
||||||
|
ContentProviderRecord dst = r.pubProviders.get(src.info.name); |
||||||
|
|
||||||
|
// 更新 provider 缓存 |
||||||
|
// 更新 mLaunchingProviders |
||||||
|
// 删除超时计时的消息 |
||||||
|
|
||||||
|
synchronized(dst){ |
||||||
|
dst.provider = src.provider; |
||||||
|
dst.proc = r; |
||||||
|
dst.notifyAll(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
AMS 主动向应用请求发布 provider: |
||||||
|
|
||||||
|
```java |
||||||
|
public void scheduleInstallProvider(ProviderInfo provider){ |
||||||
|
sendMessage(H.INSTALL_PROVIDER, provider); |
||||||
|
} |
||||||
|
public void handleInstallProvider(ProviderInfo info){ |
||||||
|
installContentProviders(mInitialApplication, Lists.newArrayList(info)); |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
#### 总结 |
||||||
|
|
||||||
|
Provider 进程未启动: |
||||||
|
|
||||||
|
![](https://i.loli.net/2020/03/25/8SMpsqbDTO5u7YL.png) |
||||||
|
|
||||||
|
Provider 进程已经启动: |
||||||
|
|
||||||
|
![](https://i.loli.net/2020/03/25/nYjFePh2gRbkQ1X.png) |
||||||
|
|
After Width: | Height: | Size: 211 KiB |
After Width: | Height: | Size: 144 KiB |
Loading…
Reference in new issue