文章出处:http://blog.csdn.net/shift_wwx
接着之前两篇
ActivityManagerService (一)
ActivityManagerService (二)
接着总结:
ActivityManagerService.installSystemProviders()
public static final void installSystemProviders() { List<ProviderInfo> providers; synchronized (mSelf) { ProcessRecord app = mSelf.mProcessNames.get("system", Process.SYSTEM_UID); providers = mSelf.generateApplicationProvidersLocked(app); if (providers != null) { for (int i=providers.size()-1; i>=0; i--) { ProviderInfo pi = (ProviderInfo)providers.get(i); if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) { Slog.w(TAG, "Not installing system proc provider " + pi.name + ": not system .apk"); providers.remove(i); } } } } if (providers != null) { mSystemThread.installSystemProviders(providers); } mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf); mSelf.mUsageStatsService.monitorPackages(); }
从函数表面是看,获取system进程的providers,然后过滤出system的providers进行install。
1)这里的app是在之前ActivityManagerService (二)setSystemProcess中提到过的:
mSelf.mProcessNames.put(app.processName, app.uid, app);显然app.processName就是system,app.uid指的也是system_uid。
private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) { List<ProviderInfo> providers = null; try { providers = AppGlobals.getPackageManager(). queryContentProviders(app.processName, app.uid, STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS); } catch (RemoteException ex) { } if (DEBUG_MU) Slog.v(TAG_MU, "generateApplicationProvidersLocked, app.info.uid = " + app.uid); int userId = app.userId; if (providers != null) { int N = providers.size(); app.pubProviders.ensureCapacity(N + app.pubProviders.size()); for (int i=0; i<N; i++) { ProviderInfo cpi = (ProviderInfo)providers.get(i); boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo, cpi.name, cpi.flags); if (singleton && UserHandle.getUserId(app.uid) != 0) { // This is a singleton provider, but a user besides the // default user is asking to initialize a process it runs // in... well, no, it doesn't actually run in this process, // it runs in the process of the default user. Get rid of it. providers.remove(i); N--; i--; continue; } ComponentName comp = new ComponentName(cpi.packageName, cpi.name); ContentProviderRecord cpr = mProviderMap.getProviderByClass(comp, userId); if (cpr == null) { cpr = new ContentProviderRecord(this, cpi, app.info, comp, singleton); mProviderMap.putProviderByClass(comp, cpr); } if (DEBUG_MU) Slog.v(TAG_MU, "generateApplicationProvidersLocked, cpi.uid = " + cpr.uid); app.pubProviders.put(cpi.name, cpr); if (!cpi.multiprocess || !"android".equals(cpi.packageName)) { // Don't add this if it is a platform component that is marked // to run in multiple processes, because this is actually // part of the framework so doesn't make sense to track as a // separate apk in the process. app.addPackage(cpi.applicationInfo.packageName, mProcessStats); } ensurePackageDexOpt(cpi.applicationInfo.packageName); } } return providers; }(1)AppGlobals.getPackageManager()
public static IPackageManager getPackageManager() { return ActivityThread.getPackageManager(); }接着:
public static IPackageManager getPackageManager() { if (sPackageManager != null) { //Slog.v("PackageManager", "returning cur default = " + sPackageManager); return sPackageManager; } IBinder b = ServiceManager.getService("package"); //Slog.v("PackageManager", "default service binder = " + b); sPackageManager = IPackageManager.Stub.asInterface(b); //Slog.v("PackageManager", "default service = " + sPackageManager); return sPackageManager; }似曾相识过吧,在 ActivityManagerService (二)setSystemProcess中提到过:
ApplicationInfo info =mSelf.mContext.getPackageManager().getApplicationInfo("android", STOCK_PM_FLAGS);不过这里是通过context获取PMS:
@Override public PackageManager getPackageManager() { if (mPackageManager != null) { return mPackageManager; } IPackageManager pm = ActivityThread.getPackageManager(); if (pm != null) { // Doesn't matter if we make more than one instance. return (mPackageManager = new ApplicationPackageManager(this, pm)); } return null; }不过最终还是会调用到ActivityThread.getPackageManager();我想这里没有用AMS中mSystemThread应该是为了区分system和非system的app吧。
static IPackageManager sPackageManager;所以用的是一个PMS。
(2)queryContentProviders
public List<ProviderInfo> queryContentProviders(String processName, int uid, int flags) { ArrayList<ProviderInfo> finalList = null; // reader synchronized (mPackages) { final Iterator<PackageParser.Provider> i = mProviders.mProviders.values().iterator(); final int userId = processName != null ? UserHandle.getUserId(uid) : UserHandle.getCallingUserId(); while (i.hasNext()) { final PackageParser.Provider p = i.next(); PackageSetting ps = mSettings.mPackages.get(p.owner.packageName); if (ps != null && p.info.authority != null && (processName == null || (p.info.processName.equals(processName) && UserHandle.isSameApp(p.info.applicationInfo.uid, uid))) && mSettings.isEnabledLPr(p.info, flags, userId) && (!mSafeMode || (p.info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0)) { if (finalList == null) { finalList = new ArrayList<ProviderInfo>(3); } ProviderInfo info = PackageParser.generateProviderInfo(p, flags, ps.readUserState(userId), userId); if (info != null) { finalList.add(info); } } } } if (finalList != null) { Collections.sort(finalList, mProviderInitOrderSorter); } return finalList; }这个函数中:
final Iterator<PackageParser.Provider> i = mProviders.mProviders.values().iterator();
不知道怎么来的,需要跟一下PMS.main,对于PMS详细过程,后期会总结,这里应该是通过PMS解析后搜集了所有的providers。
过滤条件比较多,authority不能为null,processName是system,uid是system_uid,flags的第0 bit位是FLAG_SYSTEM。
(3)app.pubProviders.ensureCapacity(N + app.pubProviders.size());
更新pubProviders的size。
final ArrayMap<String, ContentProviderRecord> pubProviders = new ArrayMap<String, ContentProviderRecord>();(4)处理provider
mProviderMap.putProviderByClass(comp, cpr);//加到AMS中的ProviderMap中
final ProviderMap mProviderMap;//mProviderMap是final的
app.pubProviders.put(cpi.name, cpr);//加到ProcessRecord里面的pubProviders
final ArrayMap<String, ContentProviderRecord> pubProviders = new ArrayMap<String, ContentProviderRecord>();
app.addPackage(cpi.applicationInfo.packageName, mProcessStats);//将package加到ProcessRecord中的pkgList
public boolean addPackage(String pkg, ProcessStatsService tracker) { if (!pkgList.containsKey(pkg)) { if (baseProcessTracker != null) {//baseProcessTracker在之前的AMS.setSystemProcess中的makeActive中初始化过 ProcessStats.ProcessState state = tracker.getProcessStateLocked( pkg, info.uid, processName); pkgList.put(pkg, state); if (state != baseProcessTracker) { state.makeActive(); } } else { pkgList.put(pkg, null); } return true; } return false; }
结合之前的AMS.setSystemProcess,这时ProcessRecord就有两个package在里面了,一个是framework-res.apk中所指的android package,另一个就是这里的process name 是system,uid是system_uid的provider。
看一下AMS和ProcessRecord中保存SettingsProvider的数据结构。
弄了半天,这样的provider在andorid系统有中有哪些呢?为什么要在AMS初始化的前期一定要初始化提出来这些provider,经过检查发现了这样的provider:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.providers.settings" coreApp="true" android:sharedUserId="android.uid.system"> <application android:allowClearUserData="false" android:label="@string/app_label" android:process="system" android:backupAgent="SettingsBackupAgent" android:killAfterRestore="false" android:icon="@mipmap/ic_launcher_settings"> <!-- todo add: android:neverEncrypt="true" --> <provider android:name="SettingsProvider" android:authorities="settings" android:multiprocess="false" android:exported="true" android:writePermission="android.permission.WRITE_SETTINGS" android:initOrder="100" /> </application> </manifest>看到package name就知道了,是SettingsProvider.apk。至于SettingsProvider具体作用这里不做解释,一些系统的默认参数都是通过这里设置,通过db来实现进程间数据共享等等。
3)mSystemThread.installSystemProviders(providers);
if (providers != null) { mSystemThread.installSystemProviders(providers); }
public final void installSystemProviders(List<ProviderInfo> providers) { if (providers != null) { installContentProviders(mInitialApplication, providers); } }
public final void installSystemProviders(List<ProviderInfo> providers) { if (providers != null) { installContentProviders(mInitialApplication, providers); } }
private void installContentProviders( Context context, List<ProviderInfo> providers) { final ArrayList<IActivityManager.ContentProviderHolder> results = new ArrayList<IActivityManager.ContentProviderHolder>(); for (ProviderInfo cpi : providers) { if (DEBUG_PROVIDER) { StringBuilder buf = new StringBuilder(128); buf.append("Pub "); buf.append(cpi.authority); buf.append(": "); buf.append(cpi.name); Log.i(TAG, buf.toString()); } IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi, false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/); if (cph != null) { cph.noReleaseNeeded = true; results.add(cph); } } try { ActivityManagerNative.getDefault().publishContentProviders( getApplicationThread(), results); } catch (RemoteException ex) { } }context是上面传进来的mInitialApplication,其实就是mSystemContext。
private IActivityManager.ContentProviderHolder installProvider(Context context, IActivityManager.ContentProviderHolder holder, ProviderInfo info, boolean noisy, boolean noReleaseNeeded, boolean stable) { ContentProvider localProvider = null; IContentProvider provider; if (holder == null || holder.provider == null) { if (DEBUG_PROVIDER || noisy) { Slog.d(TAG, "Loading provider " + info.authority + ": " + info.name); } 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 { try { c = context.createPackageContext(ai.packageName, Context.CONTEXT_INCLUDE_CODE); } catch (PackageManager.NameNotFoundException e) { // Ignore } } if (c == null) { Slog.w(TAG, "Unable to get context for package " + ai.packageName + " while loading content provider " + info.name); return null; } try { final java.lang.ClassLoader cl = c.getClassLoader(); localProvider = (ContentProvider)cl. loadClass(info.name).newInstance(); provider = localProvider.getIContentProvider(); if (provider == null) { Slog.e(TAG, "Failed to instantiate class " + info.name + " from sourceDir " + info.applicationInfo.sourceDir); return null; } if (DEBUG_PROVIDER) Slog.v( TAG, "Instantiating local provider " + info.name); // XXX Need to create the correct context for this provider. localProvider.attachInfo(c, info); } catch (java.lang.Exception e) { if (!mInstrumentation.onException(null, e)) { throw new RuntimeException( "Unable to get provider " + info.name + ": " + e.toString(), e); } return null; } } else { provider = holder.provider; if (DEBUG_PROVIDER) Slog.v(TAG, "Installing external provider " + info.authority + ": " + info.name); } IActivityManager.ContentProviderHolder retHolder; synchronized (mProviderMap) { if (DEBUG_PROVIDER) Slog.v(TAG, "Checking to add " + provider + " / " + info.name); IBinder jBinder = provider.asBinder(); if (localProvider != null) { ComponentName cname = new ComponentName(info.packageName, info.name); ProviderClientRecord pr = mLocalProvidersByName.get(cname); if (pr != null) { if (DEBUG_PROVIDER) { Slog.v(TAG, "installProvider: lost the race, " + "using existing local provider"); } provider = pr.mProvider; } else { holder = new IActivityManager.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 (DEBUG_PROVIDER) { Slog.v(TAG, "installProvider: lost the race, updating ref count"); } // We need to transfer our new reference to the existing // ref count, releasing the old one... but only if // release is needed (that is, it is not running in the // system process). if (!noReleaseNeeded) { incProviderRefLocked(prc, stable); try { ActivityManagerNative.getDefault().removeContentProvider( holder.connection, stable); } catch (RemoteException e) { //do nothing content provider object is dead any way } } } 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; }(1)传进来的holder是null,所以,直接进入if条件语句块。
然后试图确认packageName是否和mSystemContext的packageName一样,显然不一样,一个是com.android.providers.settings,一个android。
所以,索性创建了provider自己的context:
try { c = context.createPackageContext(ai.packageName, Context.CONTEXT_INCLUDE_CODE); } catch (PackageManager.NameNotFoundException e) { // Ignore }这个函数不去详细说明,主要就是通过packageName构造一个LoadedApk,通过context init来创建一个context返回。
public IContentProvider getIContentProvider() { return mTransport; }
private Transport mTransport = new Transport();
class Transport extends ContentProviderNative { ...... }
abstract public class ContentProviderNative extends Binder implements IContentProvider { ...... }集合provider定义的地方:
IContentProvider provider;
provider是个Binder,后面继续说明。
(3)localProvider.attachInfo(c, info);
public void attachInfo(Context context, ProviderInfo info) { attachInfo(context, info, false); } private void attachInfo(Context context, ProviderInfo info, boolean testing) { /* * We may be using AsyncTask from binder threads. Make it init here * so its static handler is on the main thread. */ AsyncTask.init(); mNoPerms = testing; /* * Only allow it to be set once, so after the content service gives * this to us clients can't change it. */ if (mContext == null) { mContext = context; if (context != null) { mTransport.mAppOpsManager = (AppOpsManager) context.getSystemService( Context.APP_OPS_SERVICE); } mMyUid = Process.myUid(); if (info != null) { setReadPermission(info.readPermission); setWritePermission(info.writePermission); setPathPermissions(info.pathPermissions); mExported = info.exported; } ContentProvider.this.onCreate(); } }创建AppOpsManager,设置SettingProvider的mMyUid,设置读写权限,设置path权限,设置mExported,最后回调SettingsProvider的onCreate函数。原来SettingsProvider在这里就创建ok了。
(4)IActivityManager.ContentProviderHolder retHolder;
可以说之前的都是初始化准备工作,这里才第一次创建ContentProviderHolder 对象。当然,局部的对象,是不可能直接返回的。
(5)ProviderClientRecord pr = mLocalProvidersByName.get(cname);
之前分析过了,在generateApplicationProvidersLocked中解析Provider的时候,只是在AMS和ProcessRecord里面有保存,ActivityThread里面是没有保存的,所以这里pr是null。
所以,会实例一个ContentProviderHolder。最后installProvider方法调用installProviderAuthoritiesLocked方法构造一个ProviderClientRecord对象,并添加到mProviderMap、mLocalProviders和mLocalProvidersByName中,这三个ArraryMap可以通过不同键值快速找到对象的ProviderClientRecord对象。最后返回ContentProviderHolder。AcitivytThread中保存SettingsProvider的信息如下:
返回installContentProviders,既然ContentProviderHolder已经ok了,接着看下一步:
ActivityManagerNative.getDefault().publishContentProviders( getApplicationThread(), results);
public final void publishContentProviders(IApplicationThread caller, List<ContentProviderHolder> providers) { if (providers == null) { return; } enforceNotIsolatedCaller("publishContentProviders"); synchronized (this) { final ProcessRecord r = getRecordForAppLocked(caller); if (DEBUG_MU) Slog.v(TAG_MU, "ProcessRecord uid = " + r.uid); if (r == null) { throw new SecurityException( "Unable to find app for caller " + caller + " (pid=" + Binder.getCallingPid() + ") when publishing content providers"); } final long origId = Binder.clearCallingIdentity(); 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 (DEBUG_MU) Slog.v(TAG_MU, "ContentProviderRecord uid = " + dst.uid); 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++) { mProviderMap.putProviderByName(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.proc = r; dst.notifyAll(); } updateOomAdjLocked(r); } } Binder.restoreCallingIdentity(origId); } }
(1)第一个参数getApplicationThread()
final ApplicationThread mAppThread = new ApplicationThread();在构造mSystemThread的时候构造的,具体的在 ActivityManagerService (二)中提到过。
(2)第二个参数就是之前创造的ContentProviderHolder
getRecordForAppLocked从mLruProcesses链表中查找并返回我们前面创建的ProcessRecord对象,我们知道在generateApplicationProvidersLocked方法中,我们将从PMS
得到的SettingsProvider信息已经添加到ProcessRecord的pubProviders数组中了,这里将provider信息添加到mProviderMap中,并从mLaunchingProviders(表示待启动的
provider列表)中移除已经启动的provider。
最后回到installSystemProviders方法中,注册一个ContentObserver来监听Settings.Secure.LONG_PRESS_TIMEOUT的变化并调用UsageStatsService去监听package的使用状态。
到这里AMS的installSystemProviders就总结完了。后期会进一步的完善。