blob: 1056cd003c313f6f31e72a4f3f5e8ddf8845520c [file] [log] [blame]
Geremy Condraf1bcca82013-01-07 22:35:24 -08001/*
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.Base64;
Geremy Condraf1bcca82013-01-07 22:35:24 -080023import android.util.LongSparseArray;
24
25import java.io.IOException;
26import java.io.PrintWriter;
27import java.security.PublicKey;
Geremy Condraf1bcca82013-01-07 22:35:24 -080028import java.util.HashSet;
29import java.util.Map;
30import java.util.Set;
31
32import org.xmlpull.v1.XmlPullParser;
33import org.xmlpull.v1.XmlPullParserException;
34import org.xmlpull.v1.XmlSerializer;
35
36/*
37 * Manages system-wide KeySet state.
38 */
39public class KeySetManager {
40
41 static final String TAG = "KeySetManager";
42
Kenny Root9a995f52013-07-08 09:33:22 -070043 /** Sentinel value returned when a {@code KeySet} is not found. */
44 public static final long KEYSET_NOT_FOUND = -1;
45
46 /** Sentinel value returned when public key is not found. */
Geremy Condraf1bcca82013-01-07 22:35:24 -080047 private static final long PUBLIC_KEY_NOT_FOUND = -1;
48
49 private final Object mLockObject = new Object();
50
51 private final LongSparseArray<KeySet> mKeySets;
52
53 private final LongSparseArray<PublicKey> mPublicKeys;
54
55 private final LongSparseArray<Set<Long>> mKeySetMapping;
56
57 private final Map<String, PackageSetting> mPackages;
58
59 private static long lastIssuedKeySetId = 0;
60
61 private static long lastIssuedKeyId = 0;
62
63 public KeySetManager(Map<String, PackageSetting> packages) {
64 mKeySets = new LongSparseArray<KeySet>();
65 mPublicKeys = new LongSparseArray<PublicKey>();
66 mKeySetMapping = new LongSparseArray<Set<Long>>();
67 mPackages = packages;
68 }
69
Kenny Root2042e9d2013-07-08 09:31:31 -070070 /**
Geremy Condraf1bcca82013-01-07 22:35:24 -080071 * Determine if a package is signed by the given KeySet.
72 *
73 * Returns false if the package was not signed by all the
74 * keys in the KeySet.
75 *
76 * Returns true if the package was signed by at least the
77 * keys in the given KeySet.
78 *
79 * Note that this can return true for multiple KeySets.
80 */
81 public boolean packageIsSignedBy(String packageName, KeySet ks) {
82 synchronized (mLockObject) {
83 PackageSetting pkg = mPackages.get(packageName);
84 if (pkg == null) {
85 throw new NullPointerException("Invalid package name");
86 }
87 if (pkg.keySetData == null) {
88 throw new NullPointerException("Package has no KeySet data");
89 }
90 long id = getIdByKeySetLocked(ks);
91 return pkg.keySetData.packageIsSignedBy(id);
92 }
93 }
94
Kenny Root2042e9d2013-07-08 09:31:31 -070095 /**
Geremy Condraf1bcca82013-01-07 22:35:24 -080096 * This informs the system that the given package has defined a KeySet
97 * in its manifest that a) contains the given keys and b) is named
98 * alias by that package.
99 */
100 public void addDefinedKeySetToPackage(String packageName,
101 Set<PublicKey> keys, String alias) {
102 if ((packageName == null) || (keys == null) || (alias == null)) {
Dianne Hackbornc30d92e2013-09-20 18:19:00 -0700103 //Log.d(TAG, "Got null argument for a defined keyset, ignoring!");
Geremy Condraf1bcca82013-01-07 22:35:24 -0800104 return;
105 }
106 synchronized (mLockObject) {
107 KeySet ks = addKeySetLocked(keys);
108 PackageSetting pkg = mPackages.get(packageName);
109 if (pkg == null) {
110 throw new NullPointerException("Unknown package");
111 }
112 long id = getIdByKeySetLocked(ks);
113 pkg.keySetData.addDefinedKeySet(id, alias);
114 }
115 }
116
Kenny Root2042e9d2013-07-08 09:31:31 -0700117 /**
Geremy Condraf1bcca82013-01-07 22:35:24 -0800118 * Similar to the above, this informs the system that the given package
119 * was signed by the provided KeySet.
120 */
121 public void addSigningKeySetToPackage(String packageName,
122 Set<PublicKey> signingKeys) {
123 if ((packageName == null) || (signingKeys == null)) {
Dianne Hackbornc30d92e2013-09-20 18:19:00 -0700124 //Log.d(TAG, "Got null argument for a signing keyset, ignoring!");
Geremy Condraf1bcca82013-01-07 22:35:24 -0800125 return;
126 }
127 synchronized (mLockObject) {
128 // add the signing KeySet
129 KeySet ks = addKeySetLocked(signingKeys);
130 long id = getIdByKeySetLocked(ks);
131 Set<Long> publicKeyIds = mKeySetMapping.get(id);
132 if (publicKeyIds == null) {
133 throw new NullPointerException("Got invalid KeySet id");
134 }
135
136 // attach it to the package
137 PackageSetting pkg = mPackages.get(packageName);
138 if (pkg == null) {
139 throw new NullPointerException("No such package!");
140 }
141 pkg.keySetData.addSigningKeySet(id);
142
143 // for each KeySet the package defines which is a subset of
144 // the one above, add the KeySet id to the package's signing KeySets
145 for (Long keySetID : pkg.keySetData.getDefinedKeySets()) {
146 Set<Long> definedKeys = mKeySetMapping.get(keySetID);
147 if (publicKeyIds.contains(definedKeys)) {
148 pkg.keySetData.addSigningKeySet(keySetID);
149 }
150 }
151 }
152 }
153
Kenny Root2042e9d2013-07-08 09:31:31 -0700154 /**
155 * Fetches the stable identifier associated with the given KeySet. Returns
156 * {@link #KEYSET_NOT_FOUND} if the KeySet... wasn't found.
Geremy Condraf1bcca82013-01-07 22:35:24 -0800157 */
158 public long getIdByKeySet(KeySet ks) {
159 synchronized (mLockObject) {
160 return getIdByKeySetLocked(ks);
161 }
162 }
163
164 private long getIdByKeySetLocked(KeySet ks) {
165 for (int keySetIndex = 0; keySetIndex < mKeySets.size(); keySetIndex++) {
166 KeySet value = mKeySets.valueAt(keySetIndex);
167 if (ks.equals(value)) {
168 return mKeySets.keyAt(keySetIndex);
169 }
170 }
171 return KEYSET_NOT_FOUND;
172 }
173
Kenny Root2042e9d2013-07-08 09:31:31 -0700174 /**
Geremy Condraf1bcca82013-01-07 22:35:24 -0800175 * Fetches the KeySet corresponding to the given stable identifier.
176 *
Kenny Root2042e9d2013-07-08 09:31:31 -0700177 * Returns {@link #KEYSET_NOT_FOUND} if the identifier doesn't
178 * identify a {@link KeySet}.
Geremy Condraf1bcca82013-01-07 22:35:24 -0800179 */
180 public KeySet getKeySetById(long id) {
181 synchronized (mLockObject) {
182 return mKeySets.get(id);
183 }
184 }
185
Kenny Root2042e9d2013-07-08 09:31:31 -0700186 /**
Geremy Condraf1bcca82013-01-07 22:35:24 -0800187 * Fetches the KeySet that a given package refers to by the provided alias.
188 *
189 * If the package isn't known to us, throws an IllegalArgumentException.
190 * Returns null if the alias isn't known to us.
191 */
192 public KeySet getKeySetByAliasAndPackageName(String packageName, String alias) {
193 synchronized (mLockObject) {
194 PackageSetting p = mPackages.get(packageName);
195 if (p == null) {
196 throw new NullPointerException("Unknown package");
197 }
198 if (p.keySetData == null) {
199 throw new IllegalArgumentException("Package has no keySet data");
200 }
201 long keySetId = p.keySetData.getAliases().get(alias);
202 return mKeySets.get(keySetId);
203 }
204 }
205
Kenny Root2042e9d2013-07-08 09:31:31 -0700206 /**
207 * Fetches all the known {@link KeySet KeySets} that signed the given
208 * package. Returns {@code null} if package is unknown.
Geremy Condraf1bcca82013-01-07 22:35:24 -0800209 */
210 public Set<KeySet> getSigningKeySetsByPackageName(String packageName) {
211 synchronized (mLockObject) {
212 Set<KeySet> signingKeySets = new HashSet<KeySet>();
213 PackageSetting p = mPackages.get(packageName);
214 if (p == null) {
215 throw new NullPointerException("Unknown package");
216 }
217 if (p.keySetData == null) {
218 throw new IllegalArgumentException("Package has no keySet data");
219 }
220 for (long l : p.keySetData.getSigningKeySets()) {
221 signingKeySets.add(mKeySets.get(l));
222 }
223 return signingKeySets;
224 }
225 }
226
Kenny Root2042e9d2013-07-08 09:31:31 -0700227 /**
Geremy Condraf1bcca82013-01-07 22:35:24 -0800228 * Creates a new KeySet corresponding to the given keys.
229 *
Kenny Root2042e9d2013-07-08 09:31:31 -0700230 * If the {@link PublicKey PublicKeys} aren't known to the system, this
231 * adds them. Otherwise, they're deduped.
Geremy Condraf1bcca82013-01-07 22:35:24 -0800232 *
233 * If the KeySet isn't known to the system, this adds that and creates the
234 * mapping to the PublicKeys. If it is known, then it's deduped.
235 *
Kenny Root2042e9d2013-07-08 09:31:31 -0700236 * Throws if the provided set is {@code null}.
Geremy Condraf1bcca82013-01-07 22:35:24 -0800237 */
238 private KeySet addKeySetLocked(Set<PublicKey> keys) {
239 if (keys == null) {
240 throw new NullPointerException("Provided keys cannot be null");
241 }
242 // add each of the keys in the provided set
243 Set<Long> addedKeyIds = new HashSet<Long>(keys.size());
244 for (PublicKey k : keys) {
245 long id = addPublicKeyLocked(k);
246 addedKeyIds.add(id);
247 }
248
249 // check to see if the resulting keyset is new
250 long existingKeySetId = getIdFromKeyIdsLocked(addedKeyIds);
251 if (existingKeySetId != KEYSET_NOT_FOUND) {
252 return mKeySets.get(existingKeySetId);
253 }
254
255 // create the KeySet object
256 KeySet ks = new KeySet(new Binder());
257 // get the first unoccupied slot in mKeySets
258 long id = getFreeKeySetIDLocked();
259 // add the KeySet object to it
260 mKeySets.put(id, ks);
261 // add the stable key ids to the mapping
262 mKeySetMapping.put(id, addedKeyIds);
263 // go home
264 return ks;
265 }
266
Kenny Root2042e9d2013-07-08 09:31:31 -0700267 /**
Geremy Condraf1bcca82013-01-07 22:35:24 -0800268 * Adds the given PublicKey to the system, deduping as it goes.
269 */
270 private long addPublicKeyLocked(PublicKey key) {
271 // check if the public key is new
272 long existingKeyId = getIdForPublicKeyLocked(key);
273 if (existingKeyId != PUBLIC_KEY_NOT_FOUND) {
274 return existingKeyId;
275 }
276 // if it's new find the first unoccupied slot in the public keys
277 long id = getFreePublicKeyIdLocked();
278 // add the public key to it
279 mPublicKeys.put(id, key);
280 // return the stable identifier
281 return id;
282 }
283
Kenny Root2042e9d2013-07-08 09:31:31 -0700284 /**
Geremy Condraf1bcca82013-01-07 22:35:24 -0800285 * Finds the stable identifier for a KeySet based on a set of PublicKey stable IDs.
286 *
287 * Returns KEYSET_NOT_FOUND if there isn't one.
288 */
289 private long getIdFromKeyIdsLocked(Set<Long> publicKeyIds) {
290 for (int keyMapIndex = 0; keyMapIndex < mKeySetMapping.size(); keyMapIndex++) {
291 Set<Long> value = mKeySetMapping.valueAt(keyMapIndex);
292 if (value.equals(publicKeyIds)) {
293 return mKeySetMapping.keyAt(keyMapIndex);
294 }
295 }
296 return KEYSET_NOT_FOUND;
297 }
298
Kenny Root2042e9d2013-07-08 09:31:31 -0700299 /**
Geremy Condraf1bcca82013-01-07 22:35:24 -0800300 * Finds the stable identifier for a PublicKey or PUBLIC_KEY_NOT_FOUND.
301 */
302 private long getIdForPublicKeyLocked(PublicKey k) {
303 String encodedPublicKey = new String(k.getEncoded());
304 for (int publicKeyIndex = 0; publicKeyIndex < mPublicKeys.size(); publicKeyIndex++) {
305 PublicKey value = mPublicKeys.valueAt(publicKeyIndex);
306 String encodedExistingKey = new String(value.getEncoded());
307 if (encodedPublicKey.equals(encodedExistingKey)) {
308 return mPublicKeys.keyAt(publicKeyIndex);
309 }
310 }
311 return PUBLIC_KEY_NOT_FOUND;
312 }
313
Kenny Root2042e9d2013-07-08 09:31:31 -0700314 /**
Geremy Condraf1bcca82013-01-07 22:35:24 -0800315 * Gets an unused stable identifier for a KeySet.
316 */
317 private long getFreeKeySetIDLocked() {
318 lastIssuedKeySetId += 1;
319 return lastIssuedKeySetId;
320 }
321
Kenny Root2042e9d2013-07-08 09:31:31 -0700322 /**
Geremy Condraf1bcca82013-01-07 22:35:24 -0800323 * Same as above, but for public keys.
324 */
325 private long getFreePublicKeyIdLocked() {
326 lastIssuedKeyId += 1;
327 return lastIssuedKeyId;
328 }
329
330 public void removeAppKeySetData(String packageName) {
Geremy Condraf1bcca82013-01-07 22:35:24 -0800331 synchronized (mLockObject) {
332 // Get the package's known keys and KeySets
Geremy Condracdb57892013-03-26 16:22:36 -0700333 Set<Long> deletableKeySets = getKnownKeySetsByPackageNameLocked(packageName);
Geremy Condraf1bcca82013-01-07 22:35:24 -0800334 Set<Long> deletableKeys = new HashSet<Long>();
Geremy Condracdb57892013-03-26 16:22:36 -0700335 Set<Long> knownKeys = null;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800336 for (Long ks : deletableKeySets) {
Geremy Condracdb57892013-03-26 16:22:36 -0700337 knownKeys = mKeySetMapping.get(ks);
338 if (knownKeys != null) {
339 deletableKeys.addAll(knownKeys);
340 }
Geremy Condraf1bcca82013-01-07 22:35:24 -0800341 }
342
343 // Now remove the keys and KeySets known to any other package
344 for (String pkgName : mPackages.keySet()) {
345 if (pkgName.equals(packageName)) {
346 continue;
347 }
Geremy Condracdb57892013-03-26 16:22:36 -0700348 Set<Long> knownKeySets = getKnownKeySetsByPackageNameLocked(pkgName);
Geremy Condraf1bcca82013-01-07 22:35:24 -0800349 deletableKeySets.removeAll(knownKeySets);
Geremy Condracdb57892013-03-26 16:22:36 -0700350 knownKeys = new HashSet<Long>();
Geremy Condraf1bcca82013-01-07 22:35:24 -0800351 for (Long ks : knownKeySets) {
Geremy Condracdb57892013-03-26 16:22:36 -0700352 knownKeys = mKeySetMapping.get(ks);
353 if (knownKeys != null) {
354 deletableKeys.removeAll(knownKeys);
355 }
Geremy Condraf1bcca82013-01-07 22:35:24 -0800356 }
357 }
358
359 // The remaining keys and KeySets are not known to any other
360 // application and so can be safely deleted.
361 for (Long ks : deletableKeySets) {
362 mKeySets.delete(ks);
363 mKeySetMapping.delete(ks);
364 }
365 for (Long keyId : deletableKeys) {
366 mPublicKeys.delete(keyId);
367 }
Geremy Condracdb57892013-03-26 16:22:36 -0700368
369 // Now remove them from the KeySets known to each package
370 for (String pkgName : mPackages.keySet()) {
Kenny Root92179bc2013-07-02 11:55:27 -0700371 PackageSetting p = mPackages.get(pkgName);
Geremy Condracdb57892013-03-26 16:22:36 -0700372 for (Long ks : deletableKeySets) {
373 p.keySetData.removeSigningKeySet(ks);
374 p.keySetData.removeDefinedKeySet(ks);
375 }
376 }
Geremy Condraf1bcca82013-01-07 22:35:24 -0800377 }
378 }
379
Geremy Condracdb57892013-03-26 16:22:36 -0700380 private Set<Long> getKnownKeySetsByPackageNameLocked(String packageName) {
Geremy Condraf1bcca82013-01-07 22:35:24 -0800381 PackageSetting p = mPackages.get(packageName);
382 if (p == null) {
383 throw new NullPointerException("Unknown package");
384 }
385 if (p.keySetData == null) {
386 throw new IllegalArgumentException("Package has no keySet data");
387 }
388 Set<Long> knownKeySets = new HashSet<Long>();
Geremy Condracdb57892013-03-26 16:22:36 -0700389 for (long ks : p.keySetData.getSigningKeySets()) {
Geremy Condraf1bcca82013-01-07 22:35:24 -0800390 knownKeySets.add(ks);
391 }
Geremy Condracdb57892013-03-26 16:22:36 -0700392 for (long ks : p.keySetData.getDefinedKeySets()) {
Geremy Condraf1bcca82013-01-07 22:35:24 -0800393 knownKeySets.add(ks);
394 }
395 return knownKeySets;
396 }
397
398 public String encodePublicKey(PublicKey k) throws IOException {
399 return new String(Base64.encode(k.getEncoded(), 0));
400 }
401
Dianne Hackborncbfd23e2013-06-11 14:26:53 -0700402 public void dump(PrintWriter pw, String packageName,
403 PackageManagerService.DumpState dumpState) {
Geremy Condraf1bcca82013-01-07 22:35:24 -0800404 synchronized (mLockObject) {
Dianne Hackborncbfd23e2013-06-11 14:26:53 -0700405 boolean printedHeader = false;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800406 for (Map.Entry<String, PackageSetting> e : mPackages.entrySet()) {
Dianne Hackborncbfd23e2013-06-11 14:26:53 -0700407 String keySetPackage = e.getKey();
408 if (packageName != null && !packageName.equals(keySetPackage)) {
409 continue;
410 }
411 if (!printedHeader) {
412 if (dumpState.onTitlePrinted())
413 pw.println();
414 pw.println("Key Set Manager:");
415 printedHeader = true;
416 }
Geremy Condraf1bcca82013-01-07 22:35:24 -0800417 PackageSetting pkg = e.getValue();
Dianne Hackborncbfd23e2013-06-11 14:26:53 -0700418 pw.print(" ["); pw.print(keySetPackage); pw.println("]");
Geremy Condraf1bcca82013-01-07 22:35:24 -0800419 if (pkg.keySetData != null) {
Dianne Hackborncbfd23e2013-06-11 14:26:53 -0700420 boolean printedLabel = false;
Ying Wangfb236b52013-07-08 10:53:58 -0700421 for (Map.Entry<String, Long> entry : pkg.keySetData.getAliases().entrySet()) {
Kenny Rootdf0e6ab2013-07-03 13:38:31 -0700422 if (!printedLabel) {
423 pw.print(" KeySets Aliases: ");
424 printedLabel = true;
425 } else {
426 pw.print(", ");
427 }
428 pw.print(entry.getKey());
429 pw.print('=');
430 pw.print(Long.toString(entry.getValue()));
431 }
432 if (printedLabel) {
433 pw.println("");
434 }
435 printedLabel = false;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800436 for (long keySetId : pkg.keySetData.getDefinedKeySets()) {
Dianne Hackborncbfd23e2013-06-11 14:26:53 -0700437 if (!printedLabel) {
438 pw.print(" Defined KeySets: ");
439 printedLabel = true;
440 } else {
441 pw.print(", ");
442 }
443 pw.print(Long.toString(keySetId));
Geremy Condraf1bcca82013-01-07 22:35:24 -0800444 }
Dianne Hackborncbfd23e2013-06-11 14:26:53 -0700445 if (printedLabel) {
446 pw.println("");
447 }
448 printedLabel = false;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800449 for (long keySetId : pkg.keySetData.getSigningKeySets()) {
Dianne Hackborncbfd23e2013-06-11 14:26:53 -0700450 if (!printedLabel) {
Kenny Rootdf0e6ab2013-07-03 13:38:31 -0700451 pw.print(" Signing KeySets: ");
Dianne Hackborncbfd23e2013-06-11 14:26:53 -0700452 printedLabel = true;
453 } else {
454 pw.print(", ");
455 }
Kenny Rootdf0e6ab2013-07-03 13:38:31 -0700456 pw.print(Long.toString(keySetId));
Geremy Condraf1bcca82013-01-07 22:35:24 -0800457 }
Dianne Hackborncbfd23e2013-06-11 14:26:53 -0700458 if (printedLabel) {
459 pw.println("");
460 }
Geremy Condraf1bcca82013-01-07 22:35:24 -0800461 }
462 }
463 }
464 }
465
466 void writeKeySetManagerLPr(XmlSerializer serializer) throws IOException {
467 serializer.startTag(null, "keyset-settings");
468 writePublicKeysLPr(serializer);
469 writeKeySetsLPr(serializer);
470 serializer.startTag(null, "lastIssuedKeyId");
471 serializer.attribute(null, "value", Long.toString(lastIssuedKeyId));
472 serializer.endTag(null, "lastIssuedKeyId");
473 serializer.startTag(null, "lastIssuedKeySetId");
474 serializer.attribute(null, "value", Long.toString(lastIssuedKeySetId));
475 serializer.endTag(null, "lastIssuedKeySetId");
476 serializer.endTag(null, "keyset-settings");
477 }
478
479 void writePublicKeysLPr(XmlSerializer serializer) throws IOException {
480 serializer.startTag(null, "keys");
481 for (int pKeyIndex = 0; pKeyIndex < mPublicKeys.size(); pKeyIndex++) {
482 long id = mPublicKeys.keyAt(pKeyIndex);
483 PublicKey key = mPublicKeys.valueAt(pKeyIndex);
484 String encodedKey = encodePublicKey(key);
485 serializer.startTag(null, "public-key");
486 serializer.attribute(null, "identifier", Long.toString(id));
487 serializer.attribute(null, "value", encodedKey);
488 serializer.endTag(null, "public-key");
489 }
490 serializer.endTag(null, "keys");
491 }
492
493 void writeKeySetsLPr(XmlSerializer serializer) throws IOException {
494 serializer.startTag(null, "keysets");
495 for (int keySetIndex = 0; keySetIndex < mKeySetMapping.size(); keySetIndex++) {
496 long id = mKeySetMapping.keyAt(keySetIndex);
497 Set<Long> keys = mKeySetMapping.valueAt(keySetIndex);
498 serializer.startTag(null, "keyset");
499 serializer.attribute(null, "identifier", Long.toString(id));
500 for (long keyId : keys) {
501 serializer.startTag(null, "key-id");
502 serializer.attribute(null, "identifier", Long.toString(keyId));
503 serializer.endTag(null, "key-id");
504 }
505 serializer.endTag(null, "keyset");
506 }
507 serializer.endTag(null, "keysets");
508 }
509
510 void readKeySetsLPw(XmlPullParser parser)
511 throws XmlPullParserException, IOException {
512 int type;
513 long currentKeySetId = 0;
514 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
515 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
516 continue;
517 }
518 final String tagName = parser.getName();
519 if (tagName.equals("keys")) {
520 readKeysLPw(parser);
521 } else if (tagName.equals("keysets")) {
522 readKeySetListLPw(parser);
Geremy Condraf1bcca82013-01-07 22:35:24 -0800523 }
524 }
525 }
526
527 void readKeysLPw(XmlPullParser parser)
528 throws XmlPullParserException, IOException {
529 int outerDepth = parser.getDepth();
530 int type;
531 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
532 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
533 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
534 continue;
535 }
536 final String tagName = parser.getName();
537 if (tagName.equals("public-key")) {
538 readPublicKeyLPw(parser);
539 } else if (tagName.equals("lastIssuedKeyId")) {
540 lastIssuedKeyId = Long.parseLong(parser.getAttributeValue(null, "value"));
541 } else if (tagName.equals("lastIssuedKeySetId")) {
542 lastIssuedKeySetId = Long.parseLong(parser.getAttributeValue(null, "value"));
Geremy Condraf1bcca82013-01-07 22:35:24 -0800543 }
544 }
545 }
546
547 void readKeySetListLPw(XmlPullParser parser)
548 throws XmlPullParserException, IOException {
549 int outerDepth = parser.getDepth();
550 int type;
551 long currentKeySetId = 0;
552 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
553 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
554 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
555 continue;
556 }
557 final String tagName = parser.getName();
558 if (tagName.equals("keyset")) {
559 currentKeySetId = readIdentifierLPw(parser);
560 mKeySets.put(currentKeySetId, new KeySet(new Binder()));
561 mKeySetMapping.put(currentKeySetId, new HashSet<Long>());
562 } else if (tagName.equals("key-id")) {
563 long id = readIdentifierLPw(parser);
564 mKeySetMapping.get(currentKeySetId).add(id);
Geremy Condraf1bcca82013-01-07 22:35:24 -0800565 }
566 }
567 }
568
569 long readIdentifierLPw(XmlPullParser parser)
570 throws XmlPullParserException {
571 return Long.parseLong(parser.getAttributeValue(null, "identifier"));
572 }
573
574 void readPublicKeyLPw(XmlPullParser parser)
575 throws XmlPullParserException {
576 String encodedID = parser.getAttributeValue(null, "identifier");
577 long identifier = Long.parseLong(encodedID);
578 String encodedPublicKey = parser.getAttributeValue(null, "value");
579 PublicKey pub = PackageParser.parsePublicKey(encodedPublicKey);
Geremy Condraa2d8eae2013-06-21 16:59:42 -0700580 if (pub != null) {
Geremy Condraf1bcca82013-01-07 22:35:24 -0800581 mPublicKeys.put(identifier, pub);
582 }
583 }
Ying Wangfb236b52013-07-08 10:53:58 -0700584}