summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/core/java/com/android/server/pm/KeySetHandle.java45
-rw-r--r--services/core/java/com/android/server/pm/KeySetManagerService.java517
-rw-r--r--services/core/java/com/android/server/pm/PackageKeySetData.java82
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java14
-rw-r--r--services/core/java/com/android/server/pm/Settings.java44
5 files changed, 364 insertions, 338 deletions
diff --git a/services/core/java/com/android/server/pm/KeySetHandle.java b/services/core/java/com/android/server/pm/KeySetHandle.java
index 640feb3..f34bd60 100644
--- a/services/core/java/com/android/server/pm/KeySetHandle.java
+++ b/services/core/java/com/android/server/pm/KeySetHandle.java
@@ -18,5 +18,46 @@ package com.android.server.pm;
import android.os.Binder;
-public class KeySetHandle extends Binder {
-} \ No newline at end of file
+class KeySetHandle extends Binder{
+ private final long mId;
+ private int mRefCount;
+
+ protected KeySetHandle(long id) {
+ mId = id;
+ mRefCount = 1;
+ }
+
+ /*
+ * Only used when reading state from packages.xml
+ */
+ protected KeySetHandle(long id, int refCount) {
+ mId = id;
+ mRefCount = refCount;
+ }
+
+ public long getId() {
+ return mId;
+ }
+
+ protected int getRefCountLPr() {
+ return mRefCount;
+ }
+
+ /*
+ * Only used when reading state from packages.xml
+ */
+ protected void setRefCountLPw(int newCount) {
+ mRefCount = newCount;
+ return;
+ }
+
+ protected void incrRefCountLPw() {
+ mRefCount++;
+ return;
+ }
+
+ protected int decrRefCountLPw() {
+ mRefCount--;
+ return mRefCount;
+ }
+}
diff --git a/services/core/java/com/android/server/pm/KeySetManagerService.java b/services/core/java/com/android/server/pm/KeySetManagerService.java
index aa63932..db3ae91 100644
--- a/services/core/java/com/android/server/pm/KeySetManagerService.java
+++ b/services/core/java/com/android/server/pm/KeySetManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.pm;
import android.content.pm.PackageParser;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Base64;
import android.util.Slog;
@@ -25,7 +26,6 @@ import android.util.LongSparseArray;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.PublicKey;
-import java.util.Map;
import java.util.Set;
import org.xmlpull.v1.XmlPullParser;
@@ -52,19 +52,61 @@ public class KeySetManagerService {
private final LongSparseArray<KeySetHandle> mKeySets;
- private final LongSparseArray<PublicKey> mPublicKeys;
+ private final LongSparseArray<PublicKeyHandle> mPublicKeys;
protected final LongSparseArray<ArraySet<Long>> mKeySetMapping;
- private final Map<String, PackageSetting> mPackages;
+ private final ArrayMap<String, PackageSetting> mPackages;
private static long lastIssuedKeySetId = 0;
private static long lastIssuedKeyId = 0;
- public KeySetManagerService(Map<String, PackageSetting> packages) {
+ class PublicKeyHandle {
+ private final PublicKey mKey;
+ private final long mId;
+ private int mRefCount;
+
+ public PublicKeyHandle(long id, PublicKey key) {
+ mId = id;
+ mRefCount = 1;
+ mKey = key;
+ }
+
+ /*
+ * Only used when reading state from packages.xml
+ */
+ private PublicKeyHandle(long id, int refCount, PublicKey key) {
+ mId = id;
+ mRefCount = refCount;
+ mKey = key;
+ }
+
+ public long getId() {
+ return mId;
+ }
+
+ public PublicKey getKey() {
+ return mKey;
+ }
+
+ public int getRefCountLPr() {
+ return mRefCount;
+ }
+
+ public void incrRefCountLPw() {
+ mRefCount++;
+ return;
+ }
+ public long decrRefCountLPw() {
+ mRefCount--;
+ return mRefCount;
+ }
+ }
+
+ public KeySetManagerService(ArrayMap<String, PackageSetting> packages) {
mKeySets = new LongSparseArray<KeySetHandle>();
- mPublicKeys = new LongSparseArray<PublicKey>();
+ mPublicKeys = new LongSparseArray<PublicKeyHandle>();
mKeySetMapping = new LongSparseArray<ArraySet<Long>>();
mPackages = packages;
}
@@ -92,7 +134,9 @@ public class KeySetManagerService {
if (id == KEYSET_NOT_FOUND) {
return false;
}
- return pkg.keySetData.packageIsSignedBy(id);
+ ArraySet<Long> pkgKeys = mKeySetMapping.get(pkg.keySetData.getProperSigningKeySet());
+ ArraySet<Long> testKeys = mKeySetMapping.get(id);
+ return pkgKeys.containsAll(testKeys);
}
/**
@@ -113,81 +157,45 @@ public class KeySetManagerService {
|| pkg.keySetData.getProperSigningKeySet()
== PackageKeySetData.KEYSET_UNASSIGNED) {
throw new NullPointerException("Package has no KeySet data");
- }
+ }
long id = getIdByKeySetLPr(ks);
- return pkg.keySetData.getProperSigningKeySet() == id;
- }
-
- /**
- * This informs the system that the given package has defined a KeySet
- * in its manifest that a) contains the given keys and b) is named
- * alias by that package.
- */
- public void addDefinedKeySetToPackageLPw(String packageName,
- ArraySet<PublicKey> keys, String alias) {
- if ((packageName == null) || (keys == null) || (alias == null)) {
- Slog.w(TAG, "Got null argument for a defined keyset, ignoring!");
- return;
- }
- PackageSetting pkg = mPackages.get(packageName);
- if (pkg == null) {
- throw new NullPointerException("Unknown package");
- }
- // Add to KeySets, then to package
- KeySetHandle ks = addKeySetLPw(keys);
- long id = getIdByKeySetLPr(ks);
- pkg.keySetData.addDefinedKeySet(id, alias);
- }
-
- /**
- * This informs the system that the given package has defined a KeySet
- * alias in its manifest to be an upgradeKeySet. This must be called
- * after all of the defined KeySets have been added.
- */
- public void addUpgradeKeySetToPackageLPw(String packageName, String alias) {
- if ((packageName == null) || (alias == null)) {
- Slog.w(TAG, "Got null argument for a defined keyset, ignoring!");
- return;
- }
- PackageSetting pkg = mPackages.get(packageName);
- if (pkg == null) {
- throw new NullPointerException("Unknown package");
+ if (id == KEYSET_NOT_FOUND) {
+ return false;
}
- pkg.keySetData.addUpgradeKeySet(alias);
+ ArraySet<Long> pkgKeys = mKeySetMapping.get(pkg.keySetData.getProperSigningKeySet());
+ ArraySet<Long> testKeys = mKeySetMapping.get(id);
+ return pkgKeys.equals(testKeys);
}
/**
- * Similar to the above, this informs the system that the given package
- * was signed by the provided KeySet.
+ * Informs the system that the given package was signed by the provided KeySet.
*/
public void addSigningKeySetToPackageLPw(String packageName,
ArraySet<PublicKey> signingKeys) {
- if ((packageName == null) || (signingKeys == null)) {
- Slog.w(TAG, "Got null argument for a signing keyset, ignoring!");
- return;
- }
- // add the signing KeySet
- KeySetHandle ks = addKeySetLPw(signingKeys);
- long id = getIdByKeySetLPr(ks);
- ArraySet<Long> publicKeyIds = mKeySetMapping.get(id);
- if (publicKeyIds == null) {
- throw new NullPointerException("Got invalid KeySet id");
- }
- // attach it to the package
+
+ /* check existing keyset for reuse or removal */
PackageSetting pkg = mPackages.get(packageName);
- if (pkg == null) {
- throw new NullPointerException("No such package!");
- }
- pkg.keySetData.setProperSigningKeySet(id);
- // for each KeySet which is a subset of the one above, add the
- // KeySet id to the package's signing KeySets
- for (int keySetIndex = 0; keySetIndex < mKeySets.size(); keySetIndex++) {
- long keySetID = mKeySets.keyAt(keySetIndex);
- ArraySet<Long> definedKeys = mKeySetMapping.get(keySetID);
- if (publicKeyIds.containsAll(definedKeys)) {
- pkg.keySetData.addSigningKeySet(keySetID);
+ long signingKeySetId = pkg.keySetData.getProperSigningKeySet();
+
+ if (signingKeySetId != PackageKeySetData.KEYSET_UNASSIGNED) {
+ ArraySet<PublicKey> existingKeys = getPublicKeysFromKeySetLPr(signingKeySetId);
+ if (existingKeys.equals(signingKeys)) {
+
+ /* no change in signing keys, leave PackageSetting alone */
+ return;
+ } else {
+
+ /* old keyset no longer valid, remove ref */
+ KeySetHandle ksh = mKeySets.get(signingKeySetId);
+ decrementKeySetLPw(signingKeySetId);
}
}
+
+ /* create and add a new keyset */
+ KeySetHandle ks = addKeySetLPw(signingKeys);
+ long id = ks.getId();
+ pkg.keySetData.setProperSigningKeySet(id);
+ return;
}
/**
@@ -204,25 +212,63 @@ public class KeySetManagerService {
return KEYSET_NOT_FOUND;
}
+ /*
+ * Inform the system that the given package defines the given KeySets.
+ * Remove any KeySets the package no longer defines.
+ */
+ public void addDefinedKeySetsToPackageLPw(String packageName,
+ ArrayMap<String, ArraySet<PublicKey>> definedMapping) {
+ PackageSetting pkg = mPackages.get(packageName);
+ ArrayMap<String, Long> prevDefinedKeySets = pkg.keySetData.getAliases();
+
+ /* add all of the newly defined KeySets */
+ ArrayMap<String, Long> newKeySetAliases = new ArrayMap<String, Long>();
+ final int defMapSize = definedMapping.size();
+ for (int i = 0; i < defMapSize; i++) {
+ String alias = definedMapping.keyAt(i);
+ ArraySet<PublicKey> pubKeys = definedMapping.valueAt(i);
+ if (alias != null && pubKeys != null && pubKeys.size() > 0) {
+ KeySetHandle ks = addKeySetLPw(pubKeys);
+ newKeySetAliases.put(alias, ks.getId());
+ }
+ }
+
+ /* remove each of the old references */
+ final int prevDefSize = prevDefinedKeySets.size();
+ for (int i = 0; i < prevDefSize; i++) {
+ decrementKeySetLPw(prevDefinedKeySets.valueAt(i));
+ }
+ pkg.keySetData.removeAllUpgradeKeySets();
+
+ /* switch to the just-added */
+ pkg.keySetData.setAliases(newKeySetAliases);
+ return;
+ }
+
/**
- * Fetches the KeySet corresponding to the given stable identifier.
- *
- * Returns {@link #KEYSET_NOT_FOUND} if the identifier doesn't
- * identify a {@link KeySet}.
+ * This informs the system that the given package has defined a KeySet
+ * alias in its manifest to be an upgradeKeySet. This must be called
+ * after all of the defined KeySets have been added.
*/
- public KeySetHandle getKeySetByIdLPr(long id) {
- return mKeySets.get(id);
+ public void addUpgradeKeySetsToPackageLPw(String packageName,
+ ArraySet<String> upgradeAliases) {
+ PackageSetting pkg = mPackages.get(packageName);
+ final int uaSize = upgradeAliases.size();
+ for (int i = 0; i < uaSize; i++) {
+ pkg.keySetData.addUpgradeKeySet(upgradeAliases.valueAt(i));
+ }
+ return;
}
/**
- * Fetches the {@link KeySetHandle} that a given package refers to by the
- * provided alias. Returns null if the package is unknown or does not have a
+ * Fetched the {@link KeySetHandle} that a given package refers to by the
+ * provided alias. Returns null if the package is unknown or does not have a
* KeySet corresponding to that alias.
*/
public KeySetHandle getKeySetByAliasAndPackageNameLPr(String packageName, String alias) {
PackageSetting p = mPackages.get(packageName);
if (p == null || p.keySetData == null) {
- return null;
+ return null;
}
Long keySetId = p.keySetData.getAliases().get(alias);
if (keySetId == null) {
@@ -243,8 +289,10 @@ public class KeySetManagerService {
return null;
}
ArraySet<PublicKey> mPubKeys = new ArraySet<PublicKey>();
- for (long pkId : mKeySetMapping.get(id)) {
- mPubKeys.add(mPublicKeys.get(pkId));
+ ArraySet<Long> pkIds = mKeySetMapping.get(id);
+ final int pkSize = pkIds.size();
+ for (int i = 0; i < pkSize; i++) {
+ mPubKeys.add(mPublicKeys.get(pkIds.valueAt(i)).getKey());
}
return mPubKeys;
}
@@ -254,7 +302,7 @@ public class KeySetManagerService {
* package.
*
* @throws IllegalArgumentException if the package has no keyset data.
- * @throws NullPointerException if the package is unknown.
+ * @throws NullPointerException if the packgae is unknown.
*/
public KeySetHandle getSigningKeySetByPackageNameLPr(String packageName) {
PackageSetting p = mPackages.get(packageName);
@@ -268,99 +316,100 @@ public class KeySetManagerService {
}
/**
- * Fetches all the known {@link KeySetHandle KeySets} that may upgrade the given
- * package.
- *
- * @throws IllegalArgumentException if the package has no keyset data.
- * @throws NullPointerException if the package is unknown.
- */
- public ArraySet<KeySetHandle> getUpgradeKeySetsByPackageNameLPr(String packageName) {
- ArraySet<KeySetHandle> upgradeKeySets = new ArraySet<KeySetHandle>();
- PackageSetting p = mPackages.get(packageName);
- if (p == null) {
- throw new NullPointerException("Unknown package");
- }
- if (p.keySetData == null) {
- throw new IllegalArgumentException("Package has no keySet data");
- }
- if (p.keySetData.isUsingUpgradeKeySets()) {
- for (long l : p.keySetData.getUpgradeKeySets()) {
- upgradeKeySets.add(mKeySets.get(l));
- }
- }
- return upgradeKeySets;
- }
-
- /**
* Creates a new KeySet corresponding to the given keys.
*
* If the {@link PublicKey PublicKeys} aren't known to the system, this
- * adds them. Otherwise, they're deduped.
+ * adds them. Otherwise, they're deduped and the reference count
+ * incremented.
*
* If the KeySet isn't known to the system, this adds that and creates the
- * mapping to the PublicKeys. If it is known, then it's deduped.
- *
- * If the KeySet isn't known to the system, this adds it to all appropriate
- * signingKeySets
+ * mapping to the PublicKeys. If it is known, then it's deduped and the
+ * reference count is incremented.
*
* Throws if the provided set is {@code null}.
*/
private KeySetHandle addKeySetLPw(ArraySet<PublicKey> keys) {
- if (keys == null) {
- throw new NullPointerException("Provided keys cannot be null");
+ if (keys == null || keys.size() == 0) {
+ throw new IllegalArgumentException("Cannot add an empty set of keys!");
}
- // add each of the keys in the provided set
+
+ /* add each of the keys in the provided set */
ArraySet<Long> addedKeyIds = new ArraySet<Long>(keys.size());
- for (PublicKey k : keys) {
- long id = addPublicKeyLPw(k);
+ final int kSize = keys.size();
+ for (int i = 0; i < kSize; i++) {
+ long id = addPublicKeyLPw(keys.valueAt(i));
addedKeyIds.add(id);
}
- // check to see if the resulting keyset is new
+ /* check to see if the resulting keyset is new */
long existingKeySetId = getIdFromKeyIdsLPr(addedKeyIds);
if (existingKeySetId != KEYSET_NOT_FOUND) {
- return mKeySets.get(existingKeySetId);
+
+ /* public keys were incremented, but we aren't adding a new keyset: undo */
+ for (int i = 0; i < kSize; i++) {
+ decrementPublicKeyLPw(addedKeyIds.valueAt(i));
+ }
+ KeySetHandle ks = mKeySets.get(existingKeySetId);
+ ks.incrRefCountLPw();
+ return ks;
}
- // create the KeySet object
- KeySetHandle ks = new KeySetHandle();
- // get the first unoccupied slot in mKeySets
+ // get the next keyset id
long id = getFreeKeySetIDLPw();
- // add the KeySet object to it
+
+ // create the KeySet object and add to mKeySets and mapping
+ KeySetHandle ks = new KeySetHandle(id);
mKeySets.put(id, ks);
- // add the stable key ids to the mapping
mKeySetMapping.put(id, addedKeyIds);
- // add this KeySet id to all packages which are signed by it
- for (String pkgName : mPackages.keySet()) {
- PackageSetting p = mPackages.get(pkgName);
- if (p.keySetData != null) {
- long pProperSigning = p.keySetData.getProperSigningKeySet();
- if (pProperSigning != PackageKeySetData.KEYSET_UNASSIGNED) {
- ArraySet<Long> pSigningKeys = mKeySetMapping.get(pProperSigning);
- if (pSigningKeys.containsAll(addedKeyIds)) {
- p.keySetData.addSigningKeySet(id);
- }
- }
+ return ks;
+ }
+
+ /*
+ * Decrements the reference to KeySet represented by the given id. If this
+ * drops to zero, then also decrement the reference to each public key it
+ * contains and remove the KeySet.
+ */
+ private void decrementKeySetLPw(long id) {
+ KeySetHandle ks = mKeySets.get(id);
+ if (ks.decrRefCountLPw() <= 0) {
+ ArraySet<Long> pubKeys = mKeySetMapping.get(id);
+ final int pkSize = pubKeys.size();
+ for (int i = 0; i < pkSize; i++) {
+ decrementPublicKeyLPw(pubKeys.valueAt(i));
}
+ mKeySets.delete(id);
+ mKeySetMapping.delete(id);
}
- // go home
- return ks;
+ return;
+ }
+
+ /*
+ * Decrements the reference to PublicKey represented by the given id. If
+ * this drops to zero, then remove it.
+ */
+ private void decrementPublicKeyLPw(long id) {
+ PublicKeyHandle pk = mPublicKeys.get(id);
+ if (pk.decrRefCountLPw() <= 0) {
+ mPublicKeys.delete(id);
+ }
+ return;
}
/**
* Adds the given PublicKey to the system, deduping as it goes.
*/
private long addPublicKeyLPw(PublicKey key) {
- // check if the public key is new
- long existingKeyId = getIdForPublicKeyLPr(key);
- if (existingKeyId != PUBLIC_KEY_NOT_FOUND) {
- return existingKeyId;
- }
- // if it's new find the first unoccupied slot in the public keys
- long id = getFreePublicKeyIdLPw();
- // add the public key to it
- mPublicKeys.put(id, key);
- // return the stable identifier
+ long id = getIdForPublicKeyLPr(key);
+ if (id != PUBLIC_KEY_NOT_FOUND) {
+
+ /* We already know about this key, increment its ref count and ret */
+ mPublicKeys.get(id).incrRefCountLPw();
+ return id;
+ }
+
+ /* if it's new find the first unoccupied slot in the public keys */
+ id = getFreePublicKeyIdLPw();
+ mPublicKeys.put(id, new PublicKeyHandle(id, key));
return id;
}
@@ -385,7 +434,7 @@ public class KeySetManagerService {
private long getIdForPublicKeyLPr(PublicKey k) {
String encodedPublicKey = new String(k.getEncoded());
for (int publicKeyIndex = 0; publicKeyIndex < mPublicKeys.size(); publicKeyIndex++) {
- PublicKey value = mPublicKeys.valueAt(publicKeyIndex);
+ PublicKey value = mPublicKeys.valueAt(publicKeyIndex).getKey();
String encodedExistingKey = new String(value.getEncoded());
if (encodedPublicKey.equals(encodedExistingKey)) {
return mPublicKeys.keyAt(publicKeyIndex);
@@ -410,83 +459,32 @@ public class KeySetManagerService {
return lastIssuedKeyId;
}
+ /*
+ * This package is being removed from the system, so we need to
+ * remove its keyset and public key references, then remove its
+ * keyset data.
+ */
public void removeAppKeySetDataLPw(String packageName) {
- // Get the package's known keys and KeySets
- ArraySet<Long> deletableKeySets = getOriginalKeySetsByPackageNameLPr(packageName);
- ArraySet<Long> deletableKeys = new ArraySet<Long>();
- final int origDksSize = deletableKeySets.size();
- for (int i = 0; i < origDksSize; i++) {
- ArraySet<Long> knownKeys = mKeySetMapping.get(deletableKeySets.valueAt(i));
- if (knownKeys != null) {
- deletableKeys.addAll(knownKeys);
- }
- }
-
- // Now remove the keys and KeySets on which any other package relies
- for (String pkgName : mPackages.keySet()) {
- if (pkgName.equals(packageName)) {
- continue;
- }
- ArraySet<Long> knownKeySets = getOriginalKeySetsByPackageNameLPr(pkgName);
- deletableKeySets.removeAll(knownKeySets);
- final int kksSize = knownKeySets.size();
- for (int i = 0; i < kksSize; i++) {
- ArraySet<Long> knownKeys = mKeySetMapping.get(knownKeySets.valueAt(i));
- if (knownKeys != null) {
- deletableKeys.removeAll(knownKeys);
- }
- }
- }
-
- // The remaining keys and KeySets are not relied on by any other
- // application and so can be safely deleted.
- final int dksSize = deletableKeySets.size();
- for (int i = 0; i < dksSize; i++) {
- Long ks = deletableKeySets.valueAt(i);
- mKeySets.delete(ks);
- mKeySetMapping.delete(ks);
- }
- final int dkSize = deletableKeys.size();
- for (int i = 0; i < dkSize; i++) {
- mPublicKeys.delete(deletableKeys.valueAt(i));
- }
- // Now remove the deleted KeySets from each package's signingKeySets
- for (String pkgName : mPackages.keySet()) {
- PackageSetting p = mPackages.get(pkgName);
- for (int i = 0; i < dksSize; i++) {
- Long ks = deletableKeySets.valueAt(i);
- p.keySetData.removeSigningKeySet(ks);
- }
+ /* remove refs from common keysets and public keys */
+ PackageSetting pkg = mPackages.get(packageName);
+ long signingKeySetId = pkg.keySetData.getProperSigningKeySet();
+ decrementKeySetLPw(signingKeySetId);
+ ArrayMap<String, Long> definedKeySets = pkg.keySetData.getAliases();
+ for (int i = 0; i < definedKeySets.size(); i++) {
+ decrementKeySetLPw(definedKeySets.valueAt(i));
}
- // Finally, remove all KeySets from the original package
- PackageSetting p = mPackages.get(packageName);
- clearPackageKeySetDataLPw(p);
- }
- private void clearPackageKeySetDataLPw(PackageSetting p) {
- p.keySetData.removeAllSigningKeySets();
- p.keySetData.removeAllUpgradeKeySets();
- p.keySetData.removeAllDefinedKeySets();
+ /* remove from package */
+ clearPackageKeySetDataLPw(pkg);
return;
}
- private ArraySet<Long> getOriginalKeySetsByPackageNameLPr(String packageName) {
- PackageSetting p = mPackages.get(packageName);
- if (p == null) {
- throw new NullPointerException("Unknown package");
- }
- if (p.keySetData == null) {
- throw new IllegalArgumentException("Package has no keySet data");
- }
- ArraySet<Long> knownKeySets = new ArraySet<Long>();
- knownKeySets.add(p.keySetData.getProperSigningKeySet());
- if (p.keySetData.isUsingDefinedKeySets()) {
- for (long ks : p.keySetData.getDefinedKeySets()) {
- knownKeySets.add(ks);
- }
- }
- return knownKeySets;
+ private void clearPackageKeySetDataLPw(PackageSetting pkg) {
+ pkg.keySetData.setProperSigningKeySet(PackageKeySetData.KEYSET_UNASSIGNED);
+ pkg.keySetData.removeAllDefinedKeySets();
+ pkg.keySetData.removeAllUpgradeKeySets();
+ return;
}
public String encodePublicKey(PublicKey k) throws IOException {
@@ -496,7 +494,7 @@ public class KeySetManagerService {
public void dumpLPr(PrintWriter pw, String packageName,
PackageManagerService.DumpState dumpState) {
boolean printedHeader = false;
- for (Map.Entry<String, PackageSetting> e : mPackages.entrySet()) {
+ for (ArrayMap.Entry<String, PackageSetting> e : mPackages.entrySet()) {
String keySetPackage = e.getKey();
if (packageName != null && !packageName.equals(keySetPackage)) {
continue;
@@ -511,7 +509,7 @@ public class KeySetManagerService {
pw.print(" ["); pw.print(keySetPackage); pw.println("]");
if (pkg.keySetData != null) {
boolean printedLabel = false;
- for (Map.Entry<String, Long> entry : pkg.keySetData.getAliases().entrySet()) {
+ for (ArrayMap.Entry<String, Long> entry : pkg.keySetData.getAliases().entrySet()) {
if (!printedLabel) {
pw.print(" KeySets Aliases: ");
printedLabel = true;
@@ -527,36 +525,26 @@ public class KeySetManagerService {
}
printedLabel = false;
if (pkg.keySetData.isUsingDefinedKeySets()) {
- for (long keySetId : pkg.keySetData.getDefinedKeySets()) {
+ ArrayMap<String, Long> definedKeySets = pkg.keySetData.getAliases();
+ final int dksSize = definedKeySets.size();
+ for (int i = 0; i < dksSize; i++) {
if (!printedLabel) {
pw.print(" Defined KeySets: ");
printedLabel = true;
} else {
pw.print(", ");
}
- pw.print(Long.toString(keySetId));
- }
- }
- if (printedLabel) {
- pw.println("");
- }
- printedLabel = false;
- final long[] signingKeySets = pkg.keySetData.getSigningKeySets();
- if (signingKeySets != null) {
- for (long keySetId : signingKeySets) {
- if (!printedLabel) {
- pw.print(" Signing KeySets: ");
- printedLabel = true;
- } else {
- pw.print(", ");
- }
- pw.print(Long.toString(keySetId));
+ pw.print(Long.toString(definedKeySets.valueAt(i)));
}
}
if (printedLabel) {
pw.println("");
}
printedLabel = false;
+ final long signingKeySet = pkg.keySetData.getProperSigningKeySet();
+ pw.print(" Signing KeySets: ");
+ pw.print(Long.toString(signingKeySet));
+ pw.println("");
if (pkg.keySetData.isUsingUpgradeKeySets()) {
for (long keySetId : pkg.keySetData.getUpgradeKeySets()) {
if (!printedLabel) {
@@ -593,8 +581,8 @@ public class KeySetManagerService {
serializer.startTag(null, "keys");
for (int pKeyIndex = 0; pKeyIndex < mPublicKeys.size(); pKeyIndex++) {
long id = mPublicKeys.keyAt(pKeyIndex);
- PublicKey key = mPublicKeys.valueAt(pKeyIndex);
- String encodedKey = encodePublicKey(key);
+ PublicKeyHandle pkh = mPublicKeys.valueAt(pKeyIndex);
+ String encodedKey = encodePublicKey(pkh.getKey());
serializer.startTag(null, "public-key");
serializer.attribute(null, "identifier", Long.toString(id));
serializer.attribute(null, "value", encodedKey);
@@ -620,17 +608,17 @@ public class KeySetManagerService {
serializer.endTag(null, "keysets");
}
- void readKeySetsLPw(XmlPullParser parser)
+ void readKeySetsLPw(XmlPullParser parser, ArrayMap<Long, Integer> keySetRefCounts)
throws XmlPullParserException, IOException {
int type;
long currentKeySetId = 0;
int outerDepth = parser.getDepth();
- String recordedVersion = parser.getAttributeValue(null, "version");
- if (recordedVersion == null || Integer.parseInt(recordedVersion) != CURRENT_VERSION) {
+ String recordedVersionStr = parser.getAttributeValue(null, "version");
+ if (recordedVersionStr == null) {
+ // The keyset information comes from pre-versioned devices, and
+ // is inaccurate, don't collect any of it.
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- // Our version is different than the one which generated the old keyset data.
- // We don't want any of the old data, but we must advance the parser
continue;
}
// The KeySet information read previously from packages.xml is invalid.
@@ -640,6 +628,7 @@ public class KeySetManagerService {
}
return;
}
+ int recordedVersion = Integer.parseInt(recordedVersionStr);
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
@@ -656,6 +645,8 @@ public class KeySetManagerService {
lastIssuedKeySetId = Long.parseLong(parser.getAttributeValue(null, "value"));
}
}
+
+ addRefCountsFromSavedPackagesLPw(keySetRefCounts);
}
void readKeysLPw(XmlPullParser parser)
@@ -686,29 +677,49 @@ public class KeySetManagerService {
}
final String tagName = parser.getName();
if (tagName.equals("keyset")) {
- currentKeySetId = readIdentifierLPw(parser);
- mKeySets.put(currentKeySetId, new KeySetHandle());
+ String encodedID = parser.getAttributeValue(null, "identifier");
+ currentKeySetId = Long.parseLong(encodedID);
+ int refCount = 0;
+ mKeySets.put(currentKeySetId, new KeySetHandle(currentKeySetId, refCount));
mKeySetMapping.put(currentKeySetId, new ArraySet<Long>());
} else if (tagName.equals("key-id")) {
- long id = readIdentifierLPw(parser);
+ String encodedID = parser.getAttributeValue(null, "identifier");
+ long id = Long.parseLong(encodedID);
mKeySetMapping.get(currentKeySetId).add(id);
}
}
}
- long readIdentifierLPw(XmlPullParser parser)
- throws XmlPullParserException {
- return Long.parseLong(parser.getAttributeValue(null, "identifier"));
- }
-
void readPublicKeyLPw(XmlPullParser parser)
throws XmlPullParserException {
String encodedID = parser.getAttributeValue(null, "identifier");
long identifier = Long.parseLong(encodedID);
+ int refCount = 0;
String encodedPublicKey = parser.getAttributeValue(null, "value");
PublicKey pub = PackageParser.parsePublicKey(encodedPublicKey);
if (pub != null) {
- mPublicKeys.put(identifier, pub);
+ PublicKeyHandle pkh = new PublicKeyHandle(identifier, refCount, pub);
+ mPublicKeys.put(identifier, pkh);
+ }
+ }
+
+ /*
+ * Set each KeySet ref count. Also increment all public keys in each keyset.
+ */
+ private void addRefCountsFromSavedPackagesLPw(ArrayMap<Long, Integer> keySetRefCounts) {
+ final int numRefCounts = keySetRefCounts.size();
+ for (int i = 0; i < numRefCounts; i++) {
+ KeySetHandle ks = mKeySets.get(keySetRefCounts.keyAt(i));
+ ks.setRefCountLPw(keySetRefCounts.valueAt(i));
+ }
+
+ final int numKeySets = mKeySets.size();
+ for (int i = 0; i < numKeySets; i++) {
+ ArraySet<Long> pubKeys = mKeySetMapping.valueAt(i);
+ final int pkSize = pubKeys.size();
+ for (int j = 0; j < pkSize; j++) {
+ mPublicKeys.get(pubKeys.valueAt(j)).incrRefCountLPw();
+ }
}
}
}
diff --git a/services/core/java/com/android/server/pm/PackageKeySetData.java b/services/core/java/com/android/server/pm/PackageKeySetData.java
index 8f12c03..a9126c0 100644
--- a/services/core/java/com/android/server/pm/PackageKeySetData.java
+++ b/services/core/java/com/android/server/pm/PackageKeySetData.java
@@ -27,12 +27,8 @@ public class PackageKeySetData {
/* KeySet containing all signing keys - superset of the others */
private long mProperSigningKeySet;
- private long[] mSigningKeySets;
-
private long[] mUpgradeKeySets;
- private long[] mDefinedKeySets;
-
private final ArrayMap<String, Long> mKeySetAliases = new ArrayMap<String, Long>();
PackageKeySetData() {
@@ -41,23 +37,12 @@ public class PackageKeySetData {
PackageKeySetData(PackageKeySetData original) {
mProperSigningKeySet = original.mProperSigningKeySet;
- mSigningKeySets = ArrayUtils.cloneOrNull(original.mSigningKeySets);
mUpgradeKeySets = ArrayUtils.cloneOrNull(original.mUpgradeKeySets);
- mDefinedKeySets = ArrayUtils.cloneOrNull(original.mDefinedKeySets);
mKeySetAliases.putAll(original.mKeySetAliases);
}
protected void setProperSigningKeySet(long ks) {
- if (ks == mProperSigningKeySet) {
-
- /* nothing to change */
- return;
- }
-
- /* otherwise, our current signing keysets are likely invalid */
- removeAllSigningKeySets();
mProperSigningKeySet = ks;
- addSigningKeySet(ks);
return;
}
@@ -65,15 +50,10 @@ public class PackageKeySetData {
return mProperSigningKeySet;
}
- protected void addSigningKeySet(long ks) {
- mSigningKeySets = ArrayUtils.appendLong(mSigningKeySets, ks);
- }
-
- protected void removeSigningKeySet(long ks) {
- mSigningKeySets = ArrayUtils.removeLong(mSigningKeySets, ks);
- }
-
protected void addUpgradeKeySet(String alias) {
+ if (alias == null) {
+ return;
+ }
/* must have previously been defined */
Long ks = mKeySetAliases.get(alias);
@@ -89,19 +69,9 @@ public class PackageKeySetData {
* Used only when restoring keyset data from persistent storage. Must
* correspond to a defined-keyset.
*/
- protected void addUpgradeKeySetById(long ks) {
- mSigningKeySets = ArrayUtils.appendLong(mSigningKeySets, ks);
- }
-
- protected void addDefinedKeySet(long ks, String alias) {
- mDefinedKeySets = ArrayUtils.appendLong(mDefinedKeySets, ks);
- mKeySetAliases.put(alias, ks);
- }
- protected void removeAllSigningKeySets() {
- mProperSigningKeySet = KEYSET_UNASSIGNED;
- mSigningKeySets = null;
- return;
+ protected void addUpgradeKeySetById(long ks) {
+ mUpgradeKeySets = ArrayUtils.appendLong(mUpgradeKeySets, ks);
}
protected void removeAllUpgradeKeySets() {
@@ -109,36 +79,44 @@ public class PackageKeySetData {
return;
}
- protected void removeAllDefinedKeySets() {
- mDefinedKeySets = null;
- mKeySetAliases.clear();
- return;
+ protected long[] getUpgradeKeySets() {
+ return mUpgradeKeySets;
}
- protected boolean packageIsSignedBy(long ks) {
- return ArrayUtils.contains(mSigningKeySets, ks);
+ protected ArrayMap<String, Long> getAliases() {
+ return mKeySetAliases;
}
- protected long[] getSigningKeySets() {
- return mSigningKeySets;
- }
+ /*
+ * Replace defined keysets with new ones.
+ */
+ protected void setAliases(ArrayMap<String, Long> newAliases) {
- protected long[] getUpgradeKeySets() {
- return mUpgradeKeySets;
+ /* remove old aliases */
+ removeAllDefinedKeySets();
+
+ /* add new ones */
+ final int newAliasSize = newAliases.size();
+ for (int i = 0; i < newAliasSize; i++) {
+ mKeySetAliases.put(newAliases.keyAt(i), newAliases.valueAt(i));;
+ }
}
- protected long[] getDefinedKeySets() {
- return mDefinedKeySets;
+ protected void addDefinedKeySet(long ks, String alias) {
+ mKeySetAliases.put(alias, ks);
}
- protected ArrayMap<String, Long> getAliases() {
- return mKeySetAliases;
+ protected void removeAllDefinedKeySets() {
+ final int aliasSize = mKeySetAliases.size();
+ for (int i = 0; i < aliasSize; i++) {
+ mKeySetAliases.removeAt(i);
+ }
}
protected boolean isUsingDefinedKeySets() {
- /* should never be the case that mDefinedKeySets.length == 0 */
- return (mDefinedKeySets != null && mDefinedKeySets.length > 0);
+ /* should never be the case that mUpgradeKeySets.length == 0 */
+ return (mKeySetAliases.size() > 0);
}
protected boolean isUsingUpgradeKeySets() {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 52411bf..df2d3e5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -5885,21 +5885,11 @@ public class PackageManagerService extends IPackageManager.Stub {
// Add the package's KeySets to the global KeySetManagerService
KeySetManagerService ksms = mSettings.mKeySetManagerService;
try {
- // Old KeySetData no longer valid.
- ksms.removeAppKeySetDataLPw(pkg.packageName);
ksms.addSigningKeySetToPackageLPw(pkg.packageName, pkg.mSigningKeys);
if (pkg.mKeySetMapping != null) {
- for (Map.Entry<String, ArraySet<PublicKey>> entry :
- pkg.mKeySetMapping.entrySet()) {
- if (entry.getValue() != null) {
- ksms.addDefinedKeySetToPackageLPw(pkg.packageName,
- entry.getValue(), entry.getKey());
- }
- }
+ ksms.addDefinedKeySetsToPackageLPw(pkg.packageName, pkg.mKeySetMapping);
if (pkg.mUpgradeKeySets != null) {
- for (String upgradeAlias : pkg.mUpgradeKeySets) {
- ksms.addUpgradeKeySetToPackageLPw(pkg.packageName, upgradeAlias);
- }
+ ksms.addUpgradeKeySetsToPackageLPw(pkg.packageName, pkg.mUpgradeKeySets);
}
}
} catch (NullPointerException e) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index b820d7e..3776953 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -223,6 +223,8 @@ final class Settings {
// For reading/writing settings file.
private final ArrayList<Signature> mPastSignatures =
new ArrayList<Signature>();
+ private final ArrayMap<Long, Integer> mKeySetRefs =
+ new ArrayMap<Long, Integer>();
// Mapping from permission names to info about them.
final ArrayMap<String, BasePermission> mPermissions =
@@ -1855,33 +1857,24 @@ final class Settings {
serializer.endTag(null, "perms");
}
- writeSigningKeySetsLPr(serializer, pkg.keySetData);
+ writeSigningKeySetLPr(serializer, pkg.keySetData);
writeUpgradeKeySetsLPr(serializer, pkg.keySetData);
writeKeySetAliasesLPr(serializer, pkg.keySetData);
serializer.endTag(null, "package");
}
- void writeSigningKeySetsLPr(XmlSerializer serializer,
+ void writeSigningKeySetLPr(XmlSerializer serializer,
PackageKeySetData data) throws IOException {
- if (data.getSigningKeySets() != null) {
- // Keep track of the original signing-keyset.
- // Must be recorded first, since it will be read first and wipe the
- // current signing-keysets for the package when set.
- long properSigningKeySet = data.getProperSigningKeySet();
- serializer.startTag(null, "proper-signing-keyset");
- serializer.attribute(null, "identifier", Long.toString(properSigningKeySet));
- serializer.endTag(null, "proper-signing-keyset");
- for (long id : data.getSigningKeySets()) {
- serializer.startTag(null, "signing-keyset");
- serializer.attribute(null, "identifier", Long.toString(id));
- serializer.endTag(null, "signing-keyset");
- }
- }
+ serializer.startTag(null, "proper-signing-keyset");
+ serializer.attribute(null, "identifier",
+ Long.toString(data.getProperSigningKeySet()));
+ serializer.endTag(null, "proper-signing-keyset");
}
void writeUpgradeKeySetsLPr(XmlSerializer serializer,
PackageKeySetData data) throws IOException {
+ long properSigning = data.getProperSigningKeySet();
if (data.isUsingUpgradeKeySets()) {
for (long id : data.getUpgradeKeySets()) {
serializer.startTag(null, "upgrade-keyset");
@@ -1973,6 +1966,7 @@ final class Settings {
mPendingPackages.clear();
mPastSignatures.clear();
+ mKeySetRefs.clear();
try {
if (str == null) {
@@ -2099,7 +2093,7 @@ final class Settings {
final String enforcement = parser.getAttributeValue(null, ATTR_ENFORCEMENT);
mReadExternalStorageEnforced = "1".equals(enforcement);
} else if (tagName.equals("keyset-settings")) {
- mKeySetManagerService.readKeySetsLPw(parser);
+ mKeySetManagerService.readKeySetsLPw(parser, mKeySetRefs);
} else {
Slog.w(PackageManagerService.TAG, "Unknown element under <packages>: "
+ parser.getName());
@@ -2121,6 +2115,7 @@ final class Settings {
}
final int N = mPendingPackages.size();
+
for (int i = 0; i < N; i++) {
final PendingPackage pp = mPendingPackages.get(i);
Object idObj = getUserIdLPr(pp.sharedId);
@@ -2924,16 +2919,27 @@ final class Settings {
packageSetting.permissionsFixed = true;
} else if (tagName.equals("proper-signing-keyset")) {
long id = Long.parseLong(parser.getAttributeValue(null, "identifier"));
+ Integer refCt = mKeySetRefs.get(id);
+ if (refCt != null) {
+ mKeySetRefs.put(id, refCt + 1);
+ } else {
+ mKeySetRefs.put(id, 1);
+ }
packageSetting.keySetData.setProperSigningKeySet(id);
} else if (tagName.equals("signing-keyset")) {
- long id = Long.parseLong(parser.getAttributeValue(null, "identifier"));
- packageSetting.keySetData.addSigningKeySet(id);
+ // from v1 of keysetmanagerservice - no longer used
} else if (tagName.equals("upgrade-keyset")) {
long id = Long.parseLong(parser.getAttributeValue(null, "identifier"));
packageSetting.keySetData.addUpgradeKeySetById(id);
} else if (tagName.equals("defined-keyset")) {
long id = Long.parseLong(parser.getAttributeValue(null, "identifier"));
String alias = parser.getAttributeValue(null, "alias");
+ Integer refCt = mKeySetRefs.get(id);
+ if (refCt != null) {
+ mKeySetRefs.put(id, refCt + 1);
+ } else {
+ mKeySetRefs.put(id, 1);
+ }
packageSetting.keySetData.addDefinedKeySet(id, alias);
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,