KeySetManagerService.java revision 5de7377feca5242fe7127e2d4dc7792d4886d365
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.KeySet; 20import android.content.pm.PackageParser; 21import android.os.Binder; 22import android.util.ArraySet; 23import android.util.Base64; 24import android.util.Slog; 25import android.util.LongSparseArray; 26 27import java.io.IOException; 28import java.io.PrintWriter; 29import java.security.PublicKey; 30import java.util.Map; 31import java.util.Set; 32 33import org.xmlpull.v1.XmlPullParser; 34import org.xmlpull.v1.XmlPullParserException; 35import org.xmlpull.v1.XmlSerializer; 36 37/* 38 * Manages system-wide KeySet state. 39 */ 40public class KeySetManagerService { 41 42 static final String TAG = "KeySetManagerService"; 43 44 /* original keysets implementation had no versioning info, so this is the first */ 45 public static final int FIRST_VERSION = 1; 46 47 public static final int CURRENT_VERSION = FIRST_VERSION; 48 49 /** Sentinel value returned when a {@code KeySet} is not found. */ 50 public static final long KEYSET_NOT_FOUND = -1; 51 52 /** Sentinel value returned when public key is not found. */ 53 protected static final long PUBLIC_KEY_NOT_FOUND = -1; 54 55 private final LongSparseArray<KeySet> mKeySets; 56 57 private final LongSparseArray<PublicKey> mPublicKeys; 58 59 protected final LongSparseArray<ArraySet<Long>> mKeySetMapping; 60 61 private final Map<String, PackageSetting> mPackages; 62 63 private static long lastIssuedKeySetId = 0; 64 65 private static long lastIssuedKeyId = 0; 66 67 public KeySetManagerService(Map<String, PackageSetting> packages) { 68 mKeySets = new LongSparseArray<KeySet>(); 69 mPublicKeys = new LongSparseArray<PublicKey>(); 70 mKeySetMapping = new LongSparseArray<ArraySet<Long>>(); 71 mPackages = packages; 72 } 73 74 /** 75 * Determine if a package is signed by the given KeySet. 76 * 77 * Returns false if the package was not signed by all the 78 * keys in the KeySet. 79 * 80 * Returns true if the package was signed by at least the 81 * keys in the given KeySet. 82 * 83 * Note that this can return true for multiple KeySets. 84 */ 85 public boolean packageIsSignedByLPr(String packageName, KeySet ks) { 86 PackageSetting pkg = mPackages.get(packageName); 87 if (pkg == null) { 88 throw new NullPointerException("Invalid package name"); 89 } 90 if (pkg.keySetData == null) { 91 throw new NullPointerException("Package has no KeySet data"); 92 } 93 long id = getIdByKeySetLPr(ks); 94 return pkg.keySetData.packageIsSignedBy(id); 95 } 96 97 /** 98 * This informs the system that the given package has defined a KeySet 99 * in its manifest that a) contains the given keys and b) is named 100 * alias by that package. 101 */ 102 public void addDefinedKeySetToPackageLPw(String packageName, 103 Set<PublicKey> keys, String alias) { 104 if ((packageName == null) || (keys == null) || (alias == null)) { 105 Slog.w(TAG, "Got null argument for a defined keyset, ignoring!"); 106 return; 107 } 108 PackageSetting pkg = mPackages.get(packageName); 109 if (pkg == null) { 110 throw new NullPointerException("Unknown package"); 111 } 112 // Add to KeySets, then to package 113 KeySet ks = addKeySetLPw(keys); 114 long id = getIdByKeySetLPr(ks); 115 pkg.keySetData.addDefinedKeySet(id, alias); 116 } 117 118 /** 119 * This informs the system that the given package has defined a KeySet 120 * alias in its manifest to be an upgradeKeySet. This must be called 121 * after all of the defined KeySets have been added. 122 */ 123 public void addUpgradeKeySetToPackageLPw(String packageName, String alias) { 124 if ((packageName == null) || (alias == null)) { 125 Slog.w(TAG, "Got null argument for a defined keyset, ignoring!"); 126 return; 127 } 128 PackageSetting pkg = mPackages.get(packageName); 129 if (pkg == null) { 130 throw new NullPointerException("Unknown package"); 131 } 132 pkg.keySetData.addUpgradeKeySet(alias); 133 } 134 135 /** 136 * Similar to the above, this informs the system that the given package 137 * was signed by the provided KeySet. 138 */ 139 public void addSigningKeySetToPackageLPw(String packageName, 140 Set<PublicKey> signingKeys) { 141 if ((packageName == null) || (signingKeys == null)) { 142 Slog.w(TAG, "Got null argument for a signing keyset, ignoring!"); 143 return; 144 } 145 // add the signing KeySet 146 KeySet ks = addKeySetLPw(signingKeys); 147 long id = getIdByKeySetLPr(ks); 148 Set<Long> publicKeyIds = mKeySetMapping.get(id); 149 if (publicKeyIds == null) { 150 throw new NullPointerException("Got invalid KeySet id"); 151 } 152 153 // attach it to the package 154 PackageSetting pkg = mPackages.get(packageName); 155 if (pkg == null) { 156 throw new NullPointerException("No such package!"); 157 } 158 pkg.keySetData.setProperSigningKeySet(id); 159 // for each KeySet which is a subset of the one above, add the 160 // KeySet id to the package's signing KeySets 161 for (int keySetIndex = 0; keySetIndex < mKeySets.size(); keySetIndex++) { 162 long keySetID = mKeySets.keyAt(keySetIndex); 163 Set<Long> definedKeys = mKeySetMapping.get(keySetID); 164 if (publicKeyIds.containsAll(definedKeys)) { 165 pkg.keySetData.addSigningKeySet(keySetID); 166 } 167 } 168 } 169 170 /** 171 * Fetches the stable identifier associated with the given KeySet. Returns 172 * {@link #KEYSET_NOT_FOUND} if the KeySet... wasn't found. 173 */ 174 private long getIdByKeySetLPr(KeySet ks) { 175 for (int keySetIndex = 0; keySetIndex < mKeySets.size(); keySetIndex++) { 176 KeySet value = mKeySets.valueAt(keySetIndex); 177 if (ks.equals(value)) { 178 return mKeySets.keyAt(keySetIndex); 179 } 180 } 181 return KEYSET_NOT_FOUND; 182 } 183 184 /** 185 * Fetches the KeySet corresponding to the given stable identifier. 186 * 187 * Returns {@link #KEYSET_NOT_FOUND} if the identifier doesn't 188 * identify a {@link KeySet}. 189 */ 190 public KeySet getKeySetByIdLPr(long id) { 191 return mKeySets.get(id); 192 } 193 194 /** 195 * Fetches the {@link KeySet} that a given package refers to by the provided alias. 196 * 197 * @throws IllegalArgumentException if the package has no keyset data. 198 * @throws NullPointerException if the package is unknown. 199 */ 200 public KeySet getKeySetByAliasAndPackageNameLPr(String packageName, String alias) { 201 PackageSetting p = mPackages.get(packageName); 202 if (p == null) { 203 throw new NullPointerException("Unknown package"); 204 } 205 if (p.keySetData == null) { 206 throw new IllegalArgumentException("Package has no keySet data"); 207 } 208 long keySetId = p.keySetData.getAliases().get(alias); 209 return mKeySets.get(keySetId); 210 } 211 212 /** 213 * Fetches the {@link PublicKey public keys} which belong to the specified 214 * KeySet id. 215 * 216 * Returns {@code null} if the identifier doesn't 217 * identify a {@link KeySet}. 218 */ 219 public ArraySet<PublicKey> getPublicKeysFromKeySetLPr(long id) { 220 if(mKeySetMapping.get(id) == null) { 221 return null; 222 } 223 ArraySet<PublicKey> mPubKeys = new ArraySet<PublicKey>(); 224 for (long pkId : mKeySetMapping.get(id)) { 225 mPubKeys.add(mPublicKeys.get(pkId)); 226 } 227 return mPubKeys; 228 } 229 230 /** 231 * Fetches all the known {@link KeySet KeySets} that signed the given 232 * package. 233 * 234 * @throws IllegalArgumentException if the package has no keyset data. 235 * @throws NullPointerException if the package is unknown. 236 */ 237 public Set<KeySet> getSigningKeySetsByPackageNameLPr(String packageName) { 238 Set<KeySet> signingKeySets = new ArraySet<KeySet>(); 239 PackageSetting p = mPackages.get(packageName); 240 if (p == null) { 241 throw new NullPointerException("Unknown package"); 242 } 243 if (p.keySetData == null || p.keySetData.getSigningKeySets() == null) { 244 throw new IllegalArgumentException("Package has no keySet data"); 245 } 246 for (long l : p.keySetData.getSigningKeySets()) { 247 signingKeySets.add(mKeySets.get(l)); 248 } 249 return signingKeySets; 250 } 251 252 /** 253 * Fetches all the known {@link KeySet KeySets} that may upgrade the given 254 * package. 255 * 256 * @throws IllegalArgumentException if the package has no keyset data. 257 * @throws NullPointerException if the package is unknown. 258 */ 259 public ArraySet<KeySet> getUpgradeKeySetsByPackageNameLPr(String packageName) { 260 ArraySet<KeySet> upgradeKeySets = new ArraySet<KeySet>(); 261 PackageSetting p = mPackages.get(packageName); 262 if (p == null) { 263 throw new NullPointerException("Unknown package"); 264 } 265 if (p.keySetData == null) { 266 throw new IllegalArgumentException("Package has no keySet data"); 267 } 268 if (p.keySetData.isUsingUpgradeKeySets()) { 269 for (long l : p.keySetData.getUpgradeKeySets()) { 270 upgradeKeySets.add(mKeySets.get(l)); 271 } 272 } 273 return upgradeKeySets; 274 } 275 276 /** 277 * Creates a new KeySet corresponding to the given keys. 278 * 279 * If the {@link PublicKey PublicKeys} aren't known to the system, this 280 * adds them. Otherwise, they're deduped. 281 * 282 * If the KeySet isn't known to the system, this adds that and creates the 283 * mapping to the PublicKeys. If it is known, then it's deduped. 284 * 285 * If the KeySet isn't known to the system, this adds it to all appropriate 286 * signingKeySets 287 * 288 * Throws if the provided set is {@code null}. 289 */ 290 private KeySet addKeySetLPw(Set<PublicKey> keys) { 291 if (keys == null) { 292 throw new NullPointerException("Provided keys cannot be null"); 293 } 294 // add each of the keys in the provided set 295 ArraySet<Long> addedKeyIds = new ArraySet<Long>(keys.size()); 296 for (PublicKey k : keys) { 297 long id = addPublicKeyLPw(k); 298 addedKeyIds.add(id); 299 } 300 301 // check to see if the resulting keyset is new 302 long existingKeySetId = getIdFromKeyIdsLPr(addedKeyIds); 303 if (existingKeySetId != KEYSET_NOT_FOUND) { 304 return mKeySets.get(existingKeySetId); 305 } 306 307 // create the KeySet object 308 KeySet ks = new KeySet(new Binder()); 309 // get the first unoccupied slot in mKeySets 310 long id = getFreeKeySetIDLPw(); 311 // add the KeySet object to it 312 mKeySets.put(id, ks); 313 // add the stable key ids to the mapping 314 mKeySetMapping.put(id, addedKeyIds); 315 // add this KeySet id to all packages which are signed by it 316 for (String pkgName : mPackages.keySet()) { 317 PackageSetting p = mPackages.get(pkgName); 318 if (p.keySetData != null) { 319 long pProperSigning = p.keySetData.getProperSigningKeySet(); 320 if (pProperSigning != PackageKeySetData.KEYSET_UNASSIGNED) { 321 Set<Long> pSigningKeys = mKeySetMapping.get(pProperSigning); 322 if (pSigningKeys.containsAll(addedKeyIds)) { 323 p.keySetData.addSigningKeySet(id); 324 } 325 } 326 } 327 } 328 // go home 329 return ks; 330 } 331 332 /** 333 * Adds the given PublicKey to the system, deduping as it goes. 334 */ 335 private long addPublicKeyLPw(PublicKey key) { 336 // check if the public key is new 337 long existingKeyId = getIdForPublicKeyLPr(key); 338 if (existingKeyId != PUBLIC_KEY_NOT_FOUND) { 339 return existingKeyId; 340 } 341 // if it's new find the first unoccupied slot in the public keys 342 long id = getFreePublicKeyIdLPw(); 343 // add the public key to it 344 mPublicKeys.put(id, key); 345 // return the stable identifier 346 return id; 347 } 348 349 /** 350 * Finds the stable identifier for a KeySet based on a set of PublicKey stable IDs. 351 * 352 * Returns KEYSET_NOT_FOUND if there isn't one. 353 */ 354 private long getIdFromKeyIdsLPr(Set<Long> publicKeyIds) { 355 for (int keyMapIndex = 0; keyMapIndex < mKeySetMapping.size(); keyMapIndex++) { 356 Set<Long> value = mKeySetMapping.valueAt(keyMapIndex); 357 if (value.equals(publicKeyIds)) { 358 return mKeySetMapping.keyAt(keyMapIndex); 359 } 360 } 361 return KEYSET_NOT_FOUND; 362 } 363 364 /** 365 * Finds the stable identifier for a PublicKey or PUBLIC_KEY_NOT_FOUND. 366 */ 367 private long getIdForPublicKeyLPr(PublicKey k) { 368 String encodedPublicKey = new String(k.getEncoded()); 369 for (int publicKeyIndex = 0; publicKeyIndex < mPublicKeys.size(); publicKeyIndex++) { 370 PublicKey value = mPublicKeys.valueAt(publicKeyIndex); 371 String encodedExistingKey = new String(value.getEncoded()); 372 if (encodedPublicKey.equals(encodedExistingKey)) { 373 return mPublicKeys.keyAt(publicKeyIndex); 374 } 375 } 376 return PUBLIC_KEY_NOT_FOUND; 377 } 378 379 /** 380 * Gets an unused stable identifier for a KeySet. 381 */ 382 private long getFreeKeySetIDLPw() { 383 lastIssuedKeySetId += 1; 384 return lastIssuedKeySetId; 385 } 386 387 /** 388 * Same as above, but for public keys. 389 */ 390 private long getFreePublicKeyIdLPw() { 391 lastIssuedKeyId += 1; 392 return lastIssuedKeyId; 393 } 394 395 public void removeAppKeySetDataLPw(String packageName) { 396 // Get the package's known keys and KeySets 397 ArraySet<Long> deletableKeySets = getOriginalKeySetsByPackageNameLPr(packageName); 398 ArraySet<Long> deletableKeys = new ArraySet<Long>(); 399 ArraySet<Long> knownKeys = null; 400 for (Long ks : deletableKeySets) { 401 knownKeys = mKeySetMapping.get(ks); 402 if (knownKeys != null) { 403 deletableKeys.addAll(knownKeys); 404 } 405 } 406 407 // Now remove the keys and KeySets on which any other package relies 408 for (String pkgName : mPackages.keySet()) { 409 if (pkgName.equals(packageName)) { 410 continue; 411 } 412 ArraySet<Long> knownKeySets = getOriginalKeySetsByPackageNameLPr(pkgName); 413 deletableKeySets.removeAll(knownKeySets); 414 knownKeys = new ArraySet<Long>(); 415 for (Long ks : knownKeySets) { 416 knownKeys = mKeySetMapping.get(ks); 417 if (knownKeys != null) { 418 deletableKeys.removeAll(knownKeys); 419 } 420 } 421 } 422 423 // The remaining keys and KeySets are not relied on by any other 424 // application and so can be safely deleted. 425 for (Long ks : deletableKeySets) { 426 mKeySets.delete(ks); 427 mKeySetMapping.delete(ks); 428 } 429 for (Long keyId : deletableKeys) { 430 mPublicKeys.delete(keyId); 431 } 432 433 // Now remove the deleted KeySets from each package's signingKeySets 434 for (String pkgName : mPackages.keySet()) { 435 PackageSetting p = mPackages.get(pkgName); 436 for (Long ks : deletableKeySets) { 437 p.keySetData.removeSigningKeySet(ks); 438 } 439 } 440 // Finally, remove all KeySets from the original package 441 PackageSetting p = mPackages.get(packageName); 442 clearPackageKeySetDataLPw(p); 443 } 444 445 private void clearPackageKeySetDataLPw(PackageSetting p) { 446 p.keySetData.removeAllSigningKeySets(); 447 p.keySetData.removeAllUpgradeKeySets(); 448 p.keySetData.removeAllDefinedKeySets(); 449 return; 450 } 451 452 private ArraySet<Long> getOriginalKeySetsByPackageNameLPr(String packageName) { 453 PackageSetting p = mPackages.get(packageName); 454 if (p == null) { 455 throw new NullPointerException("Unknown package"); 456 } 457 if (p.keySetData == null) { 458 throw new IllegalArgumentException("Package has no keySet data"); 459 } 460 ArraySet<Long> knownKeySets = new ArraySet<Long>(); 461 knownKeySets.add(p.keySetData.getProperSigningKeySet()); 462 if (p.keySetData.isUsingDefinedKeySets()) { 463 for (long ks : p.keySetData.getDefinedKeySets()) { 464 knownKeySets.add(ks); 465 } 466 } 467 return knownKeySets; 468 } 469 470 public String encodePublicKey(PublicKey k) throws IOException { 471 return new String(Base64.encode(k.getEncoded(), 0)); 472 } 473 474 public void dumpLPr(PrintWriter pw, String packageName, 475 PackageManagerService.DumpState dumpState) { 476 boolean printedHeader = false; 477 for (Map.Entry<String, PackageSetting> e : mPackages.entrySet()) { 478 String keySetPackage = e.getKey(); 479 if (packageName != null && !packageName.equals(keySetPackage)) { 480 continue; 481 } 482 if (!printedHeader) { 483 if (dumpState.onTitlePrinted()) 484 pw.println(); 485 pw.println("Key Set Manager:"); 486 printedHeader = true; 487 } 488 PackageSetting pkg = e.getValue(); 489 pw.print(" ["); pw.print(keySetPackage); pw.println("]"); 490 if (pkg.keySetData != null) { 491 boolean printedLabel = false; 492 for (Map.Entry<String, Long> entry : pkg.keySetData.getAliases().entrySet()) { 493 if (!printedLabel) { 494 pw.print(" KeySets Aliases: "); 495 printedLabel = true; 496 } else { 497 pw.print(", "); 498 } 499 pw.print(entry.getKey()); 500 pw.print('='); 501 pw.print(Long.toString(entry.getValue())); 502 } 503 if (printedLabel) { 504 pw.println(""); 505 } 506 printedLabel = false; 507 if (pkg.keySetData.isUsingDefinedKeySets()) { 508 for (long keySetId : pkg.keySetData.getDefinedKeySets()) { 509 if (!printedLabel) { 510 pw.print(" Defined KeySets: "); 511 printedLabel = true; 512 } else { 513 pw.print(", "); 514 } 515 pw.print(Long.toString(keySetId)); 516 } 517 } 518 if (printedLabel) { 519 pw.println(""); 520 } 521 printedLabel = false; 522 for (long keySetId : pkg.keySetData.getSigningKeySets()) { 523 if (!printedLabel) { 524 pw.print(" Signing KeySets: "); 525 printedLabel = true; 526 } else { 527 pw.print(", "); 528 } 529 pw.print(Long.toString(keySetId)); 530 } 531 if (printedLabel) { 532 pw.println(""); 533 } 534 printedLabel = false; 535 if (pkg.keySetData.isUsingUpgradeKeySets()) { 536 for (long keySetId : pkg.keySetData.getUpgradeKeySets()) { 537 if (!printedLabel) { 538 pw.print(" Upgrade KeySets: "); 539 printedLabel = true; 540 } else { 541 pw.print(", "); 542 } 543 pw.print(Long.toString(keySetId)); 544 } 545 } 546 if (printedLabel) { 547 pw.println(""); 548 } 549 } 550 } 551 } 552 553 void writeKeySetManagerServiceLPr(XmlSerializer serializer) throws IOException { 554 serializer.startTag(null, "keyset-settings"); 555 serializer.attribute(null, "version", Integer.toString(CURRENT_VERSION)); 556 writePublicKeysLPr(serializer); 557 writeKeySetsLPr(serializer); 558 serializer.startTag(null, "lastIssuedKeyId"); 559 serializer.attribute(null, "value", Long.toString(lastIssuedKeyId)); 560 serializer.endTag(null, "lastIssuedKeyId"); 561 serializer.startTag(null, "lastIssuedKeySetId"); 562 serializer.attribute(null, "value", Long.toString(lastIssuedKeySetId)); 563 serializer.endTag(null, "lastIssuedKeySetId"); 564 serializer.endTag(null, "keyset-settings"); 565 } 566 567 void writePublicKeysLPr(XmlSerializer serializer) throws IOException { 568 serializer.startTag(null, "keys"); 569 for (int pKeyIndex = 0; pKeyIndex < mPublicKeys.size(); pKeyIndex++) { 570 long id = mPublicKeys.keyAt(pKeyIndex); 571 PublicKey key = mPublicKeys.valueAt(pKeyIndex); 572 String encodedKey = encodePublicKey(key); 573 serializer.startTag(null, "public-key"); 574 serializer.attribute(null, "identifier", Long.toString(id)); 575 serializer.attribute(null, "value", encodedKey); 576 serializer.endTag(null, "public-key"); 577 } 578 serializer.endTag(null, "keys"); 579 } 580 581 void writeKeySetsLPr(XmlSerializer serializer) throws IOException { 582 serializer.startTag(null, "keysets"); 583 for (int keySetIndex = 0; keySetIndex < mKeySetMapping.size(); keySetIndex++) { 584 long id = mKeySetMapping.keyAt(keySetIndex); 585 Set<Long> keys = mKeySetMapping.valueAt(keySetIndex); 586 serializer.startTag(null, "keyset"); 587 serializer.attribute(null, "identifier", Long.toString(id)); 588 for (long keyId : keys) { 589 serializer.startTag(null, "key-id"); 590 serializer.attribute(null, "identifier", Long.toString(keyId)); 591 serializer.endTag(null, "key-id"); 592 } 593 serializer.endTag(null, "keyset"); 594 } 595 serializer.endTag(null, "keysets"); 596 } 597 598 void readKeySetsLPw(XmlPullParser parser) 599 throws XmlPullParserException, IOException { 600 int type; 601 long currentKeySetId = 0; 602 int outerDepth = parser.getDepth(); 603 String recordedVersion = parser.getAttributeValue(null, "version"); 604 if (recordedVersion == null || Integer.parseInt(recordedVersion) != CURRENT_VERSION) { 605 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 606 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 607 // Our version is different than the one which generated the old keyset data. 608 // We don't want any of the old data, but we must advance the parser 609 continue; 610 } 611 // The KeySet information read previously from packages.xml is invalid. 612 // Destroy it all. 613 for (PackageSetting p : mPackages.values()) { 614 clearPackageKeySetDataLPw(p); 615 } 616 return; 617 } 618 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 619 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 620 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 621 continue; 622 } 623 final String tagName = parser.getName(); 624 if (tagName.equals("keys")) { 625 readKeysLPw(parser); 626 } else if (tagName.equals("keysets")) { 627 readKeySetListLPw(parser); 628 } else if (tagName.equals("lastIssuedKeyId")) { 629 lastIssuedKeyId = Long.parseLong(parser.getAttributeValue(null, "value")); 630 } else if (tagName.equals("lastIssuedKeySetId")) { 631 lastIssuedKeySetId = Long.parseLong(parser.getAttributeValue(null, "value")); 632 } 633 } 634 } 635 636 void readKeysLPw(XmlPullParser parser) 637 throws XmlPullParserException, IOException { 638 int outerDepth = parser.getDepth(); 639 int type; 640 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 641 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 642 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 643 continue; 644 } 645 final String tagName = parser.getName(); 646 if (tagName.equals("public-key")) { 647 readPublicKeyLPw(parser); 648 } 649 } 650 } 651 652 void readKeySetListLPw(XmlPullParser parser) 653 throws XmlPullParserException, IOException { 654 int outerDepth = parser.getDepth(); 655 int type; 656 long currentKeySetId = 0; 657 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 658 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 659 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 660 continue; 661 } 662 final String tagName = parser.getName(); 663 if (tagName.equals("keyset")) { 664 currentKeySetId = readIdentifierLPw(parser); 665 mKeySets.put(currentKeySetId, new KeySet(new Binder())); 666 mKeySetMapping.put(currentKeySetId, new ArraySet<Long>()); 667 } else if (tagName.equals("key-id")) { 668 long id = readIdentifierLPw(parser); 669 mKeySetMapping.get(currentKeySetId).add(id); 670 } 671 } 672 } 673 674 long readIdentifierLPw(XmlPullParser parser) 675 throws XmlPullParserException { 676 return Long.parseLong(parser.getAttributeValue(null, "identifier")); 677 } 678 679 void readPublicKeyLPw(XmlPullParser parser) 680 throws XmlPullParserException { 681 String encodedID = parser.getAttributeValue(null, "identifier"); 682 long identifier = Long.parseLong(encodedID); 683 String encodedPublicKey = parser.getAttributeValue(null, "value"); 684 PublicKey pub = PackageParser.parsePublicKey(encodedPublicKey); 685 if (pub != null) { 686 mPublicKeys.put(identifier, pub); 687 } 688 } 689} 690