summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2013-01-17 17:47:37 -0800
committerDianne Hackborn <hackbod@google.com>2013-01-18 13:02:26 -0800
commitd8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaac (patch)
tree5f6d8b2c0e66c99289ae085cb6a6a3be168eb000
parentf25febf01453733e8bdd1ac241ecd9d3bcbef475 (diff)
downloadframeworks_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.java13
-rw-r--r--core/java/android/app/AppOpsManager.java6
-rw-r--r--core/java/android/app/ApplicationPackageManager.java40
-rw-r--r--core/java/android/app/ContextImpl.java6
-rw-r--r--core/java/android/content/ContentResolver.java2
-rw-r--r--core/java/android/content/Context.java3
-rw-r--r--core/java/android/content/ContextWrapper.java6
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl6
-rw-r--r--core/java/android/content/pm/ParceledListSlice.java215
-rw-r--r--core/java/android/os/Parcel.java33
-rw-r--r--core/java/android/os/SystemVibrator.java2
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java209
-rw-r--r--test-runner/src/android/test/mock/MockContext.java6
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java6
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;
}