Merge "Add <intent-filter> support to <provider>." into klp-dev

This commit is contained in:
Jeff Sharkey
2013-10-07 21:41:45 +00:00
committed by Android (Google) Code Review
12 changed files with 444 additions and 80 deletions

View File

@ -7255,6 +7255,7 @@ package android.content.pm {
method public abstract java.util.List<android.content.pm.InstrumentationInfo> queryInstrumentation(java.lang.String, int);
method public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentActivities(android.content.Intent, int);
method public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentActivityOptions(android.content.ComponentName, android.content.Intent[], android.content.Intent, int);
method public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(android.content.Intent, int);
method public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentServices(android.content.Intent, int);
method public abstract java.util.List<android.content.pm.PermissionInfo> queryPermissionsByGroup(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract deprecated void removePackageFromPreferred(java.lang.String);
@ -7420,6 +7421,7 @@ package android.content.pm {
ctor public ProviderInfo();
ctor public ProviderInfo(android.content.pm.ProviderInfo);
method public int describeContents();
method public void dump(android.util.Printer, java.lang.String);
field public static final android.os.Parcelable.Creator CREATOR;
field public static final int FLAG_SINGLE_USER = 1073741824; // 0x40000000
field public java.lang.String authority;
@ -7453,6 +7455,7 @@ package android.content.pm {
field public java.lang.CharSequence nonLocalizedLabel;
field public int preferredOrder;
field public int priority;
field public android.content.pm.ProviderInfo providerInfo;
field public java.lang.String resolvePackageName;
field public android.content.pm.ServiceInfo serviceInfo;
field public int specificIndex;
@ -20982,6 +20985,7 @@ package android.provider {
field public static final java.lang.String EXTRA_ERROR = "error";
field public static final java.lang.String EXTRA_INFO = "info";
field public static final java.lang.String EXTRA_LOADING = "loading";
field public static final java.lang.String PROVIDER_INTERFACE = "android.content.action.DOCUMENTS_PROVIDER";
}
public static final class DocumentsContract.Document {
@ -24477,6 +24481,7 @@ package android.test.mock {
method public java.util.List<android.content.pm.InstrumentationInfo> queryInstrumentation(java.lang.String, int);
method public java.util.List<android.content.pm.ResolveInfo> queryIntentActivities(android.content.Intent, int);
method public java.util.List<android.content.pm.ResolveInfo> queryIntentActivityOptions(android.content.ComponentName, android.content.Intent[], android.content.Intent, int);
method public java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(android.content.Intent, int);
method public java.util.List<android.content.pm.ResolveInfo> queryIntentServices(android.content.Intent, int);
method public java.util.List<android.content.pm.PermissionInfo> queryPermissionsByGroup(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public void removePackageFromPreferred(java.lang.String);

View File

@ -584,6 +584,22 @@ final class ApplicationPackageManager extends PackageManager {
return queryIntentServicesAsUser(intent, flags, mContext.getUserId());
}
@Override
public List<ResolveInfo> queryIntentContentProvidersAsUser(
Intent intent, int flags, int userId) {
try {
return mPM.queryIntentContentProviders(intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()), flags, userId);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
public List<ResolveInfo> queryIntentContentProviders(Intent intent, int flags) {
return queryIntentContentProvidersAsUser(intent, flags, mContext.getUserId());
}
@Override
public ProviderInfo resolveContentProvider(String name,
int flags) {

View File

@ -123,6 +123,9 @@ interface IPackageManager {
List<ResolveInfo> queryIntentServices(in Intent intent,
String resolvedType, int flags, int userId);
List<ResolveInfo> queryIntentContentProviders(in Intent intent,
String resolvedType, int flags, int userId);
/**
* This implements getInstalledPackages via a "last returned row"
* mechanism that is not exposed in the API. This is to get around the IPC

View File

@ -2210,6 +2210,24 @@ public abstract class PackageManager {
public abstract List<ResolveInfo> queryIntentServicesAsUser(Intent intent,
int flags, int userId);
/** {@hide} */
public abstract List<ResolveInfo> queryIntentContentProvidersAsUser(
Intent intent, int flags, int userId);
/**
* Retrieve all providers that can match the given intent.
*
* @param intent An intent containing all of the desired specification
* (action, data, type, category, and/or component).
* @param flags Additional option flags.
* @return A List&lt;ResolveInfo&gt; containing one entry for each matching
* ProviderInfo. These are ordered from best to worst match. If
* there are no matching providers, an empty list is returned.
* @see #GET_INTENT_FILTERS
* @see #GET_RESOLVED_FILTER
*/
public abstract List<ResolveInfo> queryIntentContentProviders(Intent intent, int flags);
/**
* Find a single content provider by its base path name.
*

View File

@ -2819,7 +2819,14 @@ public class PackageParser {
continue;
}
if (parser.getName().equals("meta-data")) {
if (parser.getName().equals("intent-filter")) {
ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
if (!parseIntent(res, parser, attrs, true, intent, outError)) {
return false;
}
outInfo.intents.add(intent);
} else if (parser.getName().equals("meta-data")) {
if ((outInfo.metaData=parseMetaData(res, parser, attrs,
outInfo.metaData, outError)) == null) {
return false;
@ -3982,7 +3989,7 @@ public class PackageParser {
return si;
}
public final static class Provider extends Component {
public final static class Provider extends Component<ProviderIntentInfo> {
public final ProviderInfo info;
public boolean syncable;
@ -4116,6 +4123,24 @@ public class PackageParser {
}
}
public static final class ProviderIntentInfo extends IntentInfo {
public final Provider provider;
public ProviderIntentInfo(Provider provider) {
this.provider = provider;
}
public String toString() {
StringBuilder sb = new StringBuilder(128);
sb.append("ProviderIntentInfo{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(' ');
provider.appendComponentShortName(sb);
sb.append('}');
return sb.toString();
}
}
/**
* @hide
*/

View File

@ -19,6 +19,7 @@ package android.content.pm;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PatternMatcher;
import android.util.Printer;
/**
* Holds information about a specific
@ -113,6 +114,12 @@ public final class ProviderInfo extends ComponentInfo
isSyncable = orig.isSyncable;
}
public void dump(Printer pw, String prefix) {
super.dumpFront(pw, prefix);
pw.println(prefix + "authority=" + authority);
pw.println(prefix + "flags=0x" + Integer.toHexString(flags));
}
public int describeContents() {
return 0;
}

View File

@ -23,6 +23,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Printer;
import android.util.Slog;
import java.text.Collator;
import java.util.Comparator;
@ -34,20 +35,30 @@ import java.util.Comparator;
* &lt;intent&gt; tags.
*/
public class ResolveInfo implements Parcelable {
private static final String TAG = "ResolveInfo";
/**
* The activity or broadcast receiver that corresponds to this resolution match,
* if this resolution is for an activity or broadcast receiver. One and only one of this and
* serviceInfo must be non-null.
* The activity or broadcast receiver that corresponds to this resolution
* match, if this resolution is for an activity or broadcast receiver.
* Exactly one of {@link #activityInfo}, {@link #serviceInfo}, or
* {@link #providerInfo} will be non-null.
*/
public ActivityInfo activityInfo;
/**
* The service that corresponds to this resolution match, if this
* resolution is for a service. One and only one of this and
* activityInfo must be non-null.
* The service that corresponds to this resolution match, if this resolution
* is for a service. Exactly one of {@link #activityInfo},
* {@link #serviceInfo}, or {@link #providerInfo} will be non-null.
*/
public ServiceInfo serviceInfo;
/**
* The provider that corresponds to this resolution match, if this
* resolution is for a provider. Exactly one of {@link #activityInfo},
* {@link #serviceInfo}, or {@link #providerInfo} will be non-null.
*/
public ProviderInfo providerInfo;
/**
* The IntentFilter that was matched for this ResolveInfo.
*/
@ -120,6 +131,13 @@ public class ResolveInfo implements Parcelable {
*/
public boolean system;
private ComponentInfo getComponentInfo() {
if (activityInfo != null) return activityInfo;
if (serviceInfo != null) return serviceInfo;
if (providerInfo != null) return providerInfo;
throw new IllegalStateException("Missing ComponentInfo!");
}
/**
* Retrieve the current textual label associated with this resolution. This
* will call back on the given PackageManager to load the label from
@ -142,7 +160,7 @@ public class ResolveInfo implements Parcelable {
return label.toString().trim();
}
}
ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo;
ComponentInfo ci = getComponentInfo();
ApplicationInfo ai = ci.applicationInfo;
if (labelRes != 0) {
label = pm.getText(ci.packageName, labelRes, ai);
@ -176,7 +194,7 @@ public class ResolveInfo implements Parcelable {
return dr;
}
}
ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo;
ComponentInfo ci = getComponentInfo();
ApplicationInfo ai = ci.applicationInfo;
if (icon != 0) {
dr = pm.getDrawable(ci.packageName, icon, ai);
@ -196,8 +214,8 @@ public class ResolveInfo implements Parcelable {
*/
public final int getIconResource() {
if (icon != 0) return icon;
if (activityInfo != null) return activityInfo.getIconResource();
if (serviceInfo != null) return serviceInfo.getIconResource();
final ComponentInfo ci = getComponentInfo();
if (ci != null) return ci.getIconResource();
return 0;
}
@ -225,6 +243,9 @@ public class ResolveInfo implements Parcelable {
} else if (serviceInfo != null) {
pw.println(prefix + "ServiceInfo:");
serviceInfo.dump(pw, prefix + " ");
} else if (providerInfo != null) {
pw.println(prefix + "ProviderInfo:");
providerInfo.dump(pw, prefix + " ");
}
}
@ -234,6 +255,7 @@ public class ResolveInfo implements Parcelable {
public ResolveInfo(ResolveInfo orig) {
activityInfo = orig.activityInfo;
serviceInfo = orig.serviceInfo;
providerInfo = orig.providerInfo;
filter = orig.filter;
priority = orig.priority;
preferredOrder = orig.preferredOrder;
@ -247,7 +269,7 @@ public class ResolveInfo implements Parcelable {
}
public String toString() {
ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo;
final ComponentInfo ci = getComponentInfo();
StringBuilder sb = new StringBuilder(128);
sb.append("ResolveInfo{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
@ -278,6 +300,9 @@ public class ResolveInfo implements Parcelable {
} else if (serviceInfo != null) {
dest.writeInt(2);
serviceInfo.writeToParcel(dest, parcelableFlags);
} else if (providerInfo != null) {
dest.writeInt(3);
providerInfo.writeToParcel(dest, parcelableFlags);
} else {
dest.writeInt(0);
}
@ -309,18 +334,21 @@ public class ResolveInfo implements Parcelable {
};
private ResolveInfo(Parcel source) {
activityInfo = null;
serviceInfo = null;
providerInfo = null;
switch (source.readInt()) {
case 1:
activityInfo = ActivityInfo.CREATOR.createFromParcel(source);
serviceInfo = null;
break;
case 2:
serviceInfo = ServiceInfo.CREATOR.createFromParcel(source);
activityInfo = null;
break;
case 3:
providerInfo = ProviderInfo.CREATOR.createFromParcel(source);
break;
default:
activityInfo = null;
serviceInfo = null;
Slog.w(TAG, "Missing ComponentInfo!");
break;
}
if (source.readInt() != 0) {

View File

@ -70,8 +70,14 @@ public final class DocumentsContract {
}
/** {@hide} */
@Deprecated
public static final String META_DATA_DOCUMENT_PROVIDER = "android.content.DOCUMENT_PROVIDER";
/**
* Intent action used to identify {@link DocumentsProvider} instances.
*/
public static final String PROVIDER_INTERFACE = "android.content.action.DOCUMENTS_PROVIDER";
/** {@hide} */
public static final String ACTION_MANAGE_ROOT = "android.provider.action.MANAGE_ROOT";
/** {@hide} */

View File

@ -21,9 +21,11 @@ import static com.android.documentsui.DocumentsActivity.TAG;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
@ -158,6 +160,9 @@ public class RootsCache {
private class UpdateTask extends AsyncTask<Void, Void, Void> {
private final String mFilterPackage;
private final Multimap<String, RootInfo> mTaskRoots = ArrayListMultimap.create();
private final HashSet<String> mTaskStoppedAuthorities = Sets.newHashSet();
/**
* Update all roots.
*/
@ -177,31 +182,52 @@ public class RootsCache {
protected Void doInBackground(Void... params) {
final long start = SystemClock.elapsedRealtime();
final Multimap<String, RootInfo> roots = ArrayListMultimap.create();
final HashSet<String> stoppedAuthorities = Sets.newHashSet();
roots.put(mRecentsRoot.authority, mRecentsRoot);
mTaskRoots.put(mRecentsRoot.authority, mRecentsRoot);
final ContentResolver resolver = mContext.getContentResolver();
final PackageManager pm = mContext.getPackageManager();
final List<ProviderInfo> providers = pm.queryContentProviders(
// Pick up provider with action string
final Intent intent = new Intent(DocumentsContract.PROVIDER_INTERFACE);
final List<ResolveInfo> providers = pm.queryIntentContentProviders(intent, 0);
for (ResolveInfo info : providers) {
handleDocumentsProvider(info.providerInfo);
}
// Pick up legacy providers
final List<ProviderInfo> legacyProviders = pm.queryContentProviders(
null, -1, PackageManager.GET_META_DATA);
for (ProviderInfo info : providers) {
for (ProviderInfo info : legacyProviders) {
if (info.metaData != null && info.metaData.containsKey(
DocumentsContract.META_DATA_DOCUMENT_PROVIDER)) {
handleDocumentsProvider(info);
}
}
final long delta = SystemClock.elapsedRealtime() - start;
Log.d(TAG, "Update found " + mTaskRoots.size() + " roots in " + delta + "ms");
synchronized (mLock) {
mRoots = mTaskRoots;
mStoppedAuthorities = mTaskStoppedAuthorities;
}
mFirstLoad.countDown();
return null;
}
private void handleDocumentsProvider(ProviderInfo info) {
// Ignore stopped packages for now; we might query them
// later during UI interaction.
if ((info.applicationInfo.flags & ApplicationInfo.FLAG_STOPPED) != 0) {
if (LOGD) Log.d(TAG, "Ignoring stopped authority " + info.authority);
stoppedAuthorities.add(info.authority);
continue;
mTaskStoppedAuthorities.add(info.authority);
return;
}
// Try using cached roots if filtering
boolean cacheHit = false;
if (mFilterPackage != null && !mFilterPackage.equals(info.packageName)) {
synchronized (mLock) {
if (roots.putAll(info.authority, mRoots.get(info.authority))) {
if (mTaskRoots.putAll(info.authority, mRoots.get(info.authority))) {
if (LOGD) Log.d(TAG, "Used cached roots for " + info.authority);
cacheHit = true;
}
@ -210,23 +236,12 @@ public class RootsCache {
// Cache miss, or loading everything
if (!cacheHit) {
roots.putAll(
info.authority, loadRootsForAuthority(resolver, info.authority));
mTaskRoots.putAll(info.authority,
loadRootsForAuthority(mContext.getContentResolver(), info.authority));
}
}
}
final long delta = SystemClock.elapsedRealtime() - start;
Log.d(TAG, "Update found " + roots.size() + " roots in " + delta + "ms");
synchronized (mLock) {
mStoppedAuthorities = stoppedAuthorities;
mRoots = roots;
}
mFirstLoad.countDown();
return null;
}
}
/**
* Bring up requested provider and query for all active roots.
*/

View File

@ -11,9 +11,9 @@
android:grantUriPermissions="true"
android:exported="true"
android:permission="android.permission.MANAGE_DOCUMENTS">
<meta-data
android:name="android.content.DOCUMENT_PROVIDER"
android:value="true" />
<intent-filter>
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
</intent-filter>
</provider>
<!-- TODO: find a better place for tests to live -->
@ -24,9 +24,9 @@
android:exported="true"
android:permission="android.permission.MANAGE_DOCUMENTS"
android:enabled="false">
<meta-data
android:name="android.content.DOCUMENT_PROVIDER"
android:value="true" />
<intent-filter>
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
</intent-filter>
</provider>
</application>
</manifest>

View File

@ -383,13 +383,12 @@ public class PackageManagerService extends IPackageManager.Stub {
// All available services, for your resolving pleasure.
final ServiceIntentResolver mServices = new ServiceIntentResolver();
// Keys are String (provider class name), values are Provider.
final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
new HashMap<ComponentName, PackageParser.Provider>();
// All available providers, for your resolving pleasure.
final ProviderIntentResolver mProviders = new ProviderIntentResolver();
// Mapping from provider base names (first directory in content URI codePath)
// to the provider information.
final HashMap<String, PackageParser.Provider> mProviders =
final HashMap<String, PackageParser.Provider> mProvidersByAuthority =
new HashMap<String, PackageParser.Provider>();
// Mapping from instrumentation class names to info about them.
@ -2095,7 +2094,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (!sUserManager.exists(userId)) return null;
enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get provider info");
synchronized (mPackages) {
PackageParser.Provider p = mProvidersByComponent.get(component);
PackageParser.Provider p = mProviders.mProviders.get(component);
if (DEBUG_PACKAGE_INFO) Log.v(
TAG, "getProviderInfo " + component + ": " + p);
if (p != null && mSettings.isEnabledLPr(p.info, flags, userId)) {
@ -3120,6 +3119,43 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
@Override
public List<ResolveInfo> queryIntentContentProviders(
Intent intent, String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
ComponentName comp = intent.getComponent();
if (comp == null) {
if (intent.getSelector() != null) {
intent = intent.getSelector();
comp = intent.getComponent();
}
}
if (comp != null) {
final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
final ProviderInfo pi = getProviderInfo(comp, flags, userId);
if (pi != null) {
final ResolveInfo ri = new ResolveInfo();
ri.providerInfo = pi;
list.add(ri);
}
return list;
}
// reader
synchronized (mPackages) {
String pkgName = intent.getPackage();
if (pkgName == null) {
return mProviders.queryIntent(intent, resolvedType, flags, userId);
}
final PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
return mProviders.queryIntentForPackage(
intent, resolvedType, flags, pkg.providers, userId);
}
return null;
}
}
@Override
public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
@ -3293,7 +3329,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (!sUserManager.exists(userId)) return null;
// reader
synchronized (mPackages) {
final PackageParser.Provider provider = mProviders.get(name);
final PackageParser.Provider provider = mProvidersByAuthority.get(name);
PackageSetting ps = provider != null
? mSettings.mPackages.get(provider.owner.packageName)
: null;
@ -3314,8 +3350,8 @@ public class PackageManagerService extends IPackageManager.Stub {
public void querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo) {
// reader
synchronized (mPackages) {
final Iterator<Map.Entry<String, PackageParser.Provider>> i = mProviders.entrySet()
.iterator();
final Iterator<Map.Entry<String, PackageParser.Provider>> i = mProvidersByAuthority
.entrySet().iterator();
final int userId = UserHandle.getCallingUserId();
while (i.hasNext()) {
Map.Entry<String, PackageParser.Provider> entry = i.next();
@ -3341,7 +3377,7 @@ public class PackageManagerService extends IPackageManager.Stub {
ArrayList<ProviderInfo> finalList = null;
// reader
synchronized (mPackages) {
final Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
final Iterator<PackageParser.Provider> i = mProviders.mProviders.values().iterator();
final int userId = processName != null ?
UserHandle.getUserId(uid) : UserHandle.getCallingUserId();
while (i.hasNext()) {
@ -4313,8 +4349,8 @@ public class PackageManagerService extends IPackageManager.Stub {
if (p.info.authority != null) {
String names[] = p.info.authority.split(";");
for (int j = 0; j < names.length; j++) {
if (mProviders.containsKey(names[j])) {
PackageParser.Provider other = mProviders.get(names[j]);
if (mProvidersByAuthority.containsKey(names[j])) {
PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
Slog.w(TAG, "Can't install because provider name " + names[j] +
" (in package " + pkg.applicationInfo.packageName +
") is already used by "
@ -4745,8 +4781,7 @@ public class PackageManagerService extends IPackageManager.Stub {
PackageParser.Provider p = pkg.providers.get(i);
p.info.processName = fixProcessName(pkg.applicationInfo.processName,
p.info.processName, pkg.applicationInfo.uid);
mProvidersByComponent.put(new ComponentName(p.info.packageName,
p.info.name), p);
mProviders.addProvider(p);
p.syncable = p.info.isSyncable;
if (p.info.authority != null) {
String names[] = p.info.authority.split(";");
@ -4763,8 +4798,8 @@ public class PackageManagerService extends IPackageManager.Stub {
p = new PackageParser.Provider(p);
p.syncable = false;
}
if (!mProviders.containsKey(names[j])) {
mProviders.put(names[j], p);
if (!mProvidersByAuthority.containsKey(names[j])) {
mProvidersByAuthority.put(names[j], p);
if (p.info.authority == null) {
p.info.authority = names[j];
} else {
@ -4777,7 +4812,7 @@ public class PackageManagerService extends IPackageManager.Stub {
+ p.info.isSyncable);
}
} else {
PackageParser.Provider other = mProviders.get(names[j]);
PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
Slog.w(TAG, "Skipping provider name " + names[j] +
" (in package " + pkg.applicationInfo.packageName +
"): name already used by "
@ -5108,8 +5143,7 @@ public class PackageManagerService extends IPackageManager.Stub {
int i;
for (i=0; i<N; i++) {
PackageParser.Provider p = pkg.providers.get(i);
mProvidersByComponent.remove(new ComponentName(p.info.packageName,
p.info.name));
mProviders.removeProvider(p);
if (p.info.authority == null) {
/* There was another ContentProvider with this authority when
@ -5120,8 +5154,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
String names[] = p.info.authority.split(";");
for (int j = 0; j < names.length; j++) {
if (mProviders.get(names[j]) == p) {
mProviders.remove(names[j]);
if (mProvidersByAuthority.get(names[j]) == p) {
mProvidersByAuthority.remove(names[j]);
if (DEBUG_REMOVE) {
if (chatty)
Log.d(TAG, "Unregistered content provider: " + names[j]
@ -5962,6 +5996,195 @@ public class PackageManagerService extends IPackageManager.Stub {
private int mFlags;
};
private final class ProviderIntentResolver
extends IntentResolver<PackageParser.ProviderIntentInfo, ResolveInfo> {
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
boolean defaultOnly, int userId) {
mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
return super.queryIntent(intent, resolvedType, defaultOnly, userId);
}
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
int userId) {
if (!sUserManager.exists(userId))
return null;
mFlags = flags;
return super.queryIntent(intent, resolvedType,
(flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
}
public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
int flags, ArrayList<PackageParser.Provider> packageProviders, int userId) {
if (!sUserManager.exists(userId))
return null;
if (packageProviders == null) {
return null;
}
mFlags = flags;
final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
final int N = packageProviders.size();
ArrayList<PackageParser.ProviderIntentInfo[]> listCut =
new ArrayList<PackageParser.ProviderIntentInfo[]>(N);
ArrayList<PackageParser.ProviderIntentInfo> intentFilters;
for (int i = 0; i < N; ++i) {
intentFilters = packageProviders.get(i).intents;
if (intentFilters != null && intentFilters.size() > 0) {
PackageParser.ProviderIntentInfo[] array =
new PackageParser.ProviderIntentInfo[intentFilters.size()];
intentFilters.toArray(array);
listCut.add(array);
}
}
return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
}
public final void addProvider(PackageParser.Provider p) {
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);
}
}
public final void removeProvider(PackageParser.Provider p) {
mProviders.remove(p.getComponentName());
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), " ");
}
removeFilter(intent);
}
}
@Override
protected boolean allowFilterResult(
PackageParser.ProviderIntentInfo filter, List<ResolveInfo> dest) {
ProviderInfo filterPi = filter.provider.info;
for (int i = dest.size() - 1; i >= 0; i--) {
ProviderInfo destPi = dest.get(i).providerInfo;
if (destPi.name == filterPi.name
&& destPi.packageName == filterPi.packageName) {
return false;
}
}
return true;
}
@Override
protected PackageParser.ProviderIntentInfo[] newArray(int size) {
return new PackageParser.ProviderIntentInfo[size];
}
@Override
protected boolean isFilterStopped(PackageParser.ProviderIntentInfo filter, int userId) {
if (!sUserManager.exists(userId))
return true;
PackageParser.Package p = filter.provider.owner;
if (p != null) {
PackageSetting ps = (PackageSetting) p.mExtras;
if (ps != null) {
// System apps are never considered stopped for purposes of
// filtering, because there may be no way for the user to
// actually re-launch them.
return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
&& ps.getStopped(userId);
}
}
return false;
}
@Override
protected boolean isPackageForFilter(String packageName,
PackageParser.ProviderIntentInfo info) {
return packageName.equals(info.provider.owner.packageName);
}
@Override
protected ResolveInfo newResult(PackageParser.ProviderIntentInfo filter,
int match, int userId) {
if (!sUserManager.exists(userId))
return null;
final PackageParser.ProviderIntentInfo info = filter;
if (!mSettings.isEnabledLPr(info.provider.info, mFlags, userId)) {
return null;
}
final PackageParser.Provider provider = info.provider;
if (mSafeMode && (provider.info.applicationInfo.flags
& ApplicationInfo.FLAG_SYSTEM) == 0) {
return null;
}
PackageSetting ps = (PackageSetting) provider.owner.mExtras;
if (ps == null) {
return null;
}
ProviderInfo pi = PackageParser.generateProviderInfo(provider, mFlags,
ps.readUserState(userId), userId);
if (pi == null) {
return null;
}
final ResolveInfo res = new ResolveInfo();
res.providerInfo = pi;
if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
res.filter = filter;
}
res.priority = info.getPriority();
res.preferredOrder = provider.owner.mPreferredOrder;
res.match = match;
res.isDefault = info.hasDefault;
res.labelRes = info.labelRes;
res.nonLocalizedLabel = info.nonLocalizedLabel;
res.icon = info.icon;
res.system = isSystemApp(res.providerInfo.applicationInfo);
return res;
}
@Override
protected void sortResults(List<ResolveInfo> results) {
Collections.sort(results, mResolvePrioritySorter);
}
@Override
protected void dumpFilter(PrintWriter out, String prefix,
PackageParser.ProviderIntentInfo filter) {
out.print(prefix);
out.print(
Integer.toHexString(System.identityHashCode(filter.provider)));
out.print(' ');
filter.provider.printComponentShortName(out);
out.print(" filter ");
out.println(Integer.toHexString(System.identityHashCode(filter)));
}
private final HashMap<ComponentName, PackageParser.Provider> mProviders
= new HashMap<ComponentName, PackageParser.Provider>();
private int mFlags;
};
private static final Comparator<ResolveInfo> mResolvePrioritySorter =
new Comparator<ResolveInfo>() {
public int compare(ResolveInfo r1, ResolveInfo r2) {
@ -10454,6 +10677,11 @@ public class PackageManagerService extends IPackageManager.Stub {
dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
dumpState.setTitlePrinted(true);
}
if (mProviders.dump(pw, dumpState.getTitlePrinted() ? "\nProvider Resolver Table:"
: "Provider Resolver Table:", " ", packageName,
dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) {
dumpState.setTitlePrinted(true);
}
}
if (dumpState.isDumping(DumpState.DUMP_PREFERRED)) {
@ -10498,7 +10726,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
boolean printedSomething = false;
for (PackageParser.Provider p : mProvidersByComponent.values()) {
for (PackageParser.Provider p : mProviders.mProviders.values()) {
if (packageName != null && !packageName.equals(p.info.packageName)) {
continue;
}
@ -10512,7 +10740,8 @@ public class PackageManagerService extends IPackageManager.Stub {
pw.print(" "); pw.println(p.toString());
}
printedSomething = false;
for (Map.Entry<String, PackageParser.Provider> entry : mProviders.entrySet()) {
for (Map.Entry<String, PackageParser.Provider> entry :
mProvidersByAuthority.entrySet()) {
PackageParser.Provider p = entry.getValue();
if (packageName != null && !packageName.equals(p.info.packageName)) {
continue;

View File

@ -282,6 +282,18 @@ public class MockPackageManager extends PackageManager {
throw new UnsupportedOperationException();
}
/** @hide */
@Override
public List<ResolveInfo> queryIntentContentProvidersAsUser(
Intent intent, int flags, int userId) {
throw new UnsupportedOperationException();
}
@Override
public List<ResolveInfo> queryIntentContentProviders(Intent intent, int flags) {
throw new UnsupportedOperationException();
}
@Override
public ProviderInfo resolveContentProvider(String name, int flags) {
throw new UnsupportedOperationException();