Android Content Provider的启动过程源码分析-阿里云开发者社区

开发者社区> 技术mix呢> 正文

Android Content Provider的启动过程源码分析

简介:
+关注继续查看

     本文參考Android应用程序组件Content Provider的启动过程源码分析http://blog.csdn.net/luoshengyang/article/details/6963418和《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; i++) {
				if (mLaunchingProviders.get(i) == cpr) {
					break;
				}
			}

			// If the provider is not already being launched, then get it
			// started.
			if (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<ProviderInfo> providers, ComponentName testName,
            String profileName, Bundle testArgs, IInstrumentationWatcher testWatcher, int debugMode,
            boolean restrictedBackupMode, Configuration config,
            Map<String, IBinder> 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<ProviderInfo> 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<String, IBinder> 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<ProviderInfo> providers,
				ComponentName instrumentationName, String profileFile,
				Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
				int debugMode, boolean isRestrictedBackupMode, Configuration config,
				Map<String, IBinder> 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<ContentProviderHolder> providers) {
		......

		synchronized(this) {
			final ProcessRecord r = getRecordForAppLocked(caller);
			......

			final int N = providers.size();
			for (int i=0; i<N; i++) {
				ContentProviderHolder src = providers.get(i);
				if (src == null || src.info == null || src.provider == null) {
					continue;
				}
				ContentProviderRecord dst = r.pubProviders.get(src.info.name);
				if (dst != null) {
					mProvidersByClass.put(dst.info.name, dst);
					String names[] = dst.info.authority.split(";");
					for (int j = 0; j < names.length; j++) {
						mProvidersByName.put(names[j], dst);
					}

					int NL = mLaunchingProviders.size();
					int j;
					for (j=0; j<NL; j++) {
						if (mLaunchingProviders.get(j) == dst) {
							mLaunchingProviders.remove(j);
							j--;
							NL--;
						}
					}
					synchronized (dst) {
						dst.provider = src.provider;
						dst.app = r;
						dst.notifyAll();
					}
					......
				}
			}
		}
	}

	......
}
        还记得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,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
4068 0
怎么设置阿里云服务器安全组?阿里云安全组规则详细解说
阿里云服务器安全组设置规则分享,阿里云服务器安全组如何放行端口设置教程
6916 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
4485 0
使用OpenApi弹性释放和设置云服务器ECS释放
云服务器ECS的一个重要特性就是按需创建资源。您可以在业务高峰期按需弹性的自定义规则进行资源创建,在完成业务计算的时候释放资源。本篇将提供几个Tips帮助您更加容易和自动化的完成云服务器的释放和弹性设置。
7758 0
阿里云服务器安全组设置内网互通的方法
虽然0.0.0.0/0使用非常方便,但是发现很多同学使用它来做内网互通,这是有安全风险的,实例有可能会在经典网络被内网IP访问到。下面介绍一下四种安全的内网互联设置方法。 购买前请先:领取阿里云幸运券,有很多优惠,可到下文中领取。
9426 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,云吞铺子总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系统盘、创建快照、配置安全组等操作如何登录ECS云服务器控制台? 1、先登录到阿里云ECS服务器控制台 2、点击顶部的“控制台” 3、通过左侧栏,切换到“云服务器ECS”即可,如下图所示 通过ECS控制台的远程连接来登录到云服务器 阿里云ECS云服务器自带远程连接功能,使用该功能可以登录到云服务器,简单且方便,如下图:点击“远程连接”,第一次连接会自动生成6位数字密码,输入密码即可登录到云服务器上。
16829 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
3227 0
+关注
2968
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载