OSDN Git Service

Remove static modifier from KeySetManagerService issuedIds.
[android-x86/frameworks-base.git] / services / core / java / com / android / server / pm / KeySetManagerService.java
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
17 package com.android.server.pm;
18
19 import android.content.pm.PackageParser;
20 import android.util.ArrayMap;
21 import android.util.ArraySet;
22 import android.util.Base64;
23 import android.util.Slog;
24 import android.util.LongSparseArray;
25
26 import java.io.IOException;
27 import java.io.PrintWriter;
28 import java.security.PublicKey;
29 import java.util.Set;
30
31 import org.xmlpull.v1.XmlPullParser;
32 import org.xmlpull.v1.XmlPullParserException;
33 import org.xmlpull.v1.XmlSerializer;
34
35 /*
36  * Manages system-wide KeySet state.
37  */
38 public 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 long lastIssuedKeySetId = 0;
62
63     private 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(), Base64.NO_WRAP));
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 }