zoukankan      html  css  js  c++  java
  • 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);
          使用进程间通信的方式取得博客栏目数量。

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

  • 相关阅读:
    Android OpenGL 编写简单滤镜
    linux 文件系统
    此博客不再更新
    golang sync包
    KADEMLIA算法
    golang 类型转换
    golang 小例子
    go-ehtereum编译:
    golang编译库文件方式
    以太坊(Ethereum)智能合约NodeJS/Web3 使用
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5155039.html
Copyright © 2011-2022 走看看