continue;
}
if (finalList == null) {
finalList = new ArrayList(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 new ParceledListSlice(finalList);
}
return ParceledListSlice.emptyList();
}
queryContentProviders
方法很长,但是其主要做的事情是,遍历了mProviders.mProviders
中的值,而mProviders.mProviders
的一个ArrayMap,value为PackageParse.Provider对象。所以,我们需要知道mProviders.mProviders是在哪里被赋值的,最后找到了PackageManagerService.ProviderIntentResolver
的addProvider方法,如下所示:
public final void addProvider(PackageParser.Provider p) {
if (mProviders.containsKey(p.getComponentName())) {
Slog.w(TAG, “Provider " + p.getComponentName() + " already defined; ignoring”);
return;
}
mProviders.put(p.getComponentName(), p);
if (DEBUG_SHOW_INFO) {
Log.v(TAG, " "
- (p.info.nonLocalizedLabel != null
? p.info.nonLocalizedLabel : p.info.name) + “:”);
Log.v(TAG, " Class=" + p.info.name);
}
final int NI = p.intents.size();
int j;
for (j = 0; j < NI; j++) {
PackageParser.ProviderIntentInfo intent = p.intents.get(j);
if (DEBUG_SHOW_INFO) {
Log.v(TAG, " IntentFilter:");
intent.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
}
if (!intent.debugCheck()) {
Log.w(TAG, "==> For Provider " + p.info.name);
}
addFilter(intent);
}
该方法中,将参数中的PackageParser.Provider对象put了进来,而PackageParser.Provider对象存储的就是每一个ContentProvider的信息。在PackageManagerService的commitPackageSettings方法中调用了上述方法,commitPackageSettings方法如下所示:
private void commitPackageSettings(PackageParser.Package pkg, PackageSetting pkgSetting,
UserHandle user, int scanFlags, boolean chatty) throws PackageManagerException {
…省略
//存储ContentProvider的信息
int N = pkg.providers.size();
StringBuilder r = null;
int i;
for (i=0; i<N; i++) {
PackageParser.Provider p = pkg.providers.get(i);
p.info.processName = fixProcessName(pkg.applicationInfo.processName,
p.info.processName);
mProviders.addProvider§;
p.syncable = p.info.isSyncable;
if (p.info.authority != null) {
String names[] = p.info.authority.split(“;”);
p.info.authority = null;
for (int j = 0; j < names.length; j++) {
if (j == 1 && p.syncable) {
// We only want the first authority for a provider to possibly be
// syncable, so if we already added this provider using a different
// authority clear the syncable flag. We copy the provider before
// changing it because the mProviders object contains a reference
// to a provider that we don’t want to change.
// Only do this for the second authority since the resulting provider
// object can be the same for all future authorities for this provider.
p = new PackageParser.Provider§;
p.syncable = false;
}
if (!mProvidersByAuthority.containsKey(names[j])) {
mProvidersByAuthority.put(names[j], p);
if (p.info.authority == null) {
p.info.authority = names[j];
} else {
p.info.authority = p.info.authority + “;” + names[j];
}
if (DEBUG_PACKAGE_SCANNING) {
if (chatty)
Log.d(TAG, "Registered content provider: " + names[j]
- ", className = " + p.info.name + ", isSyncable = "
- p.info.isSyncable);
}
} else {
PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
Slog.w(TAG, "Skipping provider name " + names[j] +
" (in package " + pkg.applicationInfo.packageName +
"): name already used by " - ((other != null && other.getComponentName() != null)
? other.getComponentName().getPackageName() : “?”));
}
}
}
if (chatty) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(’ ');
}
r.append(p.info.name);
}
}
if (r !=