Replugin中Client进程通过Server常驻进程ContentProvider对外提供Binder, 进而完成Client与常驻进程的通信.
IPC学习---AIDL简单概念Replugin初始化时, 在PmBase.init中如果是Client进程, 则会调用initForClient方法对非常驻进程进行初始化, 方法调用链
上面流程图中Client进程通过getContentResolver.query获取cursor, 然后获取常驻进程的Binder
ContentProvider获取流程
- 1、通过getContentResolver获取ContentResolver
- 2、getContentResolver返回ContextImpl内部类ApplicationContentResolver对象
- 3、ContentResolver中通过AMS和ActivityThread最终获得IContentResolver接口对象
- 3.1、首先判断URI是否符合标准
- 3.2、通过ContextImpl的内部类ApplicationContentResolver发送消息到调用者的ActivityThread中查看是否有被调用的ContentProvider的缓存, 如果有直接返回, 如果没有调用AMS的getContentProvider方法
- 3.3、AMS的getContentProvider方法又调用了getContentProviderImpl方法, 在这个方法中, 判断了provider在AMS当中是否存在缓存, 接着判断了multiprocess属性是否为true, 如果为true代表该provider允许在调用者进程中创建实例, 但是系统默认是false, 然后判断provider的进程是否已经被创建, 如果没有被创建则调用AMS中的startProcessLocked方法通过Process.start方法创建这个provider所属的进程
- 3.4、进程被创建后执行该进程的ActivityThread中的main方法, 在main方法中会开启消息循环, 然后调用attach方法, 在attach方法中通过调用AMS中的attachApplication方法, 又转到AMS的attachApplicationLocked中, 在这里通过ActivityThread的bindApplication方法调回到ActivityThread中, 在这里初始化一些信息后发送一条消息到ActivityThread中的Handler, 然后Handler调用handleBindApplication方法, 在这个方法中创建了Application方法, 然后调用installContentProviders方法
- 3.5、在installContentProvider方法中分两步:
- 3.5.1、开启for循环来加载所有需要在这个进程创建的provider, for循环中调用了installProviders方法, 在installProvider方法中加载ContentProvider类, 通过加载的ContentProvider.getIContentProvider获取IContentProvider接口对象, 这个接口对象是一个Binder对象, 返回的是一个叫Transport类型的对象, 这个对象继承于ContentProviderNative, 而ContentProviderNative继承于Binder并实现了IContentProvider接口, 也就是说在这里被加载完的ContentProvider返回的是一个Binder类型的IContentProvider接口对象, 所以它可以跨进程调用
- 3.5.2、加载ContentProvider类后调用AMS的publishContentProviders方法通知AMS, ContentProvider已经加载完成, 并返回这个Binder类型的IContentProvider接口对象, 然后就可以对该进程中的Provider进行操作了
<provider
android:name=".MyContentProvider"
android:authorities="com.example.content.provider"
android:multiprocess="false"
android:process=":remote"
android:exported="true"/>
**multiprocess: ** 为true表示每个调用者进程都会创建一个ContentProvider, 默认为false
**process: **表示ContentProvider所在的进程 **exported: **为true表示允许其他应用访问应用中的ContentProvider(跨进程访问), 默认为false1、**android:process=":remote"、android:multiprocess="true": **ContentProvider不会随着应用的启动而加载, 当调用ContentProvider的时候才会加载, 并且ContentProvider是在调用者的进程中初始化, 这时候可能定义ContentProvider的remote进程还没有启动
2、**android:process=":remote"、android:multiprocess="false": ** ContentProvider不会随着应用的启动而加载, 当调用到ContentProvider时才会加载, 并且ContentProvider是在"remote"进程中初始化
1. Context.getContentResolver
private ContextImpl(ContextImpl container, ActivityThread mainThread,
LoadedApk packageInfo, String splitName,
IBinder activityToken, UserHandle user, int flags,
ClassLoader classLoader) {
mContentResolver = new ApplicationContentResolver(this, mainThread);
}
public ContentResolver getContentResolver() {
return mContentResolver;
}
2.ApplicationContentResolver.query
public final Cursor query(final Uri uri, String[] projection, Bundle queryArgs,
CancellationSignal cancellationSignal) {
// 1.获取IContentProvider接口对象
IContentProvider unstableProvider = acquireUnstableProvider(uri);
IContentProvider stableProvider = null;
Cursor qCursor = null;
// 2.通过获取的IContentProvider查询数据, 并返回Cursor对象, 在这里会线程阻塞
qCursor = unstableProvider.query(mPackageName, uri, projection,
queryArgs, remoteCancellationSignal);
qCursor.getCount();
long durationMillis = SystemClock.uptimeMillis() - startTime;
maybeLogQueryToEventLog(durationMillis, uri, projection, queryArgs);
final IContentProvider provider = (stableProvider != null) ? stableProvider
: acquireProvider(uri);
// 5.将返回的cursor包装成CursorWrapperInner
final CursorWrapperInner wrapper = new CursorWrapperInner(qCursor, provider);
stableProvider = null;
qCursor = null;
return wrapper;
}
3 ApplicationContentResolver.acquireUnstableProvider
ApplicationContentResolver.acquireUnstableProvider()
--->ActivityThread.acquireProvider()
4 ActivityThread.acquireProvider
public final IContentProvider acquireProvider(
Context c, String auth, int userId, boolean stable) {
// 1.查看是否有缓存的IContentProvider, 如果有, 直接返回
IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
if (provider != null) {
return provider;
}
ContentProviderHolder holder = null;
// 2.拿到ActivityManagerService对象, 然后通过AMS获取被调用的provider的信息
holder = ActivityManager.getService().getContentProvider(
getApplicationThread(), auth, userId, stable);
if (holder == null) {
return null;
}
// 3.拿到目标ContentProvider信息并保存
holder = installProvider(c, holder, holder.info,
true /*noisy*/, holder.noReleaseNeeded, stable);
// 4.返回该ContentProvider
return holder.provider;
}
5.AMS.getContentProvider
@Override
public final ContentProviderHolder getContentProvider(
IApplicationThread caller, String name, int userId, boolean stable) {
// 进入该方法
return getContentProviderImpl(caller, name, null, stable, userId);
}
6.AMS.getContentProviderImpl
private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
String name, IBinder token, boolean stable, int userId) {
// 1.用来保存provider的信息
ContentProviderRecord cpr;
ContentProviderConnection conn = null;
ProviderInfo cpi = null;
synchronized(this) {
long startTime = SystemClock.uptimeMillis();
// 2.获取调用者的进程信息
ProcessRecord r = null;
if (caller != null) {
r = getRecordForAppLocked(caller);
}
boolean checkCrossUser = true;
// 3.查看provider的信息是否被加载过, 是否存在缓存
cpr = mProviderMap.getProviderByName(name, userId);
if (cpr == null && userId != UserHandle.USER_SYSTEM) {
cpr = mProviderMap.getProviderByName(name, UserHandle.USER_SYSTEM);
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_SYSTEM;
checkCrossUser = false;
} else {
cpr = null;
cpi = null;
}
}
}
// 4.如果是第一次调用, providerRunning一定为false
boolean providerRunning = cpr != null && cpr.proc != null && !cpr.proc.killed;
if (providerRunning) {
// 5.如果有缓存
cpi = cpr.info;
String msg;
// 6.判断provider的multiprocess是否为true, 如果是true, provider则会在调用者
// 的进程中初始化, 如果multiprocess为false, 则默认系统只有一个该provider
if (r != null && cpr.canRunHere(r)) {
ContentProviderHolder holder = cpr.newHolder(null);
holder.provider = null;
return holder;
}
}
// 7.如果没有缓存
if (!providerRunning) {
// 8.通过PMS得到provider所在应用程序的信息
cpi = AppGlobals.getPackageManager().
resolveContentProvider(name,
STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId);
if (cpi == null) {
return null;
}
ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
// 10.判断provider这个类是否是第一次加载
cpr = mProviderMap.getProviderByClass(comp, userId);
final boolean firstClass = cpr == null;
if (firstClass) {
final long ident = Binder.clearCallingIdentity();
try {
// 11.获取provider的Application信息
ApplicationInfo ai =
AppGlobals.getPackageManager().
getApplicationInfo(
cpi.applicationInfo.packageName,
STOCK_PM_FLAGS, userId);
ai = getAppInfoForUser(ai, userId);
cpr = new ContentProviderRecord(this, cpi, ai, comp, singleton);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* 12.判断provider的multiprocess是否为true, 如果是true, provider则会在调用者
* 的进程中初始化, multiprocess默认为false, 默认系统只有一个该provider
*/
if (r != null && cpr.canRunHere(r)) {
return cpr.newHolder(null);
}
/**
* 13.系统中所有的provider都会存储在mLaunchingProviders的ArrayList中, 默认情况下
* 系统只能有一个该provider的实例, 这里是看一下是否有其他的应用已经实例了该provider,
* 如果是肯定会存在mLaunchingProviders, 那么i也就肯定小于N
*/
final int N = mLaunchingProviders.size();
int i;
for (i = 0; i < N; i++) {
if (mLaunchingProviders.get(i) == cpr) {
break;
}
}
// 14.执行到这里说明没有其他应用实例该provider
if (i >= N) {
final long origId = Binder.clearCallingIdentity();
try {
//15.查看provider所属进程是否已经存在
ProcessRecord proc = getProcessRecordLocked(
cpi.processName, cpr.appInfo.uid, false);
//16.判断该进程是否已经启动
if (proc != null && proc.thread != null && !proc.killed) {
if (!proc.pubProviders.containsKey(cpi.name)) {
proc.pubProviders.put(cpi.name, cpr);
//16.使用ApplicationThread发送加载provider的消息
proc.thread.scheduleInstallProvider(cpi);
}
} else {
//17如果进程没有创建则创建一个新进程
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);
}
}
//18.存入provider信息
if (firstClass) {
mProviderMap.putProviderByClass(comp, cpr);
}
mProviderMap.putProviderByName(name, cpr);
conn = incProviderCountLocked(r, cpr, token, stable);
if (conn != null) {
conn.waiting = true;
}
}
}
//19.将provider的信息封装在ContentProviderHolder并返回
return cpr != null ? cpr.newHolder(conn) : null;
}
7.ActivityThread.handleBindApplication
如果multiprocess为false, 为ContentProvider新创建一个进程, 进程创建之后调用ActivityThread.handleBindApplication方法
private void handleBindApplication(AppBindData data) {
//1.创建上下文对象
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
final InstrumentationInfo ii;
//2.准备初始化
if (data.instrumentationName != null) {
ii = new ApplicationPackageManager(null, getPackageManager())
.getInstrumentationInfo(data.instrumentationName, 0);
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;
}
// Continue loading instrumentation.
if (ii != null) {
ApplicationInfo instrApp;
//3.创建Application的数据
instrApp = getPackageManager().getApplicationInfo(ii.packageName, 0,
UserHandle.myUserId());
if (instrApp == null) {
instrApp = new ApplicationInfo();
}
ii.copyTo(instrApp);
instrApp.initForUser(UserHandle.myUserId());
//4.LoadedApk对象是APK文件在内存中的表示, 例如Apk文件的相关信息, Apk文件的代码和资源,
// 甚至代码里面的Activity, Service等四大组件的信息都可以通过此对象获取.
final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
final ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
final ComponentName component = new ComponentName(ii.packageName, ii.name);
//5.初始化Instrumentation
mInstrumentation.init(this, instrContext, appContext, component,
data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
} else {
mInstrumentation = new Instrumentation();
mInstrumentation.basicInit(this);
}
Application app;
try {
// 6.通过创建Application并回调Application的attach方法
app = data.info.makeApplication(data.restrictedBackupMode, null);
app.setAutofillCompatibilityEnabled(data.autofillCompatibilityEnabled);
mInitialApplication = app;
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
//7.加载provider
installContentProviders(app, data.providers);
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}
mInstrumentation.onCreate(data.instrumentationArgs);
mInstrumentation.callApplicationOnCreate(app);
} finally {
}
}
8.ActivityThread.installContentProviders
private void installContentProviders(
Context context, List<ProviderInfo> providers) {
final ArrayList<ContentProviderHolder> results = new ArrayList<>();
for (ProviderInfo cpi : providers) {
// 1.加载ContentProvider
ContentProviderHolder cph = installProvider(context, null, cpi,
false, true, true);
if (cph != null) {
cph.noReleaseNeeded = true;
// 2.ContentProviderHolder存储进results
results.add(cph);
}
}
// 3.通知AMS, ContentProvider已经加载完成, 并将results发送给AMS进行管理
ActivityManager.getService().publishContentProviders(
getApplicationThread(), results);
}
9.ActivityThread.installProvider
private ContentProviderHolder installProvider(Context context,
ContentProviderHolder holder, ProviderInfo info,
boolean noisy, boolean noReleaseNeeded, boolean stable) {
ContentProvider localProvider = null;
IContentProvider provider;
if (holder == null || holder.provider == null) {
//1.创建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 {
c = context.createPackageContext(ai.packageName,
Context.CONTEXT_INCLUDE_CODE);
}
try {
//2.创建provider
final java.lang.ClassLoader cl = c.getClassLoader();
LoadedApk packageInfo = peekPackageInfo(ai.packageName, true);
if (packageInfo == null) {
packageInfo = getSystemContext().mPackageInfo;
}
localProvider = packageInfo.getAppFactory()
.instantiateProvider(cl, info.name);
provider = localProvider.getIContentProvider();
localProvider.attachInfo(c, info);
} catch (java.lang.Exception e) {
}
} else {
provider = holder.provider;
}
ContentProviderHolder retHolder;
synchronized (mProviderMap) {
IBinder jBinder = provider.asBinder();
//3.保持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 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);
ActivityManager.getService().removeContentProvider(
holder.connection, stable);
}
} else {
ProviderClientRecord client = installProviderAuthoritiesLocked(
provider, localProvider, holder);
if (noReleaseNeeded) {
prc = new ProviderRefCount(holder, client, 1000, 1000);
} else {
prc = stable
? new ProviderRefCount(holder, client, 1, 0)
: new ProviderRefCount(holder, client, 0, 1);
}
mProviderRefCountMap.put(jBinder, prc);
}
retHolder = prc.holder;
}
return retHolder;
}
10.ContentProvider.getIContentProvider
public IContentProvider getIContentProvider() {
return mTransport;
}
private Transport mTransport = new Transport();
class Transport extends ContentProviderNative{}
abstract public class ContentProviderNative extends Binder implements IContentProvider {}
public interface IContentProvider extends IInterface {}
public interface IInterface
{
public IBinder asBinder();
}
11.AMS.publishContentProviders
public final void publishContentProviders(IApplicationThread caller,
List<ContentProviderHolder> providers) {
synchronized (this) {
final ProcessRecord r = getRecordForAppLocked(caller);
final long origId = Binder.clearCallingIdentity();
final int N = providers.size();
for (int i = 0; i < N; i++) {
ContentProviderHolder src = providers.get(i);
//1.ContentProviderHolder与ContentPRoviderRecord进行映射
ContentProviderRecord dst = r.pubProviders.get(src.info.name);
if (dst != null) {
ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
mProviderMap.putProviderByClass(comp, dst);
String names[] = dst.info.authority.split(";");
for (int j = 0; j < names.length; j++) {
//1.缓存ContentProviderRecord
mProviderMap.putProviderByName(names[j], dst);
}
int launchingCount = mLaunchingProviders.size();
int j;
boolean wasInLaunchingProviders = false;
for (j = 0; j < launchingCount; j++) {
if (mLaunchingProviders.get(j) == dst) {
mLaunchingProviders.remove(j);
wasInLaunchingProviders = true;
j--;
launchingCount--;
}
}
if (wasInLaunchingProviders) {
mHandler.removeMessages(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r);
}
synchronized (dst) {
dst.provider = src.provider;
dst.proc = r;
dst.notifyAll();
}
updateOomAdjLocked(r, true);
maybeUpdateProviderUsageStatsLocked(r, src.info.packageName,
src.info.authority);
}
}
Binder.restoreCallingIdentity(origId);
}
}