diff options
author | Kenny Root <kroot@google.com> | 2011-04-15 17:50:10 -0700 |
---|---|---|
committer | Kenny Root <kroot@google.com> | 2011-05-26 09:53:24 -0700 |
commit | 1bb6cf18c0039cb9d2a60713ea34d3709af58c5c (patch) | |
tree | ca4c1bb52197b19df287cd4dbc4cd972ce454eef /services/java | |
parent | 42f8094c066209a65b09d53611ef5c93daba4c51 (diff) | |
download | frameworks_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.java | 140 |
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) { |