diff options
-rw-r--r-- | api/current.xml | 38 | ||||
-rw-r--r-- | core/java/android/app/ApplicationContext.java | 61 | ||||
-rw-r--r-- | core/java/android/content/pm/IPackageManager.aidl | 3 | ||||
-rw-r--r-- | core/java/android/content/pm/PackageManager.java | 22 | ||||
-rw-r--r-- | services/java/com/android/server/IntentResolver.java | 17 | ||||
-rw-r--r-- | services/java/com/android/server/PackageManagerService.java | 49 | ||||
-rw-r--r-- | test-runner/android/test/mock/MockPackageManager.java | 10 |
7 files changed, 156 insertions, 44 deletions
diff --git a/api/current.xml b/api/current.xml index c03526d..7d55a7d 100644 --- a/api/current.xml +++ b/api/current.xml @@ -33321,8 +33321,6 @@ > <parameter name="packageName" type="java.lang.String"> </parameter> -<exception name="PackageManager.NameNotFoundException" type="android.content.pm.PackageManager.NameNotFoundException"> -</exception> </method> <method name="getNameForUid" return="java.lang.String" @@ -33750,6 +33748,23 @@ <parameter name="flags" type="int"> </parameter> </method> +<method name="resolveActivity" + return="android.content.pm.ResolveInfo" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="intent" type="android.content.Intent"> +</parameter> +<parameter name="flags" type="int"> +</parameter> +<parameter name="packageName" type="java.lang.String"> +</parameter> +</method> <method name="resolveContentProvider" return="android.content.pm.ProviderInfo" abstract="true" @@ -111816,8 +111831,6 @@ > <parameter name="packageName" type="java.lang.String"> </parameter> -<exception name="PackageManager.NameNotFoundException" type="android.content.pm.PackageManager.NameNotFoundException"> -</exception> </method> <method name="getNameForUid" return="java.lang.String" @@ -112227,6 +112240,23 @@ </parameter> <parameter name="flags" type="int"> </parameter> +<parameter name="packageName" type="java.lang.String"> +</parameter> +</method> +<method name="resolveActivity" + return="android.content.pm.ResolveInfo" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="intent" type="android.content.Intent"> +</parameter> +<parameter name="flags" type="int"> +</parameter> </method> <method name="resolveContentProvider" return="android.content.pm.ProviderInfo" diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java index 81e894f..2c2310a 100644 --- a/core/java/android/app/ApplicationContext.java +++ b/core/java/android/app/ApplicationContext.java @@ -1519,43 +1519,31 @@ class ApplicationContext extends Context { throw new NameNotFoundException(packageName); } - public Intent getLaunchIntentForPackage(String packageName) - throws NameNotFoundException { + @Override + public Intent getLaunchIntentForPackage(String packageName) { // First see if the package has an INFO activity; the existence of // such an activity is implied to be the desired front-door for the // overall package (such as if it has multiple launcher entries). - Intent intent = getLaunchIntentForPackageCategory(this, packageName, - Intent.CATEGORY_INFO); - if (intent != null) { - return intent; - } - + Intent intentToResolve = new Intent(Intent.ACTION_MAIN); + intentToResolve.addCategory(Intent.CATEGORY_INFO); + ResolveInfo resolveInfo = resolveActivity(intentToResolve, 0, packageName); + // Otherwise, try to find a main launcher activity. - return getLaunchIntentForPackageCategory(this, packageName, - Intent.CATEGORY_LAUNCHER); - } - - // XXX This should be implemented as a call to the package manager, - // to reduce the work needed. - static Intent getLaunchIntentForPackageCategory(PackageManager pm, - String packageName, String category) { + if (resolveInfo == null) { + // reuse the intent instance + intentToResolve.removeCategory(Intent.CATEGORY_INFO); + intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER); + resolveInfo = resolveActivity(intentToResolve, 0, packageName); + } + if (resolveInfo == null) { + return null; + } Intent intent = new Intent(Intent.ACTION_MAIN); + intent.setClassName(packageName, resolveInfo.activityInfo.name); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - Intent intentToResolve = new Intent(Intent.ACTION_MAIN, null); - intentToResolve.addCategory(category); - final List<ResolveInfo> apps = - pm.queryIntentActivities(intentToResolve, 0); - // I wish there were a way to directly get the "main" activity of a - // package but ... - for (ResolveInfo app : apps) { - if (app.activityInfo.packageName.equals(packageName)) { - intent.setClassName(packageName, app.activityInfo.name); - return intent; - } - } - return null; + return intent; } - + @Override public int[] getPackageGids(String packageName) throws NameNotFoundException { @@ -1793,6 +1781,19 @@ class ApplicationContext extends Context { } @Override + public ResolveInfo resolveActivity(Intent intent, int flags, String packageName) { + try { + return mPM.resolveIntentForPackage( + intent, + intent.resolveTypeIfNeeded(mContext.getContentResolver()), + flags, + packageName); + } catch (RemoteException e) { + throw new RuntimeException("Package manager has died", e); + } + } + + @Override public List<ResolveInfo> queryIntentActivities(Intent intent, int flags) { try { diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index c199619..bb913cd 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -81,6 +81,9 @@ interface IPackageManager { ResolveInfo resolveIntent(in Intent intent, String resolvedType, int flags); + ResolveInfo resolveIntentForPackage(in Intent intent, String resolvedType, int flags, + String packageName); + List<ResolveInfo> queryIntentActivities(in Intent intent, String resolvedType, int flags); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 3a192f7..eecbce4 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -563,9 +563,8 @@ public abstract class PackageManager { * launch the main activity in the package, or null if the package does * not contain such an activity. */ - public abstract Intent getLaunchIntentForPackage(String packageName) - throws NameNotFoundException; - + public abstract Intent getLaunchIntentForPackage(String packageName); + /** * Return an array of all of the secondary group-ids that have been * assigned to a package. @@ -971,6 +970,23 @@ public abstract class PackageManager { public abstract ResolveInfo resolveActivity(Intent intent, int flags); /** + * Resolve the intent restricted to a package. + * {@see #resolveActivity} + * + * @param intent An intent containing all of the desired specification + * (action, data, type, category, and/or component). + * @param flags Additional option flags. The most important is + * MATCH_DEFAULT_ONLY, to limit the resolution to only + * those activities that support the CATEGORY_DEFAULT. + * @param packageName Restrict the intent resolution to this package. + * + * @return Returns a ResolveInfo containing the final activity intent that + * was determined to be the best action. Returns null if no + * matching activity was found. + */ + public abstract ResolveInfo resolveActivity(Intent intent, int flags, String packageName); + + /** * Retrieve all activities that can be performed for the given intent. * * @param intent The desired intent as per resolveActivity(). diff --git a/services/java/com/android/server/IntentResolver.java b/services/java/com/android/server/IntentResolver.java index 72efca5..53e63c2 100644 --- a/services/java/com/android/server/IntentResolver.java +++ b/services/java/com/android/server/IntentResolver.java @@ -163,6 +163,23 @@ public class IntentResolver<F extends IntentFilter, R extends Object> { return Collections.unmodifiableSet(mFilters); } + public List<R> queryIntentFromList(Intent intent, String resolvedType, + boolean defaultOnly, ArrayList<ArrayList<F>> listCut) { + ArrayList<R> resultList = new ArrayList<R>(); + + final boolean debug = localLOGV || + ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0); + + final String scheme = intent.getScheme(); + int N = listCut.size(); + for (int i = 0; i < N; ++i) { + buildResolveList(intent, debug, defaultOnly, + resolvedType, scheme, listCut.get(i), resultList); + } + sortResults(resultList); + return resultList; + } + public List<R> queryIntent(ContentResolver resolver, Intent intent, String resolvedType, boolean defaultOnly) { String scheme = intent.getScheme(); diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index 079f363..4ce40b6 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -1203,6 +1203,33 @@ class PackageManagerService extends IPackageManager.Stub { public ResolveInfo resolveIntent(Intent intent, String resolvedType, int flags) { List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags); + return chooseBestActivity(intent, resolvedType, flags, query); + } + + public ResolveInfo resolveIntentForPackage(Intent intent, String resolvedType, + int flags, String packageName) { + ComponentName comp = intent.getComponent(); + if (comp != null) { + // if this is an explicit intent, it must have the same the packageName + if (packageName.equals(comp.getPackageName())) { + return resolveIntent(intent, resolvedType, flags); + } + return null; + } else { + List<ResolveInfo> query = null; + synchronized (mPackages) { + PackageParser.Package pkg = mPackages.get(packageName); + if (pkg != null) { + query = (List<ResolveInfo>) mActivities. + queryIntentForPackage(intent, resolvedType, flags, pkg.activities); + } + } + return chooseBestActivity(intent, resolvedType, flags, query); + } + } + + private ResolveInfo chooseBestActivity(Intent intent, String resolvedType, + int flags, List<ResolveInfo> query) { if (query != null) { final int N = query.size(); if (N == 1) { @@ -2853,6 +2880,22 @@ class PackageManagerService extends IPackageManager.Stub { (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0); } + public List queryIntentForPackage(Intent intent, String resolvedType, int flags, + ArrayList<PackageParser.Activity> packageActivities) { + if (packageActivities == null) { + return null; + } + mFlags = flags; + final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0; + int N = packageActivities.size(); + ArrayList<ArrayList<PackageParser.ActivityIntentInfo>> listCut = + new ArrayList<ArrayList<PackageParser.ActivityIntentInfo>>(N); + for (int i = 0; i < N; ++i) { + listCut.add(packageActivities.get(i).intents); + } + return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut); + } + public final void addActivity(PackageParser.Activity a, String type) { mActivities.put(a.component, a); if (SHOW_INFO || Config.LOGV) Log.v( @@ -2860,8 +2903,7 @@ class PackageManagerService extends IPackageManager.Stub { (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":"); if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name); int NI = a.intents.size(); - int j; - for (j=0; j<NI; j++) { + for (int j=0; j<NI; j++) { PackageParser.ActivityIntentInfo intent = a.intents.get(j); if (SHOW_INFO || Config.LOGV) { Log.v(TAG, " IntentFilter:"); @@ -2881,8 +2923,7 @@ class PackageManagerService extends IPackageManager.Stub { (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":"); if (SHOW_INFO || Config.LOGV) Log.v(TAG, " Class=" + a.info.name); int NI = a.intents.size(); - int j; - for (j=0; j<NI; j++) { + for (int j=0; j<NI; j++) { PackageParser.ActivityIntentInfo intent = a.intents.get(j); if (SHOW_INFO || Config.LOGV) { Log.v(TAG, " IntentFilter:"); diff --git a/test-runner/android/test/mock/MockPackageManager.java b/test-runner/android/test/mock/MockPackageManager.java index bf1629f..73ae3b9 100644 --- a/test-runner/android/test/mock/MockPackageManager.java +++ b/test-runner/android/test/mock/MockPackageManager.java @@ -57,11 +57,15 @@ public class MockPackageManager extends PackageManager { } @Override - public Intent getLaunchIntentForPackage(String packageName) - throws NameNotFoundException { + public Intent getLaunchIntentForPackage(String packageName) { throw new UnsupportedOperationException(); } - + + @Override + public ResolveInfo resolveActivity(Intent intent, int flags, String packageName) { + throw new UnsupportedOperationException(); + } + @Override public int[] getPackageGids(String packageName) throws NameNotFoundException { throw new UnsupportedOperationException(); |