blob: 93d3b77511bc69c2552208969e51f31307dcde72 [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
dcashman87f794f2015-06-03 14:46:47 -070019import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
20
Todd Kennedy7c4c55d2017-11-02 10:01:39 -070021import static com.android.server.pm.PackageManagerService.SCAN_INITIAL;
22
dcashman87f794f2015-06-03 14:46:47 -070023import com.android.internal.util.Preconditions;
Geremy Condraf1bcca82013-01-07 22:35:24 -080024import android.content.pm.PackageParser;
dcashman8c04fac2015-03-23 11:39:42 -070025import android.util.ArrayMap;
dcashman55b10782014-04-09 14:20:38 -070026import android.util.ArraySet;
Geremy Condraf1bcca82013-01-07 22:35:24 -080027import android.util.Base64;
dcashman55b10782014-04-09 14:20:38 -070028import android.util.Slog;
Geremy Condraf1bcca82013-01-07 22:35:24 -080029import android.util.LongSparseArray;
30
31import java.io.IOException;
32import java.io.PrintWriter;
33import java.security.PublicKey;
Geremy Condraf1bcca82013-01-07 22:35:24 -080034import java.util.Set;
35
36import org.xmlpull.v1.XmlPullParser;
37import org.xmlpull.v1.XmlPullParserException;
38import org.xmlpull.v1.XmlSerializer;
39
40/*
41 * Manages system-wide KeySet state.
42 */
dcashman55b10782014-04-09 14:20:38 -070043public class KeySetManagerService {
Geremy Condraf1bcca82013-01-07 22:35:24 -080044
dcashman55b10782014-04-09 14:20:38 -070045 static final String TAG = "KeySetManagerService";
46
47 /* original keysets implementation had no versioning info, so this is the first */
48 public static final int FIRST_VERSION = 1;
49
50 public static final int CURRENT_VERSION = FIRST_VERSION;
Geremy Condraf1bcca82013-01-07 22:35:24 -080051
Kenny Root9a995f52013-07-08 09:33:22 -070052 /** Sentinel value returned when a {@code KeySet} is not found. */
53 public static final long KEYSET_NOT_FOUND = -1;
54
55 /** Sentinel value returned when public key is not found. */
dcashman55b10782014-04-09 14:20:38 -070056 protected static final long PUBLIC_KEY_NOT_FOUND = -1;
Geremy Condraf1bcca82013-01-07 22:35:24 -080057
dcashman9d2f4412014-06-09 09:27:54 -070058 private final LongSparseArray<KeySetHandle> mKeySets;
Geremy Condraf1bcca82013-01-07 22:35:24 -080059
dcashman8c04fac2015-03-23 11:39:42 -070060 private final LongSparseArray<PublicKeyHandle> mPublicKeys;
Geremy Condraf1bcca82013-01-07 22:35:24 -080061
dcashmand79fdf12014-06-20 15:53:06 -070062 protected final LongSparseArray<ArraySet<Long>> mKeySetMapping;
Geremy Condraf1bcca82013-01-07 22:35:24 -080063
dcashman8c04fac2015-03-23 11:39:42 -070064 private final ArrayMap<String, PackageSetting> mPackages;
Geremy Condraf1bcca82013-01-07 22:35:24 -080065
dcashman79d37cb2015-04-27 10:42:22 -070066 private long lastIssuedKeySetId = 0;
Geremy Condraf1bcca82013-01-07 22:35:24 -080067
dcashman79d37cb2015-04-27 10:42:22 -070068 private long lastIssuedKeyId = 0;
Geremy Condraf1bcca82013-01-07 22:35:24 -080069
dcashman8c04fac2015-03-23 11:39:42 -070070 class PublicKeyHandle {
71 private final PublicKey mKey;
72 private final long mId;
73 private int mRefCount;
74
75 public PublicKeyHandle(long id, PublicKey key) {
76 mId = id;
77 mRefCount = 1;
78 mKey = key;
79 }
80
81 /*
82 * Only used when reading state from packages.xml
83 */
84 private PublicKeyHandle(long id, int refCount, PublicKey key) {
85 mId = id;
86 mRefCount = refCount;
87 mKey = key;
88 }
89
90 public long getId() {
91 return mId;
92 }
93
94 public PublicKey getKey() {
95 return mKey;
96 }
97
98 public int getRefCountLPr() {
99 return mRefCount;
100 }
101
102 public void incrRefCountLPw() {
103 mRefCount++;
104 return;
105 }
dcashman87f794f2015-06-03 14:46:47 -0700106
dcashman8c04fac2015-03-23 11:39:42 -0700107 public long decrRefCountLPw() {
108 mRefCount--;
109 return mRefCount;
110 }
111 }
112
113 public KeySetManagerService(ArrayMap<String, PackageSetting> packages) {
dcashman9d2f4412014-06-09 09:27:54 -0700114 mKeySets = new LongSparseArray<KeySetHandle>();
dcashman8c04fac2015-03-23 11:39:42 -0700115 mPublicKeys = new LongSparseArray<PublicKeyHandle>();
dcashmand79fdf12014-06-20 15:53:06 -0700116 mKeySetMapping = new LongSparseArray<ArraySet<Long>>();
Geremy Condraf1bcca82013-01-07 22:35:24 -0800117 mPackages = packages;
118 }
119
Kenny Root2042e9d2013-07-08 09:31:31 -0700120 /**
Geremy Condraf1bcca82013-01-07 22:35:24 -0800121 * Determine if a package is signed by the given KeySet.
122 *
123 * Returns false if the package was not signed by all the
124 * keys in the KeySet.
125 *
126 * Returns true if the package was signed by at least the
127 * keys in the given KeySet.
128 *
129 * Note that this can return true for multiple KeySets.
130 */
dcashman9d2f4412014-06-09 09:27:54 -0700131 public boolean packageIsSignedByLPr(String packageName, KeySetHandle ks) {
dcashmand79fdf12014-06-20 15:53:06 -0700132 PackageSetting pkg = mPackages.get(packageName);
133 if (pkg == null) {
134 throw new NullPointerException("Invalid package name");
Geremy Condraf1bcca82013-01-07 22:35:24 -0800135 }
dcashmand79fdf12014-06-20 15:53:06 -0700136 if (pkg.keySetData == null) {
137 throw new NullPointerException("Package has no KeySet data");
138 }
139 long id = getIdByKeySetLPr(ks);
dcashman9d2f4412014-06-09 09:27:54 -0700140 if (id == KEYSET_NOT_FOUND) {
141 return false;
142 }
dcashman8c04fac2015-03-23 11:39:42 -0700143 ArraySet<Long> pkgKeys = mKeySetMapping.get(pkg.keySetData.getProperSigningKeySet());
144 ArraySet<Long> testKeys = mKeySetMapping.get(id);
145 return pkgKeys.containsAll(testKeys);
Geremy Condraf1bcca82013-01-07 22:35:24 -0800146 }
147
Kenny Root2042e9d2013-07-08 09:31:31 -0700148 /**
dcashman9d2f4412014-06-09 09:27:54 -0700149 * Determine if a package is signed by the given KeySet.
150 *
151 * Returns false if the package was not signed by all the
152 * keys in the KeySet, or if the package was signed by keys
153 * not in the KeySet.
154 *
155 * Note that this can return only for one KeySet.
156 */
157 public boolean packageIsSignedByExactlyLPr(String packageName, KeySetHandle ks) {
158 PackageSetting pkg = mPackages.get(packageName);
159 if (pkg == null) {
160 throw new NullPointerException("Invalid package name");
161 }
162 if (pkg.keySetData == null
163 || pkg.keySetData.getProperSigningKeySet()
164 == PackageKeySetData.KEYSET_UNASSIGNED) {
165 throw new NullPointerException("Package has no KeySet data");
dcashman8c04fac2015-03-23 11:39:42 -0700166 }
dcashman9d2f4412014-06-09 09:27:54 -0700167 long id = getIdByKeySetLPr(ks);
dcashman8c04fac2015-03-23 11:39:42 -0700168 if (id == KEYSET_NOT_FOUND) {
169 return false;
170 }
171 ArraySet<Long> pkgKeys = mKeySetMapping.get(pkg.keySetData.getProperSigningKeySet());
172 ArraySet<Long> testKeys = mKeySetMapping.get(id);
173 return pkgKeys.equals(testKeys);
dcashman9d2f4412014-06-09 09:27:54 -0700174 }
175
176 /**
dcashman87f794f2015-06-03 14:46:47 -0700177 * addScannedPackageLPw directly modifies the package metadata in pm.Settings
178 * at a point of no-return. We need to make sure that the scanned package does
179 * not contain bad keyset meta-data that could generate an incorrect
180 * PackageSetting. Verify that there is a signing keyset, there are no issues
181 * with null objects, and the upgrade and defined keysets match.
182 *
183 * Returns true if the package can safely be added to the keyset metadata.
184 */
185 public void assertScannedPackageValid(PackageParser.Package pkg)
186 throws PackageManagerException {
187 if (pkg == null || pkg.packageName == null) {
188 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
189 "Passed invalid package to keyset validation.");
190 }
Patrick Baumann420d58a2017-12-19 10:17:21 -0800191 ArraySet<PublicKey> signingKeys = pkg.mSigningDetails.publicKeys;
dcashman87f794f2015-06-03 14:46:47 -0700192 if (signingKeys == null || !(signingKeys.size() > 0) || signingKeys.contains(null)) {
193 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
194 "Package has invalid signing-key-set.");
195 }
196 ArrayMap<String, ArraySet<PublicKey>> definedMapping = pkg.mKeySetMapping;
197 if (definedMapping != null) {
198 if (definedMapping.containsKey(null) || definedMapping.containsValue(null)) {
199 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
200 "Package has null defined key set.");
201 }
202 int defMapSize = definedMapping.size();
203 for (int i = 0; i < defMapSize; i++) {
204 if (!(definedMapping.valueAt(i).size() > 0)
205 || definedMapping.valueAt(i).contains(null)) {
206 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
207 "Package has null/no public keys for defined key-sets.");
208 }
209 }
210 }
211 ArraySet<String> upgradeAliases = pkg.mUpgradeKeySets;
212 if (upgradeAliases != null) {
213 if (definedMapping == null || !(definedMapping.keySet().containsAll(upgradeAliases))) {
214 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
215 "Package has upgrade-key-sets without corresponding definitions.");
216 }
217 }
218 }
219
220 public void addScannedPackageLPw(PackageParser.Package pkg) {
221 Preconditions.checkNotNull(pkg, "Attempted to add null pkg to ksms.");
222 Preconditions.checkNotNull(pkg.packageName, "Attempted to add null pkg to ksms.");
223 PackageSetting ps = mPackages.get(pkg.packageName);
224 Preconditions.checkNotNull(ps, "pkg: " + pkg.packageName
225 + "does not have a corresponding entry in mPackages.");
Patrick Baumann420d58a2017-12-19 10:17:21 -0800226 addSigningKeySetToPackageLPw(ps, pkg.mSigningDetails.publicKeys);
dcashman87f794f2015-06-03 14:46:47 -0700227 if (pkg.mKeySetMapping != null) {
228 addDefinedKeySetsToPackageLPw(ps, pkg.mKeySetMapping);
229 if (pkg.mUpgradeKeySets != null) {
230 addUpgradeKeySetsToPackageLPw(ps, pkg.mUpgradeKeySets);
231 }
232 }
233 }
234
235 /**
dcashman8c04fac2015-03-23 11:39:42 -0700236 * Informs the system that the given package was signed by the provided KeySet.
Geremy Condraf1bcca82013-01-07 22:35:24 -0800237 */
dcashman87f794f2015-06-03 14:46:47 -0700238 void addSigningKeySetToPackageLPw(PackageSetting pkg,
dcashman9d2f4412014-06-09 09:27:54 -0700239 ArraySet<PublicKey> signingKeys) {
dcashman8c04fac2015-03-23 11:39:42 -0700240
241 /* check existing keyset for reuse or removal */
dcashman8c04fac2015-03-23 11:39:42 -0700242 long signingKeySetId = pkg.keySetData.getProperSigningKeySet();
243
244 if (signingKeySetId != PackageKeySetData.KEYSET_UNASSIGNED) {
245 ArraySet<PublicKey> existingKeys = getPublicKeysFromKeySetLPr(signingKeySetId);
dcashman87f794f2015-06-03 14:46:47 -0700246 if (existingKeys != null && existingKeys.equals(signingKeys)) {
dcashman8c04fac2015-03-23 11:39:42 -0700247
248 /* no change in signing keys, leave PackageSetting alone */
249 return;
250 } else {
251
252 /* old keyset no longer valid, remove ref */
dcashman8c04fac2015-03-23 11:39:42 -0700253 decrementKeySetLPw(signingKeySetId);
Geremy Condraf1bcca82013-01-07 22:35:24 -0800254 }
255 }
dcashman8c04fac2015-03-23 11:39:42 -0700256
257 /* create and add a new keyset */
258 KeySetHandle ks = addKeySetLPw(signingKeys);
259 long id = ks.getId();
260 pkg.keySetData.setProperSigningKeySet(id);
261 return;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800262 }
263
Kenny Root2042e9d2013-07-08 09:31:31 -0700264 /**
265 * Fetches the stable identifier associated with the given KeySet. Returns
266 * {@link #KEYSET_NOT_FOUND} if the KeySet... wasn't found.
Geremy Condraf1bcca82013-01-07 22:35:24 -0800267 */
dcashman9d2f4412014-06-09 09:27:54 -0700268 private long getIdByKeySetLPr(KeySetHandle ks) {
Geremy Condraf1bcca82013-01-07 22:35:24 -0800269 for (int keySetIndex = 0; keySetIndex < mKeySets.size(); keySetIndex++) {
dcashman9d2f4412014-06-09 09:27:54 -0700270 KeySetHandle value = mKeySets.valueAt(keySetIndex);
Geremy Condraf1bcca82013-01-07 22:35:24 -0800271 if (ks.equals(value)) {
272 return mKeySets.keyAt(keySetIndex);
273 }
274 }
275 return KEYSET_NOT_FOUND;
276 }
277
dcashman87f794f2015-06-03 14:46:47 -0700278 /**
dcashman8c04fac2015-03-23 11:39:42 -0700279 * Inform the system that the given package defines the given KeySets.
280 * Remove any KeySets the package no longer defines.
Geremy Condraf1bcca82013-01-07 22:35:24 -0800281 */
dcashman87f794f2015-06-03 14:46:47 -0700282 void addDefinedKeySetsToPackageLPw(PackageSetting pkg,
dcashman8c04fac2015-03-23 11:39:42 -0700283 ArrayMap<String, ArraySet<PublicKey>> definedMapping) {
dcashman8c04fac2015-03-23 11:39:42 -0700284 ArrayMap<String, Long> prevDefinedKeySets = pkg.keySetData.getAliases();
285
286 /* add all of the newly defined KeySets */
287 ArrayMap<String, Long> newKeySetAliases = new ArrayMap<String, Long>();
288 final int defMapSize = definedMapping.size();
289 for (int i = 0; i < defMapSize; i++) {
290 String alias = definedMapping.keyAt(i);
291 ArraySet<PublicKey> pubKeys = definedMapping.valueAt(i);
Thecrazyskull7664bce2017-01-26 08:59:51 -0600292 if (alias != null && pubKeys != null && pubKeys.size() > 0) {
dcashman8c04fac2015-03-23 11:39:42 -0700293 KeySetHandle ks = addKeySetLPw(pubKeys);
294 newKeySetAliases.put(alias, ks.getId());
295 }
296 }
297
298 /* remove each of the old references */
299 final int prevDefSize = prevDefinedKeySets.size();
300 for (int i = 0; i < prevDefSize; i++) {
301 decrementKeySetLPw(prevDefinedKeySets.valueAt(i));
302 }
303 pkg.keySetData.removeAllUpgradeKeySets();
304
305 /* switch to the just-added */
306 pkg.keySetData.setAliases(newKeySetAliases);
307 return;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800308 }
309
Kenny Root2042e9d2013-07-08 09:31:31 -0700310 /**
dcashman8c04fac2015-03-23 11:39:42 -0700311 * This informs the system that the given package has defined a KeySet
312 * alias in its manifest to be an upgradeKeySet. This must be called
313 * after all of the defined KeySets have been added.
314 */
dcashman87f794f2015-06-03 14:46:47 -0700315 void addUpgradeKeySetsToPackageLPw(PackageSetting pkg,
316 ArraySet<String> upgradeAliases) {
dcashman8c04fac2015-03-23 11:39:42 -0700317 final int uaSize = upgradeAliases.size();
318 for (int i = 0; i < uaSize; i++) {
319 pkg.keySetData.addUpgradeKeySet(upgradeAliases.valueAt(i));
320 }
321 return;
322 }
323
324 /**
325 * Fetched the {@link KeySetHandle} that a given package refers to by the
326 * provided alias. Returns null if the package is unknown or does not have a
dcashman9d2f4412014-06-09 09:27:54 -0700327 * KeySet corresponding to that alias.
Geremy Condraf1bcca82013-01-07 22:35:24 -0800328 */
dcashman9d2f4412014-06-09 09:27:54 -0700329 public KeySetHandle getKeySetByAliasAndPackageNameLPr(String packageName, String alias) {
dcashmand79fdf12014-06-20 15:53:06 -0700330 PackageSetting p = mPackages.get(packageName);
dcashman9d2f4412014-06-09 09:27:54 -0700331 if (p == null || p.keySetData == null) {
dcashman8c04fac2015-03-23 11:39:42 -0700332 return null;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800333 }
dcashman9d2f4412014-06-09 09:27:54 -0700334 Long keySetId = p.keySetData.getAliases().get(alias);
335 if (keySetId == null) {
336 throw new IllegalArgumentException("Unknown KeySet alias: " + alias);
dcashmand79fdf12014-06-20 15:53:06 -0700337 }
dcashmand79fdf12014-06-20 15:53:06 -0700338 return mKeySets.get(keySetId);
Geremy Condraf1bcca82013-01-07 22:35:24 -0800339 }
340
dcashman465ef5c2015-06-11 15:22:05 -0700341 /* Checks if an identifier refers to a known keyset */
342 public boolean isIdValidKeySetId(long id) {
343 return mKeySets.get(id) != null;
344 }
345
Todd Kennedy7c4c55d2017-11-02 10:01:39 -0700346 public boolean shouldCheckUpgradeKeySetLocked(PackageSettingBase oldPs, int scanFlags) {
347 // Can't rotate keys during boot or if sharedUser.
348 if (oldPs == null || (scanFlags&SCAN_INITIAL) != 0 || oldPs.isSharedUser()
349 || !oldPs.keySetData.isUsingUpgradeKeySets()) {
350 return false;
351 }
352 // app is using upgradeKeySets; make sure all are valid
353 long[] upgradeKeySets = oldPs.keySetData.getUpgradeKeySets();
354 for (int i = 0; i < upgradeKeySets.length; i++) {
355 if (!isIdValidKeySetId(upgradeKeySets[i])) {
356 Slog.wtf(TAG, "Package "
357 + (oldPs.name != null ? oldPs.name : "<null>")
358 + " contains upgrade-key-set reference to unknown key-set: "
359 + upgradeKeySets[i]
360 + " reverting to signatures check.");
361 return false;
362 }
363 }
364 return true;
365 }
366
367 public boolean checkUpgradeKeySetLocked(PackageSettingBase oldPS,
368 PackageParser.Package newPkg) {
369 // Upgrade keysets are being used. Determine if new package has a superset of the
370 // required keys.
371 long[] upgradeKeySets = oldPS.keySetData.getUpgradeKeySets();
372 for (int i = 0; i < upgradeKeySets.length; i++) {
373 Set<PublicKey> upgradeSet = getPublicKeysFromKeySetLPr(upgradeKeySets[i]);
Patrick Baumann420d58a2017-12-19 10:17:21 -0800374 if (upgradeSet != null && newPkg.mSigningDetails.publicKeys.containsAll(upgradeSet)) {
Todd Kennedy7c4c55d2017-11-02 10:01:39 -0700375 return true;
376 }
377 }
378 return false;
379 }
380
Kenny Root2042e9d2013-07-08 09:31:31 -0700381 /**
dcashman55b10782014-04-09 14:20:38 -0700382 * Fetches the {@link PublicKey public keys} which belong to the specified
383 * KeySet id.
384 *
385 * Returns {@code null} if the identifier doesn't
dcashman9d2f4412014-06-09 09:27:54 -0700386 * identify a {@link KeySetHandle}.
dcashman55b10782014-04-09 14:20:38 -0700387 */
dcashmand79fdf12014-06-20 15:53:06 -0700388 public ArraySet<PublicKey> getPublicKeysFromKeySetLPr(long id) {
dcashman87f794f2015-06-03 14:46:47 -0700389 ArraySet<Long> pkIds = mKeySetMapping.get(id);
390 if (pkIds == null) {
dcashmand79fdf12014-06-20 15:53:06 -0700391 return null;
dcashman55b10782014-04-09 14:20:38 -0700392 }
dcashmand79fdf12014-06-20 15:53:06 -0700393 ArraySet<PublicKey> mPubKeys = new ArraySet<PublicKey>();
dcashman8c04fac2015-03-23 11:39:42 -0700394 final int pkSize = pkIds.size();
395 for (int i = 0; i < pkSize; i++) {
396 mPubKeys.add(mPublicKeys.get(pkIds.valueAt(i)).getKey());
dcashmand79fdf12014-06-20 15:53:06 -0700397 }
398 return mPubKeys;
dcashman55b10782014-04-09 14:20:38 -0700399 }
400
401 /**
dcashman9d2f4412014-06-09 09:27:54 -0700402 * Fetches the proper {@link KeySetHandle KeySet} that signed the given
dcashman55b10782014-04-09 14:20:38 -0700403 * package.
404 *
405 * @throws IllegalArgumentException if the package has no keyset data.
dcashman8c04fac2015-03-23 11:39:42 -0700406 * @throws NullPointerException if the packgae is unknown.
Geremy Condraf1bcca82013-01-07 22:35:24 -0800407 */
dcashman9d2f4412014-06-09 09:27:54 -0700408 public KeySetHandle getSigningKeySetByPackageNameLPr(String packageName) {
dcashmand79fdf12014-06-20 15:53:06 -0700409 PackageSetting p = mPackages.get(packageName);
dcashman9d2f4412014-06-09 09:27:54 -0700410 if (p == null
411 || p.keySetData == null
412 || p.keySetData.getProperSigningKeySet()
413 == PackageKeySetData.KEYSET_UNASSIGNED) {
414 return null;
dcashman55b10782014-04-09 14:20:38 -0700415 }
dcashman9d2f4412014-06-09 09:27:54 -0700416 return mKeySets.get(p.keySetData.getProperSigningKeySet());
dcashman55b10782014-04-09 14:20:38 -0700417 }
418
419 /**
Geremy Condraf1bcca82013-01-07 22:35:24 -0800420 * Creates a new KeySet corresponding to the given keys.
421 *
Kenny Root2042e9d2013-07-08 09:31:31 -0700422 * If the {@link PublicKey PublicKeys} aren't known to the system, this
dcashman8c04fac2015-03-23 11:39:42 -0700423 * adds them. Otherwise, they're deduped and the reference count
424 * incremented.
Geremy Condraf1bcca82013-01-07 22:35:24 -0800425 *
426 * If the KeySet isn't known to the system, this adds that and creates the
dcashman8c04fac2015-03-23 11:39:42 -0700427 * mapping to the PublicKeys. If it is known, then it's deduped and the
428 * reference count is incremented.
dcashman55b10782014-04-09 14:20:38 -0700429 *
Kenny Root2042e9d2013-07-08 09:31:31 -0700430 * Throws if the provided set is {@code null}.
Geremy Condraf1bcca82013-01-07 22:35:24 -0800431 */
dcashman9d2f4412014-06-09 09:27:54 -0700432 private KeySetHandle addKeySetLPw(ArraySet<PublicKey> keys) {
dcashman8c04fac2015-03-23 11:39:42 -0700433 if (keys == null || keys.size() == 0) {
434 throw new IllegalArgumentException("Cannot add an empty set of keys!");
Geremy Condraf1bcca82013-01-07 22:35:24 -0800435 }
dcashman8c04fac2015-03-23 11:39:42 -0700436
437 /* add each of the keys in the provided set */
dcashmand79fdf12014-06-20 15:53:06 -0700438 ArraySet<Long> addedKeyIds = new ArraySet<Long>(keys.size());
dcashman8c04fac2015-03-23 11:39:42 -0700439 final int kSize = keys.size();
440 for (int i = 0; i < kSize; i++) {
441 long id = addPublicKeyLPw(keys.valueAt(i));
Geremy Condraf1bcca82013-01-07 22:35:24 -0800442 addedKeyIds.add(id);
443 }
444
dcashman8c04fac2015-03-23 11:39:42 -0700445 /* check to see if the resulting keyset is new */
dcashmand79fdf12014-06-20 15:53:06 -0700446 long existingKeySetId = getIdFromKeyIdsLPr(addedKeyIds);
Geremy Condraf1bcca82013-01-07 22:35:24 -0800447 if (existingKeySetId != KEYSET_NOT_FOUND) {
dcashman8c04fac2015-03-23 11:39:42 -0700448
449 /* public keys were incremented, but we aren't adding a new keyset: undo */
450 for (int i = 0; i < kSize; i++) {
451 decrementPublicKeyLPw(addedKeyIds.valueAt(i));
452 }
453 KeySetHandle ks = mKeySets.get(existingKeySetId);
454 ks.incrRefCountLPw();
455 return ks;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800456 }
457
dcashman8c04fac2015-03-23 11:39:42 -0700458 // get the next keyset id
dcashmand79fdf12014-06-20 15:53:06 -0700459 long id = getFreeKeySetIDLPw();
dcashman8c04fac2015-03-23 11:39:42 -0700460
461 // create the KeySet object and add to mKeySets and mapping
462 KeySetHandle ks = new KeySetHandle(id);
Geremy Condraf1bcca82013-01-07 22:35:24 -0800463 mKeySets.put(id, ks);
Geremy Condraf1bcca82013-01-07 22:35:24 -0800464 mKeySetMapping.put(id, addedKeyIds);
Geremy Condraf1bcca82013-01-07 22:35:24 -0800465 return ks;
466 }
467
dcashman8c04fac2015-03-23 11:39:42 -0700468 /*
469 * Decrements the reference to KeySet represented by the given id. If this
470 * drops to zero, then also decrement the reference to each public key it
471 * contains and remove the KeySet.
472 */
473 private void decrementKeySetLPw(long id) {
474 KeySetHandle ks = mKeySets.get(id);
dcashman87f794f2015-06-03 14:46:47 -0700475 if (ks == null) {
476 /* nothing to do */
477 return;
478 }
dcashman8c04fac2015-03-23 11:39:42 -0700479 if (ks.decrRefCountLPw() <= 0) {
480 ArraySet<Long> pubKeys = mKeySetMapping.get(id);
481 final int pkSize = pubKeys.size();
482 for (int i = 0; i < pkSize; i++) {
483 decrementPublicKeyLPw(pubKeys.valueAt(i));
484 }
485 mKeySets.delete(id);
486 mKeySetMapping.delete(id);
487 }
dcashman8c04fac2015-03-23 11:39:42 -0700488 }
489
490 /*
491 * Decrements the reference to PublicKey represented by the given id. If
492 * this drops to zero, then remove it.
493 */
494 private void decrementPublicKeyLPw(long id) {
495 PublicKeyHandle pk = mPublicKeys.get(id);
dcashman87f794f2015-06-03 14:46:47 -0700496 if (pk == null) {
497 /* nothing to do */
498 return;
499 }
dcashman8c04fac2015-03-23 11:39:42 -0700500 if (pk.decrRefCountLPw() <= 0) {
501 mPublicKeys.delete(id);
502 }
dcashman8c04fac2015-03-23 11:39:42 -0700503 }
504
Kenny Root2042e9d2013-07-08 09:31:31 -0700505 /**
Geremy Condraf1bcca82013-01-07 22:35:24 -0800506 * Adds the given PublicKey to the system, deduping as it goes.
507 */
dcashmand79fdf12014-06-20 15:53:06 -0700508 private long addPublicKeyLPw(PublicKey key) {
dcashman87f794f2015-06-03 14:46:47 -0700509 Preconditions.checkNotNull(key, "Cannot add null public key!");
dcashman8c04fac2015-03-23 11:39:42 -0700510 long id = getIdForPublicKeyLPr(key);
511 if (id != PUBLIC_KEY_NOT_FOUND) {
512
513 /* We already know about this key, increment its ref count and ret */
514 mPublicKeys.get(id).incrRefCountLPw();
515 return id;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800516 }
dcashman8c04fac2015-03-23 11:39:42 -0700517
518 /* if it's new find the first unoccupied slot in the public keys */
519 id = getFreePublicKeyIdLPw();
520 mPublicKeys.put(id, new PublicKeyHandle(id, key));
Geremy Condraf1bcca82013-01-07 22:35:24 -0800521 return id;
522 }
523
Kenny Root2042e9d2013-07-08 09:31:31 -0700524 /**
Geremy Condraf1bcca82013-01-07 22:35:24 -0800525 * Finds the stable identifier for a KeySet based on a set of PublicKey stable IDs.
526 *
527 * Returns KEYSET_NOT_FOUND if there isn't one.
528 */
dcashmand79fdf12014-06-20 15:53:06 -0700529 private long getIdFromKeyIdsLPr(Set<Long> publicKeyIds) {
Geremy Condraf1bcca82013-01-07 22:35:24 -0800530 for (int keyMapIndex = 0; keyMapIndex < mKeySetMapping.size(); keyMapIndex++) {
dcashman9d2f4412014-06-09 09:27:54 -0700531 ArraySet<Long> value = mKeySetMapping.valueAt(keyMapIndex);
Geremy Condraf1bcca82013-01-07 22:35:24 -0800532 if (value.equals(publicKeyIds)) {
533 return mKeySetMapping.keyAt(keyMapIndex);
534 }
535 }
536 return KEYSET_NOT_FOUND;
537 }
538
Kenny Root2042e9d2013-07-08 09:31:31 -0700539 /**
Geremy Condraf1bcca82013-01-07 22:35:24 -0800540 * Finds the stable identifier for a PublicKey or PUBLIC_KEY_NOT_FOUND.
541 */
dcashmand79fdf12014-06-20 15:53:06 -0700542 private long getIdForPublicKeyLPr(PublicKey k) {
Geremy Condraf1bcca82013-01-07 22:35:24 -0800543 String encodedPublicKey = new String(k.getEncoded());
544 for (int publicKeyIndex = 0; publicKeyIndex < mPublicKeys.size(); publicKeyIndex++) {
dcashman8c04fac2015-03-23 11:39:42 -0700545 PublicKey value = mPublicKeys.valueAt(publicKeyIndex).getKey();
Geremy Condraf1bcca82013-01-07 22:35:24 -0800546 String encodedExistingKey = new String(value.getEncoded());
547 if (encodedPublicKey.equals(encodedExistingKey)) {
548 return mPublicKeys.keyAt(publicKeyIndex);
549 }
550 }
551 return PUBLIC_KEY_NOT_FOUND;
552 }
553
Kenny Root2042e9d2013-07-08 09:31:31 -0700554 /**
Geremy Condraf1bcca82013-01-07 22:35:24 -0800555 * Gets an unused stable identifier for a KeySet.
556 */
dcashmand79fdf12014-06-20 15:53:06 -0700557 private long getFreeKeySetIDLPw() {
Geremy Condraf1bcca82013-01-07 22:35:24 -0800558 lastIssuedKeySetId += 1;
559 return lastIssuedKeySetId;
560 }
561
Kenny Root2042e9d2013-07-08 09:31:31 -0700562 /**
Geremy Condraf1bcca82013-01-07 22:35:24 -0800563 * Same as above, but for public keys.
564 */
dcashmand79fdf12014-06-20 15:53:06 -0700565 private long getFreePublicKeyIdLPw() {
Geremy Condraf1bcca82013-01-07 22:35:24 -0800566 lastIssuedKeyId += 1;
567 return lastIssuedKeyId;
568 }
569
dcashman8c04fac2015-03-23 11:39:42 -0700570 /*
571 * This package is being removed from the system, so we need to
572 * remove its keyset and public key references, then remove its
573 * keyset data.
574 */
dcashmand79fdf12014-06-20 15:53:06 -0700575 public void removeAppKeySetDataLPw(String packageName) {
dcashman8c04fac2015-03-23 11:39:42 -0700576
577 /* remove refs from common keysets and public keys */
578 PackageSetting pkg = mPackages.get(packageName);
dcashman87f794f2015-06-03 14:46:47 -0700579 Preconditions.checkNotNull(pkg, "pkg name: " + packageName
580 + "does not have a corresponding entry in mPackages.");
dcashman8c04fac2015-03-23 11:39:42 -0700581 long signingKeySetId = pkg.keySetData.getProperSigningKeySet();
582 decrementKeySetLPw(signingKeySetId);
583 ArrayMap<String, Long> definedKeySets = pkg.keySetData.getAliases();
584 for (int i = 0; i < definedKeySets.size(); i++) {
585 decrementKeySetLPw(definedKeySets.valueAt(i));
dcashmand79fdf12014-06-20 15:53:06 -0700586 }
587
dcashman8c04fac2015-03-23 11:39:42 -0700588 /* remove from package */
589 clearPackageKeySetDataLPw(pkg);
dcashman55b10782014-04-09 14:20:38 -0700590 return;
591 }
592
dcashman8c04fac2015-03-23 11:39:42 -0700593 private void clearPackageKeySetDataLPw(PackageSetting pkg) {
594 pkg.keySetData.setProperSigningKeySet(PackageKeySetData.KEYSET_UNASSIGNED);
595 pkg.keySetData.removeAllDefinedKeySets();
596 pkg.keySetData.removeAllUpgradeKeySets();
597 return;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800598 }
599
600 public String encodePublicKey(PublicKey k) throws IOException {
dcashman8a331212015-04-24 10:52:56 -0700601 return new String(Base64.encode(k.getEncoded(), Base64.NO_WRAP));
Geremy Condraf1bcca82013-01-07 22:35:24 -0800602 }
603
dcashmand79fdf12014-06-20 15:53:06 -0700604 public void dumpLPr(PrintWriter pw, String packageName,
Todd Kennedy91a39d12017-09-27 12:37:04 -0700605 DumpState dumpState) {
dcashmand79fdf12014-06-20 15:53:06 -0700606 boolean printedHeader = false;
dcashman8c04fac2015-03-23 11:39:42 -0700607 for (ArrayMap.Entry<String, PackageSetting> e : mPackages.entrySet()) {
dcashmand79fdf12014-06-20 15:53:06 -0700608 String keySetPackage = e.getKey();
609 if (packageName != null && !packageName.equals(keySetPackage)) {
610 continue;
611 }
612 if (!printedHeader) {
613 if (dumpState.onTitlePrinted())
614 pw.println();
615 pw.println("Key Set Manager:");
616 printedHeader = true;
617 }
618 PackageSetting pkg = e.getValue();
619 pw.print(" ["); pw.print(keySetPackage); pw.println("]");
620 if (pkg.keySetData != null) {
621 boolean printedLabel = false;
dcashman8c04fac2015-03-23 11:39:42 -0700622 for (ArrayMap.Entry<String, Long> entry : pkg.keySetData.getAliases().entrySet()) {
dcashmand79fdf12014-06-20 15:53:06 -0700623 if (!printedLabel) {
624 pw.print(" KeySets Aliases: ");
625 printedLabel = true;
626 } else {
627 pw.print(", ");
628 }
629 pw.print(entry.getKey());
630 pw.print('=');
631 pw.print(Long.toString(entry.getValue()));
Dianne Hackborncbfd23e2013-06-11 14:26:53 -0700632 }
dcashmand79fdf12014-06-20 15:53:06 -0700633 if (printedLabel) {
634 pw.println("");
Dianne Hackborncbfd23e2013-06-11 14:26:53 -0700635 }
dcashmand79fdf12014-06-20 15:53:06 -0700636 printedLabel = false;
637 if (pkg.keySetData.isUsingDefinedKeySets()) {
dcashman8c04fac2015-03-23 11:39:42 -0700638 ArrayMap<String, Long> definedKeySets = pkg.keySetData.getAliases();
639 final int dksSize = definedKeySets.size();
640 for (int i = 0; i < dksSize; i++) {
Kenny Rootdf0e6ab2013-07-03 13:38:31 -0700641 if (!printedLabel) {
dcashmand79fdf12014-06-20 15:53:06 -0700642 pw.print(" Defined KeySets: ");
Dianne Hackborncbfd23e2013-06-11 14:26:53 -0700643 printedLabel = true;
644 } else {
645 pw.print(", ");
646 }
dcashman8c04fac2015-03-23 11:39:42 -0700647 pw.print(Long.toString(definedKeySets.valueAt(i)));
Geremy Condraf1bcca82013-01-07 22:35:24 -0800648 }
dcashmand79fdf12014-06-20 15:53:06 -0700649 }
650 if (printedLabel) {
651 pw.println("");
652 }
653 printedLabel = false;
dcashman8c04fac2015-03-23 11:39:42 -0700654 final long signingKeySet = pkg.keySetData.getProperSigningKeySet();
655 pw.print(" Signing KeySets: ");
656 pw.print(Long.toString(signingKeySet));
657 pw.println("");
dcashmand79fdf12014-06-20 15:53:06 -0700658 if (pkg.keySetData.isUsingUpgradeKeySets()) {
659 for (long keySetId : pkg.keySetData.getUpgradeKeySets()) {
660 if (!printedLabel) {
661 pw.print(" Upgrade KeySets: ");
662 printedLabel = true;
663 } else {
664 pw.print(", ");
dcashman55b10782014-04-09 14:20:38 -0700665 }
dcashmand79fdf12014-06-20 15:53:06 -0700666 pw.print(Long.toString(keySetId));
dcashman55b10782014-04-09 14:20:38 -0700667 }
dcashmand79fdf12014-06-20 15:53:06 -0700668 }
669 if (printedLabel) {
670 pw.println("");
Geremy Condraf1bcca82013-01-07 22:35:24 -0800671 }
672 }
673 }
674 }
675
dcashman55b10782014-04-09 14:20:38 -0700676 void writeKeySetManagerServiceLPr(XmlSerializer serializer) throws IOException {
Geremy Condraf1bcca82013-01-07 22:35:24 -0800677 serializer.startTag(null, "keyset-settings");
dcashman55b10782014-04-09 14:20:38 -0700678 serializer.attribute(null, "version", Integer.toString(CURRENT_VERSION));
Geremy Condraf1bcca82013-01-07 22:35:24 -0800679 writePublicKeysLPr(serializer);
680 writeKeySetsLPr(serializer);
681 serializer.startTag(null, "lastIssuedKeyId");
682 serializer.attribute(null, "value", Long.toString(lastIssuedKeyId));
683 serializer.endTag(null, "lastIssuedKeyId");
684 serializer.startTag(null, "lastIssuedKeySetId");
685 serializer.attribute(null, "value", Long.toString(lastIssuedKeySetId));
686 serializer.endTag(null, "lastIssuedKeySetId");
687 serializer.endTag(null, "keyset-settings");
688 }
689
690 void writePublicKeysLPr(XmlSerializer serializer) throws IOException {
691 serializer.startTag(null, "keys");
692 for (int pKeyIndex = 0; pKeyIndex < mPublicKeys.size(); pKeyIndex++) {
693 long id = mPublicKeys.keyAt(pKeyIndex);
dcashman8c04fac2015-03-23 11:39:42 -0700694 PublicKeyHandle pkh = mPublicKeys.valueAt(pKeyIndex);
695 String encodedKey = encodePublicKey(pkh.getKey());
Geremy Condraf1bcca82013-01-07 22:35:24 -0800696 serializer.startTag(null, "public-key");
697 serializer.attribute(null, "identifier", Long.toString(id));
698 serializer.attribute(null, "value", encodedKey);
699 serializer.endTag(null, "public-key");
700 }
701 serializer.endTag(null, "keys");
702 }
703
704 void writeKeySetsLPr(XmlSerializer serializer) throws IOException {
705 serializer.startTag(null, "keysets");
706 for (int keySetIndex = 0; keySetIndex < mKeySetMapping.size(); keySetIndex++) {
707 long id = mKeySetMapping.keyAt(keySetIndex);
dcashman9d2f4412014-06-09 09:27:54 -0700708 ArraySet<Long> keys = mKeySetMapping.valueAt(keySetIndex);
Geremy Condraf1bcca82013-01-07 22:35:24 -0800709 serializer.startTag(null, "keyset");
710 serializer.attribute(null, "identifier", Long.toString(id));
711 for (long keyId : keys) {
712 serializer.startTag(null, "key-id");
713 serializer.attribute(null, "identifier", Long.toString(keyId));
714 serializer.endTag(null, "key-id");
715 }
716 serializer.endTag(null, "keyset");
717 }
718 serializer.endTag(null, "keysets");
719 }
720
dcashman8c04fac2015-03-23 11:39:42 -0700721 void readKeySetsLPw(XmlPullParser parser, ArrayMap<Long, Integer> keySetRefCounts)
Geremy Condraf1bcca82013-01-07 22:35:24 -0800722 throws XmlPullParserException, IOException {
723 int type;
724 long currentKeySetId = 0;
dcashman55b10782014-04-09 14:20:38 -0700725 int outerDepth = parser.getDepth();
dcashman8c04fac2015-03-23 11:39:42 -0700726 String recordedVersionStr = parser.getAttributeValue(null, "version");
727 if (recordedVersionStr == null) {
728 // The keyset information comes from pre-versioned devices, and
729 // is inaccurate, don't collect any of it.
dcashman55b10782014-04-09 14:20:38 -0700730 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
731 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
dcashman55b10782014-04-09 14:20:38 -0700732 continue;
733 }
734 // The KeySet information read previously from packages.xml is invalid.
735 // Destroy it all.
736 for (PackageSetting p : mPackages.values()) {
dcashmand79fdf12014-06-20 15:53:06 -0700737 clearPackageKeySetDataLPw(p);
dcashman55b10782014-04-09 14:20:38 -0700738 }
739 return;
740 }
dcashman8c04fac2015-03-23 11:39:42 -0700741 int recordedVersion = Integer.parseInt(recordedVersionStr);
dcashman55b10782014-04-09 14:20:38 -0700742 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
743 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
Geremy Condraf1bcca82013-01-07 22:35:24 -0800744 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
745 continue;
746 }
747 final String tagName = parser.getName();
748 if (tagName.equals("keys")) {
749 readKeysLPw(parser);
750 } else if (tagName.equals("keysets")) {
751 readKeySetListLPw(parser);
dcashman55b10782014-04-09 14:20:38 -0700752 } else if (tagName.equals("lastIssuedKeyId")) {
753 lastIssuedKeyId = Long.parseLong(parser.getAttributeValue(null, "value"));
754 } else if (tagName.equals("lastIssuedKeySetId")) {
755 lastIssuedKeySetId = Long.parseLong(parser.getAttributeValue(null, "value"));
Geremy Condraf1bcca82013-01-07 22:35:24 -0800756 }
757 }
dcashman8c04fac2015-03-23 11:39:42 -0700758
759 addRefCountsFromSavedPackagesLPw(keySetRefCounts);
Geremy Condraf1bcca82013-01-07 22:35:24 -0800760 }
761
762 void readKeysLPw(XmlPullParser parser)
763 throws XmlPullParserException, IOException {
764 int outerDepth = parser.getDepth();
765 int type;
766 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
767 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
768 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
769 continue;
770 }
771 final String tagName = parser.getName();
772 if (tagName.equals("public-key")) {
773 readPublicKeyLPw(parser);
Geremy Condraf1bcca82013-01-07 22:35:24 -0800774 }
775 }
776 }
777
778 void readKeySetListLPw(XmlPullParser parser)
779 throws XmlPullParserException, IOException {
780 int outerDepth = parser.getDepth();
781 int type;
782 long currentKeySetId = 0;
783 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
784 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
785 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
786 continue;
787 }
788 final String tagName = parser.getName();
789 if (tagName.equals("keyset")) {
dcashman8c04fac2015-03-23 11:39:42 -0700790 String encodedID = parser.getAttributeValue(null, "identifier");
791 currentKeySetId = Long.parseLong(encodedID);
792 int refCount = 0;
793 mKeySets.put(currentKeySetId, new KeySetHandle(currentKeySetId, refCount));
dcashman55b10782014-04-09 14:20:38 -0700794 mKeySetMapping.put(currentKeySetId, new ArraySet<Long>());
Geremy Condraf1bcca82013-01-07 22:35:24 -0800795 } else if (tagName.equals("key-id")) {
dcashman8c04fac2015-03-23 11:39:42 -0700796 String encodedID = parser.getAttributeValue(null, "identifier");
797 long id = Long.parseLong(encodedID);
Geremy Condraf1bcca82013-01-07 22:35:24 -0800798 mKeySetMapping.get(currentKeySetId).add(id);
Geremy Condraf1bcca82013-01-07 22:35:24 -0800799 }
800 }
801 }
802
Geremy Condraf1bcca82013-01-07 22:35:24 -0800803 void readPublicKeyLPw(XmlPullParser parser)
804 throws XmlPullParserException {
805 String encodedID = parser.getAttributeValue(null, "identifier");
806 long identifier = Long.parseLong(encodedID);
dcashman8c04fac2015-03-23 11:39:42 -0700807 int refCount = 0;
Geremy Condraf1bcca82013-01-07 22:35:24 -0800808 String encodedPublicKey = parser.getAttributeValue(null, "value");
809 PublicKey pub = PackageParser.parsePublicKey(encodedPublicKey);
Geremy Condraa2d8eae2013-06-21 16:59:42 -0700810 if (pub != null) {
dcashman8c04fac2015-03-23 11:39:42 -0700811 PublicKeyHandle pkh = new PublicKeyHandle(identifier, refCount, pub);
812 mPublicKeys.put(identifier, pkh);
813 }
814 }
815
816 /*
817 * Set each KeySet ref count. Also increment all public keys in each keyset.
818 */
819 private void addRefCountsFromSavedPackagesLPw(ArrayMap<Long, Integer> keySetRefCounts) {
820 final int numRefCounts = keySetRefCounts.size();
821 for (int i = 0; i < numRefCounts; i++) {
822 KeySetHandle ks = mKeySets.get(keySetRefCounts.keyAt(i));
dcashman87f794f2015-06-03 14:46:47 -0700823 if (ks == null) {
824 /* something went terribly wrong and we have references to a non-existent key-set */
825 Slog.wtf(TAG, "Encountered non-existent key-set reference when reading settings");
826 continue;
827 }
dcashman8c04fac2015-03-23 11:39:42 -0700828 ks.setRefCountLPw(keySetRefCounts.valueAt(i));
829 }
830
dcashman87f794f2015-06-03 14:46:47 -0700831 /*
832 * In case something went terribly wrong and we have keysets with no associated packges
833 * that refer to them, record the orphaned keyset ids, and remove them using
834 * decrementKeySetLPw() after all keyset references have been set so that the associtaed
835 * public keys have the appropriate references from all keysets.
836 */
837 ArraySet<Long> orphanedKeySets = new ArraySet<Long>();
dcashman8c04fac2015-03-23 11:39:42 -0700838 final int numKeySets = mKeySets.size();
839 for (int i = 0; i < numKeySets; i++) {
dcashman87f794f2015-06-03 14:46:47 -0700840 if (mKeySets.valueAt(i).getRefCountLPr() == 0) {
841 Slog.wtf(TAG, "Encountered key-set w/out package references when reading settings");
842 orphanedKeySets.add(mKeySets.keyAt(i));
843 }
dcashman8c04fac2015-03-23 11:39:42 -0700844 ArraySet<Long> pubKeys = mKeySetMapping.valueAt(i);
845 final int pkSize = pubKeys.size();
846 for (int j = 0; j < pkSize; j++) {
847 mPublicKeys.get(pubKeys.valueAt(j)).incrRefCountLPw();
848 }
Geremy Condraf1bcca82013-01-07 22:35:24 -0800849 }
dcashman87f794f2015-06-03 14:46:47 -0700850 final int numOrphans = orphanedKeySets.size();
851 for (int i = 0; i < numOrphans; i++) {
852 decrementKeySetLPw(orphanedKeySets.valueAt(i));
853 }
Geremy Condraf1bcca82013-01-07 22:35:24 -0800854 }
Ying Wangfb236b52013-07-08 10:53:58 -0700855}