博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android Content Provider的启动过程源码分析
阅读量:6593 次
发布时间:2019-06-24

本文共 14779 字,大约阅读时间需要 49 分钟。

     本文參考Android应用程序组件Content Provider的启动过程源码分析和《Android系统源码情景分析》,作者罗升阳。

       0、总图流程图例如以下:

       1、MainActivity进程向ActivityServiceManager主线程发送GET_CONTENT_PORVIDER_TRANSACTION

       例如以下图:

         如图:第一步

         ~/Android/frameworks/base/core/java/android/app

         ----ActivityManagerNative.java

class ActivityManagerProxy implements IActivityManager{	......    public ContentProviderHolder getContentProvider(IApplicationThread caller,                                                    String name) throws RemoteException    {            Parcel data = Parcel.obtain();        Parcel reply = Parcel.obtain();        data.writeInterfaceToken(IActivityManager.descriptor);        data.writeStrongBinder(caller != null ? caller.asBinder() : null);        data.writeString(name);        mRemote.transact(GET_CONTENT_PROVIDER_TRANSACTION, data, reply, 0);        reply.readException();        int res = reply.readInt();        ContentProviderHolder cph = null;        if (res != 0) {             cph = ContentProviderHolder.CREATOR.createFromParcel(reply);        }            data.recycle();        reply.recycle();        return cph;     }    	......}
        当中name为shy.luo.providers.articles。

        如图:第二步,省略binder_transaction传输过程,由于上面已经分析过了。

        如图:第三步

        ~/Android/frameworks/base/core/java/android/app

        ----ActivityManagerNative.java

public abstract class ActivityManagerNative extends Binder implements IActivityManager{    ......    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)            throws RemoteException {        switch (code) {        case GET_CONTENT_PROVIDER_TRANSACTION: {            data.enforceInterface(IActivityManager.descriptor);            IBinder b = data.readStrongBinder();            IApplicationThread app = ApplicationThreadNative.asInterface(b);            String name = data.readString();            ContentProviderHolder cph = getContentProvider(app, name);            reply.writeNoException();            if (cph != null) {                reply.writeInt(1);                cph.writeToParcel(reply, 0);            } else {                reply.writeInt(0);            }            return true;        }      .......}
       当中name为
shy.luo.providers.articles。

       如图:第四步

       ~/Android/frameworks/base/services/java/com/android/server/am

       ----ActivityManagerService.java

public final class ActivityManagerService extends ActivityManagerNative		implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {	......	public final ContentProviderHolder getContentProvider(			IApplicationThread caller, String name) {		......		return getContentProviderImpl(caller, name);	}	......}
       

      它调用getContentProviderImpl函数来进一步运行操作。

public final class ActivityManagerService extends ActivityManagerNative		implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {	......	private final ContentProviderHolder getContentProviderImpl(			IApplicationThread caller, String name) {		ContentProviderRecord cpr;		ProviderInfo cpi = null;		synchronized(this) {			ProcessRecord r = null;			if (caller != null) {				r = getRecordForAppLocked(caller);				......			}			// First check if this content provider has been published...			cpr = mProvidersByName.get(name);			if (cpr != null) {				......			} else {				try {					cpi = AppGlobals.getPackageManager().						resolveContentProvider(name,						STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS);				} catch (RemoteException ex) {				}				......			}			cpr = mProvidersByClass.get(cpi.name);			final boolean firstClass = cpr == null;			if (firstClass) {				try {					ApplicationInfo ai =						AppGlobals.getPackageManager().						getApplicationInfo(						cpi.applicationInfo.packageName,						STOCK_PM_FLAGS);					......					cpr = new ContentProviderRecord(cpi, ai);				} catch (RemoteException ex) {					// pm is in same process, this will never happen.				}			}			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;			}			......			// This is single process, and our app is now connecting to it.			// See if we are already in the process of launching this			// provider.			final int N = mLaunchingProviders.size();			int i;			for (i=0; i
= N) { final long origId = Binder.clearCallingIdentity(); ProcessRecord proc = startProcessLocked(cpi.processName, cpr.appInfo, false, 0, "content provider", new ComponentName(cpi.applicationInfo.packageName, cpi.name), false); ...... mLaunchingProviders.add(cpr); ...... } // Make sure the provider is published (the same provider class // may be published under multiple names). if (firstClass) { mProvidersByClass.put(cpi.name, cpr); } cpr.launchingApp = proc; mProvidersByName.put(name, cpr); ...... } // Wait for the provider to be published... synchronized (cpr) { while (cpr.provider == null) { ...... try { cpr.wait(); } catch (InterruptedException ex) { } } } return cpr; } ......}
      主要做了下面几件事:

     (1)依据传递过来的name创建了ProviderInfo对象和ApplicationInfo对象,然后依据它们两个对象创建了ContentProviderRecord对象。

     (2)创建了ProcessRecord对象,并创建ArticlesProvider子线程。

     (3)循环等待cpr.provider的值不为null。

       2、创建ArticlesProvider子线程,略。

       3、ArticlesProvider子线程向ActivityManagerService子线程发送ATTACH_APPLICATION_TRANSACTION

       第一、二、三步所有省略。仅仅看第四步。

       ~/Android/frameworks/base/services/java/com/android/server/am

       ----ActivityManagerService.java

public final class ActivityManagerService extends ActivityManagerNative		implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {	......	private final boolean attachApplicationLocked(IApplicationThread thread,			int pid) {		// Find the application record that is being attached...  either via		// the pid if we are running in multiple processes, or just pull the		// next app record if we are emulating process with anonymous threads.		ProcessRecord app;		if (pid != MY_PID && pid >= 0) {			synchronized (mPidsSelfLocked) {				app = mPidsSelfLocked.get(pid);			}		} else if (mStartingProcesses.size() > 0) {			......		} else {			......		}		......		app.thread = thread;		app.curAdj = app.setAdj = -100;		app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;		app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;		app.forcingToForeground = null;		app.foregroundServices = false;		app.debugging = false;		......		boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);		List providers = normalMode ? generateApplicationProvidersLocked(app) : null;		try {			......			thread.bindApplication(processName, app.instrumentationInfo != null				?

app.instrumentationInfo : app.info, providers, app.instrumentationClass, app.instrumentationProfileFile, app.instrumentationArguments, app.instrumentationWatcher, testMode, isRestrictedBackupMode || !normalMode, mConfiguration, getCommonServicesLocked()); ...... } catch (Exception e) { ...... } ...... return true; } ...... private final List generateApplicationProvidersLocked(ProcessRecord app) { List providers = null; try { providers = AppGlobals.getPackageManager(). queryContentProviders(app.processName, app.info.uid, STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS); } catch (RemoteException ex) { } if (providers != null) { final int N = providers.size(); for (int i=0; i<N; i++) { ProviderInfo cpi = (ProviderInfo)providers.get(i); ContentProviderRecord cpr = mProvidersByClass.get(cpi.name); if (cpr == null) { cpr = new ContentProviderRecord(cpi, app.info); mProvidersByClass.put(cpi.name, cpr); } app.pubProviders.put(cpi.name, cpr); app.addPackage(cpi.applicationInfo.packageName); ensurePackageDexOpt(cpi.applicationInfo.packageName); } } return providers; } ...... }

      主要做了下面几件事:

     (1)获取了刚在ActivityServiceManager主线程创建的ProcessRecord对象。

     (2)依据这个ProcessRecord对象获得刚在ActivityServiceManager主线程中的ProviderInfo对象。  

     (3)ActivityServiceManager子线程向ArticlesProvider子线程发送BIND_APPLICATION_TRANSACTION。

4、ActivityServiceManager子线程向ArticlesProvider子线程发送BIND_APPLICATION_TRANSACTION

        如图:第一步

        ~/Android/frameworks/base/core/java/android/app

        ----ApplicationThreadNative.java。ApplicationThreadProxy类

public final void bindApplication(String packageName, ApplicationInfo info,            List
providers, ComponentName testName, String profileName, Bundle testArgs, IInstrumentationWatcher testWatcher, int debugMode, boolean restrictedBackupMode, Configuration config, Map
services) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeString(packageName); info.writeToParcel(data, 0); data.writeTypedList(providers); if (testName == null) { data.writeInt(0); } else { data.writeInt(1); testName.writeToParcel(data, 0); } data.writeString(profileName); data.writeBundle(testArgs); data.writeStrongInterface(testWatcher); data.writeInt(debugMode); data.writeInt(restrictedBackupMode ? 1 : 0); config.writeToParcel(data, 0); data.writeMap(services); mRemote.transact(BIND_APPLICATION_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); }
       

       当中providers是在ActivityServiceManager主线程依据传递过来的name创建了ProviderInfo对象。

       如图:第二步,省略binder_transaction传输过程,由于上面已经分析过了。

       如图:第三步

       ~/Android/frameworks/base/core/java/android/app

       ----ApplicationThreadNative.java

public abstract class ApplicationThreadNative extends Binder        implements IApplicationThread {    ........    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)            throws RemoteException {        switch (code) {        case BIND_APPLICATION_TRANSACTION:        {            data.enforceInterface(IApplicationThread.descriptor);            String packageName = data.readString();            ApplicationInfo info =                ApplicationInfo.CREATOR.createFromParcel(data);            List
providers = data.createTypedArrayList(ProviderInfo.CREATOR); ComponentName testName = (data.readInt() != 0) ? new ComponentName(data) : null; String profileName = data.readString(); Bundle testArgs = data.readBundle(); IBinder binder = data.readStrongBinder(); IInstrumentationWatcher testWatcher = IInstrumentationWatcher.Stub.asInterface(binder); int testMode = data.readInt(); boolean restrictedBackupMode = (data.readInt() != 0); Configuration config = Configuration.CREATOR.createFromParcel(data); HashMap
services = data.readHashMap(null); bindApplication(packageName, info, providers, testName, profileName, testArgs, testWatcher, testMode, restrictedBackupMode, config, services); return true; } .....}
     
当中providers是在ActivityServiceManager主线程
依据传递过来的name创建了
ProviderInfo对象。

       如图:第四步

      ~/Android/frameworks/base/core/java/android/app

      ----ActivityThread.java

public final class ActivityThread {	......	private final class ApplicationThread extends ApplicationThreadNative {		......		public final void bindApplication(String processName,				ApplicationInfo appInfo, List
providers, ComponentName instrumentationName, String profileFile, Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher, int debugMode, boolean isRestrictedBackupMode, Configuration config, Map
services) { if (services != null) { // Setup the service cache in the ServiceManager ServiceManager.initServiceCache(services); } AppBindData data = new AppBindData(); data.processName = processName; data.appInfo = appInfo; data.providers = providers; data.instrumentationName = instrumentationName; data.profileFile = profileFile; data.instrumentationArgs = instrumentationArgs; data.instrumentationWatcher = instrumentationWatcher; data.debugMode = debugMode; data.restrictedBackupMode = isRestrictedBackupMode; data.config = config; queueOrSendMessage(H.BIND_APPLICATION, data); } ...... } ......}

      这个函数把相关的信息都封装成一个AppBindData对象,然后以一个消息的形式发送到主线程的消息队列中去等等待处理。这个消息终于在ArticlesProvider主线程中处理。

      
5、ArticlesProvider主线程installContentProvider
      主要做了下面几件事:

    (1)依据传递过来的providers把ArticlesProvider这个Content Provider类载入到内存中来了,并调用了它的onCreat方法。

    (2)创建了Transport对象,它的关系图例如以下:

  (3)ArticlesProvider主线程ActivityServiceManager子线程发送PUBLISH_CONTENT_PROVIDER_TRANSACTION

6、ArticlesProvider主线程ActivityServiceManager子线程发送PUBLISH_CONTENT_PROVIDER_TRANSACTION

       第一、二、三步所有省略。仅仅看第四步。

       ~/Android/frameworks/base/services/java/com/android/server/am

       ----ActivityManagerService.java

public final class ActivityManagerService extends ActivityManagerNative		implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {	......	public final void publishContentProviders(IApplicationThread caller,			List
providers) { ...... synchronized(this) { final ProcessRecord r = getRecordForAppLocked(caller); ...... final int N = providers.size(); for (int i=0; i
        还记得ActivityServiceManager在循环等待么?这里dst.provider = src.provider,为ContentProviderProxy对象(实现了IContentProvider)。

        之后调用notifyAll通知ActivityManagerService主线程,让它从等待中返回。

7、notifyAll通知ActivityManagerService主线程

8、ActivityManagerService主线程向MainActivity进程发送返回结果

        ~/Android/frameworks/base/core/java/android/app

        ----ActivityThread.java

private final IContentProvider getProvider(Context context, String name) {		IContentProvider existing = getExistingProvider(context, name);		if (existing != null) {			return existing;		}		IActivityManager.ContentProviderHolder holder = null;		try {			holder = ActivityManagerNative.getDefault().getContentProvider(				getApplicationThread(), name);		} catch (RemoteException ex) {		}		IContentProvider prov = installProvider(context, holder.provider,			holder.info, true);		......		return prov;	}
    

public class ArticlesAdapter {	......	private ContentResolver resolver = null;	public ArticlesAdapter(Context context) {		resolver = context.getContentResolver();	}	......	public int getArticleCount() {		int count = 0;		try {			IContentProvider provider = resolver.acquireProvider(Articles.CONTENT_URI);			Bundle bundle = provider.call(Articles.METHOD_GET_ITEM_COUNT, null, null);			count = bundle.getInt(Articles.KEY_ITEM_COUNT, 0);		} catch(RemoteException e) {			e.printStackTrace();		}		return count;	}	......}
         最后返回的是ContentProviderProxy对象,指向了ArticlesProvider主线程中Transport对象。例如以下图:

Bundle bundle = provider.call(Articles.METHOD_GET_ITEM_COUNT, null, null);
      
使用进程间通信的方式取得博客栏目数量。

由于要传输的数据比較小。

本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5155039.html,如需转载请自行联系原作者

你可能感兴趣的文章
“#51CTO学院四周年#互相交流,共同提高!
查看>>
同样是做内容创业,你为什么没有别人赚得多?
查看>>
检查Linux系统日志error和mysql错误日志的脚本
查看>>
高效制冷与自然冷却并重
查看>>
SQL Server 2008 全文搜索的一些知识
查看>>
GUN as 使用
查看>>
一周最新示例代码回顾 (4/16–4/22)
查看>>
TCPDUMP快速入门手册
查看>>
【转】Ubuntu13.04配置:Vim+Syntastic+Vundle+YouCompleteMe
查看>>
Nginx学习之二-配置项解析及编程实现
查看>>
点击edittext并显示其内容
查看>>
从机器学习谈起
查看>>
[Effective Java]第十一章 序列化
查看>>
[算法导论]红黑树实现(插入和删除) @ Python
查看>>
iPhone开发 数据持久化总结(终结篇)—5种数据持久化方法对比
查看>>
使用ReaderWriterLock类实现多用户读/单用户写同步
查看>>
中国式危机公关9加1策略(第十四章 国外危机应对案例參考)
查看>>
CKEditor上传插件
查看>>
Java 缩放图片工具类,创建缩略图、伸缩图片比例
查看>>
Rebuild Instance 操作详解 - 每天5分钟玩转 OpenStack(37)
查看>>