Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android Content Provider的啟動過程源代碼分析

Android Content Provider的啟動過程源代碼分析

編輯:關於Android編程

本文參考Android應用程序組件Content Provider的啟動過程源代碼分析http://blog.csdn.net/luoshengyang/article/details/6963418和《Android系統源代碼情景分析》,作者羅升陽。

0、總圖流程圖如下:

\


1、MainActivity進程向ActivityServiceManager主線程發送GET_CONTENT_PORVIDER_TRANSACTION<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+ICAgICAgIMjnz8LNvKO6PGJyPgo8L3A+CjxwPjxpbWcgc3JjPQ=="/uploadfile/Collfiles/20140713/2014071310171261.jpg" alt="\">

如圖:第一步

~/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      主要做了以下幾件事:

(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);
使用進程間通信的方式取得博客欄目數量。因為要傳輸的數據比較小。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved