KeySetManagerService.java revision 8c04facdf5e76fb34c55cfe3dc9a0216322b91b8
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.pm; 18 19import android.content.pm.PackageParser; 20import android.util.ArrayMap; 21import android.util.ArraySet; 22import android.util.Base64; 23import android.util.Slog; 24import android.util.LongSparseArray; 25 26import java.io.IOException; 27import java.io.PrintWriter; 28import java.security.PublicKey; 29import java.util.Set; 30 31import org.xmlpull.v1.XmlPullParser; 32import org.xmlpull.v1.XmlPullParserException; 33import org.xmlpull.v1.XmlSerializer; 34 35/* 36 * Manages system-wide KeySet state. 37 */ 38public class KeySetManagerService { 39 40 static final String TAG = "KeySetManagerService"; 41 42 /* original keysets implementation had no versioning info, so this is the first */ 43 public static final int FIRST_VERSION = 1; 44 45 public static final int CURRENT_VERSION = FIRST_VERSION; 46 47 /** Sentinel value returned when a {@code KeySet} is not found. */ 48 public static final long KEYSET_NOT_FOUND = -1; 49 50 /** Sentinel value returned when public key is not found. */ 51 protected static final long PUBLIC_KEY_NOT_FOUND = -1; 52 53 private final LongSparseArray<KeySetHandle> mKeySets; 54 55 private final LongSparseArray<PublicKeyHandle> mPublicKeys; 56 57 protected final LongSparseArray<ArraySet<Long>> mKeySetMapping; 58 59 private final ArrayMap<String, PackageSetting> mPackages; 60 61 private static long lastIssuedKeySetId = 0; 62 63 private static long lastIssuedKeyId = 0; 64 65 class PublicKeyHandle { 66 private final PublicKey mKey; 67 private final long mId; 68 private int mRefCount; 69 70 public PublicKeyHandle(long id, PublicKey key) { 71 mId = id; 72 mRefCount = 1; 73 mKey = key; 74 } 75 76 /* 77 * Only used when reading state from packages.xml 78 */ 79 private PublicKeyHandle(long id, int refCount, PublicKey key) { 80 mId = id; 81 mRefCount = refCount; 82 mKey = key; 83 } 84 85 public long getId() { 86 return mId; 87 } 88 89 public PublicKey getKey() { 90 return mKey; 91 } 92 93 public int getRefCountLPr() { 94 return mRefCount; 95 } 96 97 public void incrRefCountLPw() { 98 mRefCount++; 99 return; 100 } 101 public long decrRefCountLPw() { 102 mRefCount--; 103 return mRefCount; 104 } 105 } 106 107 public KeySetManagerService(ArrayMap<String, PackageSetting> packages) { 108 mKeySets = new LongSparseArray<KeySetHandle>(); 109 mPublicKeys = new LongSparseArray<PublicKeyHandle>(); 110 mKeySetMapping = new LongSparseArray<ArraySet<Long>>(); 111 mPackages = packages; 112 } 113 114 /** 115 * Determine if a package is signed by the given KeySet. 116 * 117 * Returns false if the package was not signed by all the 118 * keys in the KeySet. 119 * 120 * Returns true if the package was signed by at least the 121 * keys in the given KeySet. 122 * 123 * Note that this can return true for multiple KeySets. 124 */ 125 public boolean packageIsSignedByLPr(String packageName, KeySetHandle ks) { 126 PackageSetting pkg = mPackages.get(packageName); 127 if (pkg == null) { 128 throw new NullPointerException("Invalid package name"); 129 } 130 if (pkg.keySetData == null) { 131 throw new NullPointerException("Package has no KeySet data"); 132 } 133 long id = getIdByKeySetLPr(ks); 134 if (id == KEYSET_NOT_FOUND) { 135 return false; 136 } 137 ArraySet<Long> pkgKeys = mKeySetMapping.get(pkg.keySetData.getProperSigningKeySet()); 138 ArraySet<Long> testKeys = mKeySetMapping.get(id); 139 return pkgKeys.containsAll(testKeys); 140 } 141 142 /** 143 * Determine if a package is signed by the given KeySet. 144 * 145 * Returns false if the package was not signed by all the 146 * keys in the KeySet, or if the package was signed by keys 147 * not in the KeySet. 148 * 149 * Note that this can return only for one KeySet. 150 */ 151 public boolean packageIsSignedByExactlyLPr(String packageName, KeySetHandle ks) { 152 PackageSetting pkg = mPackages.get(packageName); 153 if (pkg == null) { 154 throw new NullPointerException("Invalid package name"); 155 } 156 if (pkg.keySetData == null 157 || pkg.keySetData.getProperSigningKeySet() 158 == PackageKeySetData.KEYSET_UNASSIGNED) { 159 throw new NullPointerException("Package has no KeySet data"); 160 } 161 long id = getIdByKeySetLPr(ks); 162 if (id == KEYSET_NOT_FOUND) { 163 return false; 164 } 165 ArraySet<Long> pkgKeys = mKeySetMapping.get(pkg.keySetData.getProperSigningKeySet()); 166 ArraySet<Long> testKeys = mKeySetMapping.get(id); 167 return pkgKeys.equals(testKeys); 168 } 169 170 /** 171 * Informs the system that the given package was signed by the provided KeySet. 172 */ 173 public void addSigningKeySetToPackageLPw(String packageName, 174 ArraySet<PublicKey> signingKeys) { 175 176 /* check existing keyset for reuse or removal */ 177 PackageSetting pkg = mPackages.get(packageName); 178 long signingKeySetId = pkg.keySetData.getProperSigningKeySet(); 179 180 if (signingKeySetId != PackageKeySetData.KEYSET_UNASSIGNED) { 181 ArraySet<PublicKey> existingKeys = getPublicKeysFromKeySetLPr(signingKeySetId); 182 if (existingKeys.equals(signingKeys)) { 183 184 /* no change in signing keys, leave PackageSetting alone */ 185 return; 186 } else { 187 188 /* old keyset no longer valid, remove ref */ 189 KeySetHandle ksh = mKeySets.get(signingKeySetId); 190 decrementKeySetLPw(signingKeySetId); 191 } 192 } 193 194 /* create and add a new keyset */ 195 KeySetHandle ks = addKeySetLPw(signingKeys); 196 long id = ks.getId(); 197 pkg.keySetData.setProperSigningKeySet(id); 198 return; 199 } 200 201 /** 202 * Fetches the stable identifier associated with the given KeySet. Returns 203 * {@link #KEYSET_NOT_FOUND} if the KeySet... wasn't found. 204 */ 205 private long getIdByKeySetLPr(KeySetHandle ks) { 206 for (int keySetIndex = 0; keySetIndex < mKeySets.size(); keySetIndex++) { 207 KeySetHandle value = mKeySets.valueAt(keySetIndex); 208 if (ks.equals(value)) { 209 return mKeySets.keyAt(keySetIndex); 210 } 211 } 212 return KEYSET_NOT_FOUND; 213 } 214 215 /* 216 * Inform the system that the given package defines the given KeySets. 217 * Remove any KeySets the package no longer defines. 218 */ 219 public void addDefinedKeySetsToPackageLPw(String packageName, 220 ArrayMap<String, ArraySet<PublicKey>> definedMapping) { 221 PackageSetting pkg = mPackages.get(packageName); 222 ArrayMap<String, Long> prevDefinedKeySets = pkg.keySetData.getAliases(); 223 224 /* add all of the newly defined KeySets */ 225 ArrayMap<String, Long> newKeySetAliases = new ArrayMap<String, Long>(); 226 final int defMapSize = definedMapping.size(); 227 for (int i = 0; i < defMapSize; i++) { 228 String alias = definedMapping.keyAt(i); 229 ArraySet<PublicKey> pubKeys = definedMapping.valueAt(i); 230 if (alias != null && pubKeys != null && pubKeys.size() > 0) { 231 KeySetHandle ks = addKeySetLPw(pubKeys); 232 newKeySetAliases.put(alias, ks.getId()); 233 } 234 } 235 236 /* remove each of the old references */ 237 final int prevDefSize = prevDefinedKeySets.size(); 238 for (int i = 0; i < prevDefSize; i++) { 239 decrementKeySetLPw(prevDefinedKeySets.valueAt(i)); 240 } 241 pkg.keySetData.removeAllUpgradeKeySets(); 242 243 /* switch to the just-added */ 244 pkg.keySetData.setAliases(newKeySetAliases); 245 return; 246 } 247 248 /** 249 * This informs the system that the given package has defined a KeySet 250 * alias in its manifest to be an upgradeKeySet. This must be called 251 * after all of the defined KeySets have been added. 252 */ 253 public void addUpgradeKeySetsToPackageLPw(String packageName, 254 ArraySet<String> upgradeAliases) { 255 PackageSetting pkg = mPackages.get(packageName); 256 final int uaSize = upgradeAliases.size(); 257 for (int i = 0; i < uaSize; i++) { 258 pkg.keySetData.addUpgradeKeySet(upgradeAliases.valueAt(i)); 259 } 260 return; 261 } 262 263 /** 264 * Fetched the {@link KeySetHandle} that a given package refers to by the 265 * provided alias. Returns null if the package is unknown or does not have a 266 * KeySet corresponding to that alias. 267 */ 268 public KeySetHandle getKeySetByAliasAndPackageNameLPr(String packageName, String alias) { 269 PackageSetting p = mPackages.get(packageName); 270 if (p == null || p.keySetData == null) { 271 return null; 272 } 273 Long keySetId = p.keySetData.getAliases().get(alias); 274 if (keySetId == null) { 275 throw new IllegalArgumentException("Unknown KeySet alias: " + alias); 276 } 277 return mKeySets.get(keySetId); 278 } 279 280 /** 281 * Fetches the {@link PublicKey public keys} which belong to the specified 282 * KeySet id. 283 * 284 * Returns {@code null} if the identifier doesn't 285 * identify a {@link KeySetHandle}. 286 */ 287 public ArraySet<PublicKey> getPublicKeysFromKeySetLPr(long id) { 288 if(mKeySetMapping.get(id) == null) { 289 return null; 290 } 291 ArraySet<PublicKey> mPubKeys = new ArraySet<PublicKey>(); 292 ArraySet<Long> pkIds = mKeySetMapping.get(id); 293 final int pkSize = pkIds.size(); 294 for (int i = 0; i < pkSize; i++) { 295 mPubKeys.add(mPublicKeys.get(pkIds.valueAt(i)).getKey()); 296 } 297 return mPubKeys; 298 } 299 300 /** 301 * Fetches the proper {@link KeySetHandle KeySet} that signed the given 302 * package. 303 * 304 * @throws IllegalArgumentException if the package has no keyset data. 305 * @throws NullPointerException if the packgae is unknown. 306 */ 307 public KeySetHandle getSigningKeySetByPackageNameLPr(String packageName) { 308 PackageSetting p = mPackages.get(packageName); 309 if (p == null 310 || p.keySetData == null 311 || p.keySetData.getProperSigningKeySet() 312 == PackageKeySetData.KEYSET_UNASSIGNED) { 313 return null; 314 } 315 return mKeySets.get(p.keySetData.getProperSigningKeySet()); 316 } 317 318 /** 319 * Creates a new KeySet corresponding to the given keys. 320 * 321 * If the {@link PublicKey PublicKeys} aren't known to the system, this 322 * adds them. Otherwise, they're deduped and the reference count 323 * incremented. 324 * 325 * If the KeySet isn't known to the system, this adds that and creates the 326 * mapping to the PublicKeys. If it is known, then it's deduped and the 327 * reference count is incremented. 328 * 329 * Throws if the provided set is {@code null}. 330 */ 331 private KeySetHandle addKeySetLPw(ArraySet<PublicKey> keys) { 332 if (keys == null || keys.size() == 0) { 333 throw new IllegalArgumentException("Cannot add an empty set of keys!"); 334 } 335 336 /* add each of the keys in the provided set */ 337 ArraySet<Long> addedKeyIds = new ArraySet<Long>(keys.size()); 338 final int kSize = keys.size(); 339 for (int i = 0; i < kSize; i++) { 340 long id = addPublicKeyLPw(keys.valueAt(i)); 341 addedKeyIds.add(id); 342 } 343 344 /* check to see if the resulting keyset is new */ 345 long existingKeySetId = getIdFromKeyIdsLPr(addedKeyIds); 346 if (existingKeySetId != KEYSET_NOT_FOUND) { 347 348 /* public keys were incremented, but we aren't adding a new keyset: undo */ 349 for (int i = 0; i < kSize; i++) { 350 decrementPublicKeyLPw(addedKeyIds.valueAt(i)); 351 } 352 KeySetHandle ks = mKeySets.get(existingKeySetId); 353 ks.incrRefCountLPw(); 354 return ks; 355 } 356 357 // get the next keyset id 358 long id = getFreeKeySetIDLPw(); 359 360 // create the KeySet object and add to mKeySets and mapping 361 KeySetHandle ks = new KeySetHandle(id); 362 mKeySets.put(id, ks); 363 mKeySetMapping.put(id, addedKeyIds); 364 return ks; 365 } 366 367 /* 368 * Decrements the reference to KeySet represented by the given id. If this 369 * drops to zero, then also decrement the reference to each public key it 370 * contains and remove the KeySet. 371 */ 372 private void decrementKeySetLPw(long id) { 373 KeySetHandle ks = mKeySets.get(id); 374 if (ks.decrRefCountLPw() <= 0) { 375 ArraySet<Long> pubKeys = mKeySetMapping.get(id); 376 final int pkSize = pubKeys.size(); 377 for (int i = 0; i < pkSize; i++) { 378 decrementPublicKeyLPw(pubKeys.valueAt(i)); 379 } 380 mKeySets.delete(id); 381 mKeySetMapping.delete(id); 382 } 383 return; 384 } 385 386 /* 387 * Decrements the reference to PublicKey represented by the given id. If 388 * this drops to zero, then remove it. 389 */ 390 private void decrementPublicKeyLPw(long id) { 391 PublicKeyHandle pk = mPublicKeys.get(id); 392 if (pk.decrRefCountLPw() <= 0) { 393 mPublicKeys.delete(id); 394 } 395 return; 396 } 397 398 /** 399 * Adds the given PublicKey to the system, deduping as it goes. 400 */ 401 private long addPublicKeyLPw(PublicKey key) { 402 long id = getIdForPublicKeyLPr(key); 403 if (id != PUBLIC_KEY_NOT_FOUND) { 404 405 /* We already know about this key, increment its ref count and ret */ 406 mPublicKeys.get(id).incrRefCountLPw(); 407 return id; 408 } 409 410 /* if it's new find the first unoccupied slot in the public keys */ 411 id = getFreePublicKeyIdLPw(); 412 mPublicKeys.put(id, new PublicKeyHandle(id, key)); 413 return id; 414 } 415 416 /** 417 * Finds the stable identifier for a KeySet based on a set of PublicKey stable IDs. 418 * 419 * Returns KEYSET_NOT_FOUND if there isn't one. 420 */ 421 private long getIdFromKeyIdsLPr(Set<Long> publicKeyIds) { 422 for (int keyMapIndex = 0; keyMapIndex < mKeySetMapping.size(); keyMapIndex++) { 423 ArraySet<Long> value = mKeySetMapping.valueAt(keyMapIndex); 424 if (value.equals(publicKeyIds)) { 425 return mKeySetMapping.keyAt(keyMapIndex); 426 } 427 } 428 return KEYSET_NOT_FOUND; 429 } 430 431 /** 432 * Finds the stable identifier for a PublicKey or PUBLIC_KEY_NOT_FOUND. 433 */ 434 private long getIdForPublicKeyLPr(PublicKey k) { 435 String encodedPublicKey = new String(k.getEncoded()); 436 for (int publicKeyIndex = 0; publicKeyIndex < mPublicKeys.size(); publicKeyIndex++) { 437 PublicKey value = mPublicKeys.valueAt(publicKeyIndex).getKey(); 438 String encodedExistingKey = new String(value.getEncoded()); 439 if (encodedPublicKey.equals(encodedExistingKey)) { 440 return mPublicKeys.keyAt(publicKeyIndex); 441 } 442 } 443 return PUBLIC_KEY_NOT_FOUND; 444 } 445 446 /** 447 * Gets an unused stable identifier for a KeySet. 448 */ 449 private long getFreeKeySetIDLPw() { 450 lastIssuedKeySetId += 1; 451 return lastIssuedKeySetId; 452 } 453 454 /** 455 * Same as above, but for public keys. 456 */ 457 private long getFreePublicKeyIdLPw() { 458 lastIssuedKeyId += 1; 459 return lastIssuedKeyId; 460 } 461 462 /* 463 * This package is being removed from the system, so we need to 464 * remove its keyset and public key references, then remove its 465 * keyset data. 466 */ 467 public void removeAppKeySetDataLPw(String packageName) { 468 469 /* remove refs from common keysets and public keys */ 470 PackageSetting pkg = mPackages.get(packageName); 471 long signingKeySetId = pkg.keySetData.getProperSigningKeySet(); 472 decrementKeySetLPw(signingKeySetId); 473 ArrayMap<String, Long> definedKeySets = pkg.keySetData.getAliases(); 474 for (int i = 0; i < definedKeySets.size(); i++) { 475 decrementKeySetLPw(definedKeySets.valueAt(i)); 476 } 477 478 /* remove from package */ 479 clearPackageKeySetDataLPw(pkg); 480 return; 481 } 482 483 private void clearPackageKeySetDataLPw(PackageSetting pkg) { 484 pkg.keySetData.setProperSigningKeySet(PackageKeySetData.KEYSET_UNASSIGNED); 485 pkg.keySetData.removeAllDefinedKeySets(); 486 pkg.keySetData.removeAllUpgradeKeySets(); 487 return; 488 } 489 490 public String encodePublicKey(PublicKey k) throws IOException { 491 return new String(Base64.encode(k.getEncoded(), 0)); 492 } 493 494 public void dumpLPr(PrintWriter pw, String packageName, 495 PackageManagerService.DumpState dumpState) { 496 boolean printedHeader = false; 497 for (ArrayMap.Entry<String, PackageSetting> e : mPackages.entrySet()) { 498 String keySetPackage = e.getKey(); 499 if (packageName != null && !packageName.equals(keySetPackage)) { 500 continue; 501 } 502 if (!printedHeader) { 503 if (dumpState.onTitlePrinted()) 504 pw.println(); 505 pw.println("Key Set Manager:"); 506 printedHeader = true; 507 } 508 PackageSetting pkg = e.getValue(); 509 pw.print(" ["); pw.print(keySetPackage); pw.println("]"); 510 if (pkg.keySetData != null) { 511 boolean printedLabel = false; 512 for (ArrayMap.Entry<String, Long> entry : pkg.keySetData.getAliases().entrySet()) { 513 if (!printedLabel) { 514 pw.print(" KeySets Aliases: "); 515 printedLabel = true; 516 } else { 517 pw.print(", "); 518 } 519 pw.print(entry.getKey()); 520 pw.print('='); 521 pw.print(Long.toString(entry.getValue())); 522 } 523 if (printedLabel) { 524 pw.println(""); 525 } 526 printedLabel = false; 527 if (pkg.keySetData.isUsingDefinedKeySets()) { 528 ArrayMap<String, Long> definedKeySets = pkg.keySetData.getAliases(); 529 final int dksSize = definedKeySets.size(); 530 for (int i = 0; i < dksSize; i++) { 531 if (!printedLabel) { 532 pw.print(" Defined KeySets: "); 533 printedLabel = true; 534 } else { 535 pw.print(", "); 536 } 537 pw.print(Long.toString(definedKeySets.valueAt(i))); 538 } 539 } 540 if (printedLabel) { 541 pw.println(""); 542 } 543 printedLabel = false; 544 final long signingKeySet = pkg.keySetData.getProperSigningKeySet(); 545 pw.print(" Signing KeySets: "); 546 pw.print(Long.toString(signingKeySet)); 547 pw.println(""); 548 if (pkg.keySetData.isUsingUpgradeKeySets()) { 549 for (long keySetId : pkg.keySetData.getUpgradeKeySets()) { 550 if (!printedLabel) { 551 pw.print(" Upgrade KeySets: "); 552 printedLabel = true; 553 } else { 554 pw.print(", "); 555 } 556 pw.print(Long.toString(keySetId)); 557 } 558 } 559 if (printedLabel) { 560 pw.println(""); 561 } 562 } 563 } 564 } 565 566 void writeKeySetManagerServiceLPr(XmlSerializer serializer) throws IOException { 567 serializer.startTag(null, "keyset-settings"); 568 serializer.attribute(null, "version", Integer.toString(CURRENT_VERSION)); 569 writePublicKeysLPr(serializer); 570 writeKeySetsLPr(serializer); 571 serializer.startTag(null, "lastIssuedKeyId"); 572 serializer.attribute(null, "value", Long.toString(lastIssuedKeyId)); 573 serializer.endTag(null, "lastIssuedKeyId"); 574 serializer.startTag(null, "lastIssuedKeySetId"); 575 serializer.attribute(null, "value", Long.toString(lastIssuedKeySetId)); 576 serializer.endTag(null, "lastIssuedKeySetId"); 577 serializer.endTag(null, "keyset-settings"); 578 } 579 580 void writePublicKeysLPr(XmlSerializer serializer) throws IOException { 581 serializer.startTag(null, "keys"); 582 for (int pKeyIndex = 0; pKeyIndex < mPublicKeys.size(); pKeyIndex++) { 583 long id = mPublicKeys.keyAt(pKeyIndex); 584 PublicKeyHandle pkh = mPublicKeys.valueAt(pKeyIndex); 585 String encodedKey = encodePublicKey(pkh.getKey()); 586 serializer.startTag(null, "public-key"); 587 serializer.attribute(null, "identifier", Long.toString(id)); 588 serializer.attribute(null, "value", encodedKey); 589 serializer.endTag(null, "public-key"); 590 } 591 serializer.endTag(null, "keys"); 592 } 593 594 void writeKeySetsLPr(XmlSerializer serializer) throws IOException { 595 serializer.startTag(null, "keysets"); 596 for (int keySetIndex = 0; keySetIndex < mKeySetMapping.size(); keySetIndex++) { 597 long id = mKeySetMapping.keyAt(keySetIndex); 598 ArraySet<Long> keys = mKeySetMapping.valueAt(keySetIndex); 599 serializer.startTag(null, "keyset"); 600 serializer.attribute(null, "identifier", Long.toString(id)); 601 for (long keyId : keys) { 602 serializer.startTag(null, "key-id"); 603 serializer.attribute(null, "identifier", Long.toString(keyId)); 604 serializer.endTag(null, "key-id"); 605 } 606 serializer.endTag(null, "keyset"); 607 } 608 serializer.endTag(null, "keysets"); 609 } 610 611 void readKeySetsLPw(XmlPullParser parser, ArrayMap<Long, Integer> keySetRefCounts) 612 throws XmlPullParserException, IOException { 613 int type; 614 long currentKeySetId = 0; 615 int outerDepth = parser.getDepth(); 616 String recordedVersionStr = parser.getAttributeValue(null, "version"); 617 if (recordedVersionStr == null) { 618 // The keyset information comes from pre-versioned devices, and 619 // is inaccurate, don't collect any of it. 620 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 621 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 622 continue; 623 } 624 // The KeySet information read previously from packages.xml is invalid. 625 // Destroy it all. 626 for (PackageSetting p : mPackages.values()) { 627 clearPackageKeySetDataLPw(p); 628 } 629 return; 630 } 631 int recordedVersion = Integer.parseInt(recordedVersionStr); 632 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 633 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 634 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 635 continue; 636 } 637 final String tagName = parser.getName(); 638 if (tagName.equals("keys")) { 639 readKeysLPw(parser); 640 } else if (tagName.equals("keysets")) { 641 readKeySetListLPw(parser); 642 } else if (tagName.equals("lastIssuedKeyId")) { 643 lastIssuedKeyId = Long.parseLong(parser.getAttributeValue(null, "value")); 644 } else if (tagName.equals("lastIssuedKeySetId")) { 645 lastIssuedKeySetId = Long.parseLong(parser.getAttributeValue(null, "value")); 646 } 647 } 648 649 addRefCountsFromSavedPackagesLPw(keySetRefCounts); 650 } 651 652 void readKeysLPw(XmlPullParser parser) 653 throws XmlPullParserException, IOException { 654 int outerDepth = parser.getDepth(); 655 int type; 656 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 657 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 658 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 659 continue; 660 } 661 final String tagName = parser.getName(); 662 if (tagName.equals("public-key")) { 663 readPublicKeyLPw(parser); 664 } 665 } 666 } 667 668 void readKeySetListLPw(XmlPullParser parser) 669 throws XmlPullParserException, IOException { 670 int outerDepth = parser.getDepth(); 671 int type; 672 long currentKeySetId = 0; 673 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 674 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 675 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 676 continue; 677 } 678 final String tagName = parser.getName(); 679 if (tagName.equals("keyset")) { 680 String encodedID = parser.getAttributeValue(null, "identifier"); 681 currentKeySetId = Long.parseLong(encodedID); 682 int refCount = 0; 683 mKeySets.put(currentKeySetId, new KeySetHandle(currentKeySetId, refCount)); 684 mKeySetMapping.put(currentKeySetId, new ArraySet<Long>()); 685 } else if (tagName.equals("key-id")) { 686 String encodedID = parser.getAttributeValue(null, "identifier"); 687 long id = Long.parseLong(encodedID); 688 mKeySetMapping.get(currentKeySetId).add(id); 689 } 690 } 691 } 692 693 void readPublicKeyLPw(XmlPullParser parser) 694 throws XmlPullParserException { 695 String encodedID = parser.getAttributeValue(null, "identifier"); 696 long identifier = Long.parseLong(encodedID); 697 int refCount = 0; 698 String encodedPublicKey = parser.getAttributeValue(null, "value"); 699 PublicKey pub = PackageParser.parsePublicKey(encodedPublicKey); 700 if (pub != null) { 701 PublicKeyHandle pkh = new PublicKeyHandle(identifier, refCount, pub); 702 mPublicKeys.put(identifier, pkh); 703 } 704 } 705 706 /* 707 * Set each KeySet ref count. Also increment all public keys in each keyset. 708 */ 709 private void addRefCountsFromSavedPackagesLPw(ArrayMap<Long, Integer> keySetRefCounts) { 710 final int numRefCounts = keySetRefCounts.size(); 711 for (int i = 0; i < numRefCounts; i++) { 712 KeySetHandle ks = mKeySets.get(keySetRefCounts.keyAt(i)); 713 ks.setRefCountLPw(keySetRefCounts.valueAt(i)); 714 } 715 716 final int numKeySets = mKeySets.size(); 717 for (int i = 0; i < numKeySets; i++) { 718 ArraySet<Long> pubKeys = mKeySetMapping.valueAt(i); 719 final int pkSize = pubKeys.size(); 720 for (int j = 0; j < pkSize; j++) { 721 mPublicKeys.get(pubKeys.valueAt(j)).incrRefCountLPw(); 722 } 723 } 724 } 725} 726