summaryrefslogtreecommitdiffstats
path: root/services/java
diff options
context:
space:
mode:
authorKenny Root <kroot@google.com>2011-04-15 17:50:10 -0700
committerKenny Root <kroot@google.com>2011-05-26 09:53:24 -0700
commit1bb6cf18c0039cb9d2a60713ea34d3709af58c5c (patch)
treeca4c1bb52197b19df287cd4dbc4cd972ce454eef /services/java
parent42f8094c066209a65b09d53611ef5c93daba4c51 (diff)
downloadframeworks_base-1bb6cf18c0039cb9d2a60713ea34d3709af58c5c.zip
frameworks_base-1bb6cf18c0039cb9d2a60713ea34d3709af58c5c.tar.gz
frameworks_base-1bb6cf18c0039cb9d2a60713ea34d3709af58c5c.tar.bz2
Break apart queries to getInstalled* API DO NOT MERGE
To avoid blowing past the Binder IPC limit, change the PackageManagerService to have a DB-like interaction where the client tells the service the last "row" that it read. The fact that we use a HashMap instead of a TreeMap makes this problematic. For now we're just making a new ArrayList for the keys and then sorting them for each call. This can make the API slower for callers of this, but it's probably greatly overshadowed by the cost of the data transfer itself. Bug: 4064282 Change-Id: Ia3a8cdaa94581ed9336f2e05694b8c8a5f757bce
Diffstat (limited to 'services/java')
-rw-r--r--services/java/com/android/server/PackageManagerService.java140
1 files changed, 95 insertions, 45 deletions
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 4a66a40..dd5c2a9 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -55,6 +55,8 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageInfoLite;
import android.content.pm.PackageManager;
import android.content.pm.PackageStats;
+import android.content.pm.ParceledListSlice;
+
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
@@ -75,6 +77,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
+import android.os.Parcelable;
import android.os.RemoteException;
import android.os.Environment;
import android.os.FileObserver;
@@ -2331,63 +2334,110 @@ class PackageManagerService extends IPackageManager.Stub {
}
}
- public List<PackageInfo> getInstalledPackages(int flags) {
- ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>();
+ private static final int getContinuationPoint(final String[] keys, final String key) {
+ final int index;
+ if (key == null) {
+ index = 0;
+ } else {
+ final int insertPoint = Arrays.binarySearch(keys, key);
+ if (insertPoint < 0) {
+ index = -insertPoint;
+ } else {
+ index = insertPoint + 1;
+ }
+ }
+ return index;
+ }
+
+ public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, String lastRead) {
+ final ParceledListSlice<PackageInfo> list = new ParceledListSlice<PackageInfo>();
+ final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
+ final String[] keys;
synchronized (mPackages) {
- if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
- Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
- while (i.hasNext()) {
- final PackageSetting ps = i.next();
- PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags);
- if(psPkg != null) {
- finalList.add(psPkg);
- }
- }
- }
- else {
- Iterator<PackageParser.Package> i = mPackages.values().iterator();
- while (i.hasNext()) {
- final PackageParser.Package p = i.next();
- if (p.applicationInfo != null) {
- PackageInfo pi = generatePackageInfo(p, flags);
- if(pi != null) {
- finalList.add(pi);
- }
+ if (listUninstalled) {
+ keys = mSettings.mPackages.keySet().toArray(new String[mSettings.mPackages.size()]);
+ } else {
+ keys = mPackages.keySet().toArray(new String[mPackages.size()]);
+ }
+
+ Arrays.sort(keys);
+ int i = getContinuationPoint(keys, lastRead);
+ final int N = keys.length;
+
+ while (i < N) {
+ final String packageName = keys[i++];
+
+ PackageInfo pi = null;
+ if (listUninstalled) {
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
+ if (ps != null) {
+ pi = generatePackageInfoFromSettingsLP(ps.name, flags);
+ }
+ } else {
+ final PackageParser.Package p = mPackages.get(packageName);
+ if (p != null) {
+ pi = generatePackageInfo(p, flags);
}
}
+
+ if (pi != null && !list.append(pi)) {
+ break;
+ }
+ }
+
+ if (i == N) {
+ list.setLastSlice(true);
}
}
- return finalList;
+
+ return list;
}
- public List<ApplicationInfo> getInstalledApplications(int flags) {
- ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>();
- synchronized(mPackages) {
- if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) {
- Iterator<PackageSetting> i = mSettings.mPackages.values().iterator();
- while (i.hasNext()) {
- final PackageSetting ps = i.next();
- ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
- if(ai != null) {
- finalList.add(ai);
- }
- }
- }
- else {
- Iterator<PackageParser.Package> i = mPackages.values().iterator();
- while (i.hasNext()) {
- final PackageParser.Package p = i.next();
- if (p.applicationInfo != null) {
- ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags);
- if(ai != null) {
- finalList.add(ai);
- }
+ public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags,
+ String lastRead) {
+ final ParceledListSlice<ApplicationInfo> list = new ParceledListSlice<ApplicationInfo>();
+ final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
+ final String[] keys;
+
+ synchronized (mPackages) {
+ if (listUninstalled) {
+ keys = mSettings.mPackages.keySet().toArray(new String[mSettings.mPackages.size()]);
+ } else {
+ keys = mPackages.keySet().toArray(new String[mPackages.size()]);
+ }
+
+ Arrays.sort(keys);
+ int i = getContinuationPoint(keys, lastRead);
+ final int N = keys.length;
+
+ while (i < N) {
+ final String packageName = keys[i++];
+
+ ApplicationInfo ai = null;
+ if (listUninstalled) {
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
+ if (ps != null) {
+ ai = generateApplicationInfoFromSettingsLP(ps.name, flags);
+ }
+ } else {
+ final PackageParser.Package p = mPackages.get(packageName);
+ if (p != null) {
+ ai = PackageParser.generateApplicationInfo(p, flags);
}
}
+
+ if (ai != null && !list.append(ai)) {
+ break;
+ }
+ }
+
+ if (i == N) {
+ list.setLastSlice(true);
}
}
- return finalList;
+
+ return list;
}
public List<ApplicationInfo> getPersistentApplications(int flags) {