diff options
author | Dianne Hackborn <hackbod@google.com> | 2013-01-17 17:47:37 -0800 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2013-01-18 13:02:26 -0800 |
commit | d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaac (patch) | |
tree | 5f6d8b2c0e66c99289ae085cb6a6a3be168eb000 | |
parent | f25febf01453733e8bdd1ac241ecd9d3bcbef475 (diff) | |
download | frameworks_base-d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaac.zip frameworks_base-d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaac.tar.gz frameworks_base-d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaac.tar.bz2 |
Rework ParceledListSlice to be much easier to use.
Take advantage of this to return better information about
packages filtered by permissions -- include the permissions
they have in the requested array.
Also fix issue #8026793 (Contact picture shows default pic
while searching for a contact in qsb) by using the base
package name of the Context when reporting the app name
of an operation. Otherwise you could make a resource-only
context for another application and do calls through that
and get reported as the wrong app.
Change-Id: I5e0488bf773acea5a3d22f245641828e1a106fb8
-rw-r--r-- | cmds/pm/src/com/android/commands/pm/Pm.java | 13 | ||||
-rw-r--r-- | core/java/android/app/AppOpsManager.java | 6 | ||||
-rw-r--r-- | core/java/android/app/ApplicationPackageManager.java | 40 | ||||
-rw-r--r-- | core/java/android/app/ContextImpl.java | 6 | ||||
-rw-r--r-- | core/java/android/content/ContentResolver.java | 2 | ||||
-rw-r--r-- | core/java/android/content/Context.java | 3 | ||||
-rw-r--r-- | core/java/android/content/ContextWrapper.java | 6 | ||||
-rw-r--r-- | core/java/android/content/pm/IPackageManager.aidl | 6 | ||||
-rw-r--r-- | core/java/android/content/pm/ParceledListSlice.java | 215 | ||||
-rw-r--r-- | core/java/android/os/Parcel.java | 33 | ||||
-rw-r--r-- | core/java/android/os/SystemVibrator.java | 2 | ||||
-rw-r--r-- | services/java/com/android/server/pm/PackageManagerService.java | 209 | ||||
-rw-r--r-- | test-runner/src/android/test/mock/MockContext.java | 6 | ||||
-rw-r--r-- | tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java | 6 |
14 files changed, 265 insertions, 288 deletions
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index 42c9d34..39539b4 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -321,17 +321,8 @@ public final class Pm { @SuppressWarnings("unchecked") private List<PackageInfo> getInstalledPackages(IPackageManager pm, int flags, int userId) throws RemoteException { - final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>(); - PackageInfo lastItem = null; - ParceledListSlice<PackageInfo> slice; - - do { - final String lastKey = lastItem != null ? lastItem.packageName : null; - slice = pm.getInstalledPackages(flags, lastKey, userId); - lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR); - } while (!slice.isLastSlice()); - - return packageInfos; + ParceledListSlice<PackageInfo> slice = pm.getInstalledPackages(flags, userId); + return slice.getList(); } /** diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 4cea6a0..679c91d 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -228,7 +228,7 @@ public class AppOpsManager { } public int noteOp(int op) { - return noteOp(op, Process.myUid(), mContext.getPackageName()); + return noteOp(op, Process.myUid(), mContext.getBasePackageName()); } public int startOp(int op, int uid, String packageName) { @@ -252,7 +252,7 @@ public class AppOpsManager { } public int startOp(int op) { - return startOp(op, Process.myUid(), mContext.getPackageName()); + return startOp(op, Process.myUid(), mContext.getBasePackageName()); } public void finishOp(int op, int uid, String packageName) { @@ -263,6 +263,6 @@ public class AppOpsManager { } public void finishOp(int op) { - finishOp(op, Process.myUid(), mContext.getPackageName()); + finishOp(op, Process.myUid(), mContext.getBasePackageName()); } } diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 2ef3944..f09c2fe 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -426,17 +426,8 @@ final class ApplicationPackageManager extends PackageManager { @Override public List<PackageInfo> getInstalledPackages(int flags, int userId) { try { - final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>(); - PackageInfo lastItem = null; - ParceledListSlice<PackageInfo> slice; - - do { - final String lastKey = lastItem != null ? lastItem.packageName : null; - slice = mPM.getInstalledPackages(flags, lastKey, userId); - lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR); - } while (!slice.isLastSlice()); - - return packageInfos; + ParceledListSlice<PackageInfo> slice = mPM.getInstalledPackages(flags, userId); + return slice.getList(); } catch (RemoteException e) { throw new RuntimeException("Package manager has died", e); } @@ -448,17 +439,9 @@ final class ApplicationPackageManager extends PackageManager { String[] permissions, int flags) { final int userId = mContext.getUserId(); try { - final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>(); - PackageInfo lastItem = null; - ParceledListSlice<PackageInfo> slice; - - do { - final String lastKey = lastItem != null ? lastItem.packageName : null; - slice = mPM.getPackagesHoldingPermissions(permissions, flags, lastKey, userId); - lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR); - } while (!slice.isLastSlice()); - - return packageInfos; + ParceledListSlice<PackageInfo> slice = mPM.getPackagesHoldingPermissions( + permissions, flags, userId); + return slice.getList(); } catch (RemoteException e) { throw new RuntimeException("Package manager has died", e); } @@ -469,17 +452,8 @@ final class ApplicationPackageManager extends PackageManager { public List<ApplicationInfo> getInstalledApplications(int flags) { final int userId = mContext.getUserId(); try { - final List<ApplicationInfo> applicationInfos = new ArrayList<ApplicationInfo>(); - ApplicationInfo lastItem = null; - ParceledListSlice<ApplicationInfo> slice; - - do { - final String lastKey = lastItem != null ? lastItem.packageName : null; - slice = mPM.getInstalledApplications(flags, lastKey, userId); - lastItem = slice.populateList(applicationInfos, ApplicationInfo.CREATOR); - } while (!slice.isLastSlice()); - - return applicationInfos; + ParceledListSlice<ApplicationInfo> slice = mPM.getInstalledApplications(flags, userId); + return slice.getList(); } catch (RemoteException e) { throw new RuntimeException("Package manager has died", e); } diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 4925bf1..fd4389e 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -628,6 +628,12 @@ class ContextImpl extends Context { return "android"; } + /** @hide */ + @Override + public String getBasePackageName() { + return mBasePackageName != null ? mBasePackageName : getPackageName(); + } + @Override public ApplicationInfo getApplicationInfo() { if (mPackageInfo != null) { diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index fb73529..63c97ba 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -208,7 +208,7 @@ public abstract class ContentResolver { public ContentResolver(Context context) { mContext = context != null ? context : ActivityThread.currentApplication(); - mPackageName = mContext.getPackageName(); + mPackageName = context.getBasePackageName(); } /** @hide */ diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 14f2847..f7c28b6 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -418,6 +418,9 @@ public abstract class Context { /** Return the name of this application's package. */ public abstract String getPackageName(); + /** @hide Return the name of the base context this context is derived from. */ + public abstract String getBasePackageName(); + /** Return the full application info for this context's package. */ public abstract ApplicationInfo getApplicationInfo(); diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index 6a61884..b63f45e 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -135,6 +135,12 @@ public class ContextWrapper extends Context { return mBase.getPackageName(); } + /** @hide */ + @Override + public String getBasePackageName() { + return mBase.getBasePackageName(); + } + @Override public ApplicationInfo getApplicationInfo() { return mBase.getApplicationInfo(); diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 4c9c278..0445b39 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -127,7 +127,7 @@ interface IPackageManager { * limit that kicks in when flags are included that bloat up the data * returned. */ - ParceledListSlice getInstalledPackages(int flags, in String lastRead, in int userId); + ParceledListSlice getInstalledPackages(int flags, in int userId); /** * This implements getPackagesHoldingPermissions via a "last returned row" @@ -136,7 +136,7 @@ interface IPackageManager { * returned. */ ParceledListSlice getPackagesHoldingPermissions(in String[] permissions, - int flags, in String lastRead, int userId); + int flags, int userId); /** * This implements getInstalledApplications via a "last returned row" @@ -144,7 +144,7 @@ interface IPackageManager { * limit that kicks in when flags are included that bloat up the data * returned. */ - ParceledListSlice getInstalledApplications(int flags, in String lastRead, int userId); + ParceledListSlice getInstalledApplications(int flags, int userId); /** * Retrieve all applications that are marked as persistent. diff --git a/core/java/android/content/pm/ParceledListSlice.java b/core/java/android/content/pm/ParceledListSlice.java index f3a98db..8a43472 100644 --- a/core/java/android/content/pm/ParceledListSlice.java +++ b/core/java/android/content/pm/ParceledListSlice.java @@ -16,44 +16,92 @@ package android.content.pm; +import android.os.Binder; +import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; +import android.os.RemoteException; +import android.util.Log; +import java.util.ArrayList; import java.util.List; /** - * Builds up a parcel that is discarded when written to another parcel or - * written to a list. This is useful for API that sends huge lists across a - * Binder that may be larger than the IPC limit. + * Transfer a large list of Parcelable objects across an IPC. Splits into + * multiple transactions if needed. * * @hide */ public class ParceledListSlice<T extends Parcelable> implements Parcelable { + private static String TAG = "ParceledListSlice"; + private static boolean DEBUG = false; + /* * TODO get this number from somewhere else. For now set it to a quarter of * the 1MB limit. */ private static final int MAX_IPC_SIZE = 256 * 1024; + private static final int MAX_FIRST_IPC_SIZE = MAX_IPC_SIZE / 2; - private Parcel mParcel; - - private int mNumItems; + private final List<T> mList; - private boolean mIsLastSlice; + public ParceledListSlice(List<T> list) { + mList = list; + } - public ParceledListSlice() { - mParcel = Parcel.obtain(); + private ParceledListSlice(Parcel p, ClassLoader loader) { + final int N = p.readInt(); + mList = new ArrayList<T>(N); + if (DEBUG) Log.d(TAG, "Retrieving " + N + " items"); + if (N <= 0) { + return; + } + Parcelable.Creator<T> creator = p.readParcelableCreator(loader); + int i = 0; + while (i < N) { + if (p.readInt() == 0) { + break; + } + mList.add(p.readCreator(creator, loader)); + if (DEBUG) Log.d(TAG, "Read inline #" + i + ": " + mList.get(mList.size()-1)); + i++; + } + if (i >= N) { + return; + } + final IBinder retriever = p.readStrongBinder(); + while (i < N) { + if (DEBUG) Log.d(TAG, "Reading more @" + i + " of " + N + ": retriever=" + retriever); + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInt(i); + try { + retriever.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0); + } catch (RemoteException e) { + Log.w(TAG, "Failure retrieving array; only received " + i + " of " + N, e); + return; + } + while (i < N && reply.readInt() != 0) { + mList.add(reply.readCreator(creator, loader)); + if (DEBUG) Log.d(TAG, "Read extra #" + i + ": " + mList.get(mList.size()-1)); + i++; + } + reply.recycle(); + data.recycle(); + } } - private ParceledListSlice(Parcel p, int numItems, boolean lastSlice) { - mParcel = p; - mNumItems = numItems; - mIsLastSlice = lastSlice; + public List<T> getList() { + return mList; } @Override public int describeContents() { - return 0; + int contents = 0; + for (int i=0; i<mList.size(); i++) { + contents |= mList.get(i).describeContents(); + } + return contents; } /** @@ -63,104 +111,59 @@ public class ParceledListSlice<T extends Parcelable> implements Parcelable { */ @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(mNumItems); - dest.writeInt(mIsLastSlice ? 1 : 0); - - if (mNumItems > 0) { - final int parcelSize = mParcel.dataSize(); - dest.writeInt(parcelSize); - dest.appendFrom(mParcel, 0, parcelSize); - } - - mNumItems = 0; - mParcel.recycle(); - mParcel = null; - } - - /** - * Appends a parcel to this list slice. - * - * @param item Parcelable item to append to this list slice - * @return true when the list slice is full and should not be appended to - * anymore - */ - public boolean append(T item) { - if (mParcel == null) { - throw new IllegalStateException("ParceledListSlice has already been recycled"); - } - - item.writeToParcel(mParcel, PARCELABLE_WRITE_RETURN_VALUE); - mNumItems++; - - return mParcel.dataSize() > MAX_IPC_SIZE; - } - - /** - * Populates a list and discards the internal state of the - * ParceledListSlice in the process. The instance should - * not be used anymore. - * - * @param list list to insert items from this slice. - * @param creator creator that knows how to unparcel the - * target object type. - * @return the last item inserted into the list or null if none. - */ - public T populateList(List<T> list, Creator<T> creator) { - mParcel.setDataPosition(0); - - T item = null; - for (int i = 0; i < mNumItems; i++) { - item = creator.createFromParcel(mParcel); - list.add(item); + final int N = mList.size(); + final int callFlags = flags; + dest.writeInt(N); + if (DEBUG) Log.d(TAG, "Writing " + N + " items"); + if (N > 0) { + dest.writeParcelableCreator(mList.get(0)); + int i = 0; + while (i < N && dest.dataSize() < MAX_FIRST_IPC_SIZE) { + dest.writeInt(1); + mList.get(i).writeToParcel(dest, callFlags); + if (DEBUG) Log.d(TAG, "Wrote inline #" + i + ": " + mList.get(i)); + i++; + } + if (i < N) { + dest.writeInt(0); + Binder retriever = new Binder() { + @Override + protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) + throws RemoteException { + if (code != FIRST_CALL_TRANSACTION) { + return super.onTransact(code, data, reply, flags); + } + int i = data.readInt(); + if (DEBUG) Log.d(TAG, "Writing more @" + i + " of " + N); + while (i < N && reply.dataSize() < MAX_IPC_SIZE) { + reply.writeInt(1); + mList.get(i).writeToParcel(reply, callFlags); + if (DEBUG) Log.d(TAG, "Wrote extra #" + i + ": " + mList.get(i)); + i++; + } + if (i < N) { + if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N); + reply.writeInt(0); + } + return true; + } + }; + if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N + ": retriever=" + retriever); + dest.writeStrongBinder(retriever); + } } - - mParcel.recycle(); - mParcel = null; - - return item; - } - - /** - * Sets whether this is the last list slice in the series. - * - * @param lastSlice - */ - public void setLastSlice(boolean lastSlice) { - mIsLastSlice = lastSlice; - } - - /** - * Returns whether this is the last slice in a series of slices. - * - * @return true if this is the last slice in the series. - */ - public boolean isLastSlice() { - return mIsLastSlice; } @SuppressWarnings("unchecked") - public static final Parcelable.Creator<ParceledListSlice> CREATOR = - new Parcelable.Creator<ParceledListSlice>() { + public static final Parcelable.ClassLoaderCreator<ParceledListSlice> CREATOR = + new Parcelable.ClassLoaderCreator<ParceledListSlice>() { public ParceledListSlice createFromParcel(Parcel in) { - final int numItems = in.readInt(); - final boolean lastSlice = in.readInt() == 1; - - if (numItems > 0) { - final int parcelSize = in.readInt(); - - // Advance within this Parcel - int offset = in.dataPosition(); - in.setDataPosition(offset + parcelSize); - - Parcel p = Parcel.obtain(); - p.setDataPosition(0); - p.appendFrom(in, offset, parcelSize); - p.setDataPosition(0); + return new ParceledListSlice(in, null); + } - return new ParceledListSlice(p, numItems, lastSlice); - } else { - return new ParceledListSlice(); - } + @Override + public ParceledListSlice createFromParcel(Parcel in, ClassLoader loader) { + return new ParceledListSlice(in, loader); } public ParceledListSlice[] newArray(int size) { diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index d69fef0..31d323b 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -1254,6 +1254,12 @@ public final class Parcel { p.writeToParcel(this, parcelableFlags); } + /** @hide */ + public final void writeParcelableCreator(Parcelable p) { + String name = p.getClass().getName(); + writeString(name); + } + /** * Write a generic serializable object in to a Parcel. It is strongly * recommended that this method be avoided, since the serialization @@ -2046,6 +2052,28 @@ public final class Parcel { * was an error trying to instantiate the Parcelable. */ public final <T extends Parcelable> T readParcelable(ClassLoader loader) { + Parcelable.Creator<T> creator = readParcelableCreator(loader); + if (creator == null) { + return null; + } + if (creator instanceof Parcelable.ClassLoaderCreator<?>) { + return ((Parcelable.ClassLoaderCreator<T>)creator).createFromParcel(this, loader); + } + return creator.createFromParcel(this); + } + + /** @hide */ + public final <T extends Parcelable> T readCreator(Parcelable.Creator<T> creator, + ClassLoader loader) { + if (creator instanceof Parcelable.ClassLoaderCreator<?>) { + return ((Parcelable.ClassLoaderCreator<T>)creator).createFromParcel(this, loader); + } + return creator.createFromParcel(this); + } + + /** @hide */ + public final <T extends Parcelable> Parcelable.Creator<T> readParcelableCreator( + ClassLoader loader) { String name = readString(); if (name == null) { return null; @@ -2101,10 +2129,7 @@ public final class Parcel { } } - if (creator instanceof Parcelable.ClassLoaderCreator<?>) { - return ((Parcelable.ClassLoaderCreator<T>)creator).createFromParcel(this, loader); - } - return creator.createFromParcel(this); + return creator; } /** diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java index 54ea385..08eba4f 100644 --- a/core/java/android/os/SystemVibrator.java +++ b/core/java/android/os/SystemVibrator.java @@ -38,7 +38,7 @@ public class SystemVibrator extends Vibrator { } public SystemVibrator(Context context) { - mPackageName = context.getPackageName(); + mPackageName = context.getBasePackageName(); mService = IVibratorService.Stub.asInterface( ServiceManager.getService("vibrator")); } diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 9b3795a..47987f1 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -2878,187 +2878,144 @@ public class PackageManagerService extends IPackageManager.Stub { } } - 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; - } - @Override - public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, String lastRead, - int userId) { - final ParceledListSlice<PackageInfo> list = new ParceledListSlice<PackageInfo>(); + public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) { final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0; - final String[] keys; enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "get installed packages"); // writer synchronized (mPackages) { + ArrayList<PackageInfo> list; 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) { + list = new ArrayList<PackageInfo>(mSettings.mPackages.size()); + for (PackageSetting ps : mSettings.mPackages.values()) { + PackageInfo pi; + if (ps.pkg != null) { + pi = generatePackageInfo(ps.pkg, flags, userId); + } else { pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId); } - } else { - final PackageParser.Package p = mPackages.get(packageName); - if (p != null) { - pi = generatePackageInfo(p, flags, userId); + if (pi != null) { + list.add(pi); } } - - if (pi != null && list.append(pi)) { - break; + } else { + list = new ArrayList<PackageInfo>(mPackages.size()); + for (PackageParser.Package p : mPackages.values()) { + PackageInfo pi = generatePackageInfo(p, flags, userId); + if (pi != null) { + list.add(pi); + } } } - if (i == N) { - list.setLastSlice(true); - } + return new ParceledListSlice<PackageInfo>(list); } + } - return list; + private void addPackageHoldingPermissions(ArrayList<PackageInfo> list, PackageSetting ps, + String[] permissions, boolean[] tmp, int flags, int userId) { + int numMatch = 0; + for (int i=0; i<permissions.length; i++) { + if (ps.grantedPermissions.contains(permissions[i])) { + tmp[i] = true; + numMatch++; + } else { + tmp[i] = false; + } + } + if (numMatch == 0) { + return; + } + PackageInfo pi; + if (ps.pkg != null) { + pi = generatePackageInfo(ps.pkg, flags, userId); + } else { + pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId); + } + if ((flags&PackageManager.GET_PERMISSIONS) == 0) { + if (numMatch == permissions.length) { + pi.requestedPermissions = permissions; + } else { + pi.requestedPermissions = new String[numMatch]; + numMatch = 0; + for (int i=0; i<permissions.length; i++) { + if (tmp[i]) { + pi.requestedPermissions[numMatch] = permissions[i]; + numMatch++; + } + } + } + } + list.add(pi); } @Override public ParceledListSlice<PackageInfo> getPackagesHoldingPermissions( - String[] permissions, int flags, String lastRead, int userId) { + String[] permissions, int flags, int userId) { if (!sUserManager.exists(userId)) return null; - final ParceledListSlice<PackageInfo> list = new ParceledListSlice<PackageInfo>(); final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0; // writer synchronized (mPackages) { - ArrayList<String> keysList = new ArrayList<String>(); + ArrayList<PackageInfo> list = new ArrayList<PackageInfo>(); + boolean[] tmpBools = new boolean[permissions.length]; if (listUninstalled) { for (PackageSetting ps : mSettings.mPackages.values()) { - for (String perm : permissions) { - if (ps.grantedPermissions.contains(perm)) { - keysList.add(ps.name); - break; - } - } + addPackageHoldingPermissions(list, ps, permissions, tmpBools, flags, userId); } } else { for (PackageParser.Package pkg : mPackages.values()) { PackageSetting ps = (PackageSetting)pkg.mExtras; if (ps != null) { - for (String perm : permissions) { - if (ps.grantedPermissions.contains(perm)) { - keysList.add(ps.name); - break; - } - } + addPackageHoldingPermissions(list, ps, permissions, tmpBools, flags, + userId); } } } - String[] keys = new String[keysList.size()]; - keysList.toArray(keys); - 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 = generatePackageInfoFromSettingsLPw(ps.name, flags, userId); - } - } else { - final PackageParser.Package p = mPackages.get(packageName); - if (p != null) { - pi = generatePackageInfo(p, flags, userId); - } - } - - if (pi != null && list.append(pi)) { - break; - } - } - - if (i == N) { - list.setLastSlice(true); - } + return new ParceledListSlice<PackageInfo>(list); } - - return list; } @Override - public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, - String lastRead, int userId) { + public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, int userId) { if (!sUserManager.exists(userId)) return null; - final ParceledListSlice<ApplicationInfo> list = new ParceledListSlice<ApplicationInfo>(); final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0; - final String[] keys; // writer synchronized (mPackages) { + ArrayList<ApplicationInfo> list; 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; - final PackageSetting ps = mSettings.mPackages.get(packageName); - if (listUninstalled) { - if (ps != null) { + list = new ArrayList<ApplicationInfo>(mSettings.mPackages.size()); + for (PackageSetting ps : mSettings.mPackages.values()) { + ApplicationInfo ai; + if (ps.pkg != null) { + ai = PackageParser.generateApplicationInfo(ps.pkg, flags, + ps.readUserState(userId), userId); + } else { ai = generateApplicationInfoFromSettingsLPw(ps.name, flags, userId); } - } else { - final PackageParser.Package p = mPackages.get(packageName); - if (p != null && ps != null) { - ai = PackageParser.generateApplicationInfo(p, flags, - ps.readUserState(userId), userId); + if (ai != null) { + list.add(ai); } } - - if (ai != null && list.append(ai)) { - break; + } else { + list = new ArrayList<ApplicationInfo>(mPackages.size()); + for (PackageParser.Package p : mPackages.values()) { + if (p.mExtras != null) { + ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags, + ((PackageSetting)p.mExtras).readUserState(userId), userId); + if (ai != null) { + list.add(ai); + } + } } } - if (i == N) { - list.setLastSlice(true); - } + return new ParceledListSlice<ApplicationInfo>(list); } - - return list; } public List<ApplicationInfo> getPersistentApplications(int flags) { diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java index 3097811..248fbf1 100644 --- a/test-runner/src/android/test/mock/MockContext.java +++ b/test-runner/src/android/test/mock/MockContext.java @@ -106,6 +106,12 @@ public class MockContext extends Context { throw new UnsupportedOperationException(); } + /** @hide */ + @Override + public String getBasePackageName() { + throw new UnsupportedOperationException(); + } + @Override public ApplicationInfo getApplicationInfo() { throw new UnsupportedOperationException(); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java index e2fced6..e682da7 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java @@ -1080,6 +1080,12 @@ public final class BridgeContext extends Context { } @Override + public String getBasePackageName() { + // pass + return null; + } + + @Override public ApplicationInfo getApplicationInfo() { return mApplicationInfo; } |