KeySetManagerService.java revision 7664bceec3422f55db46d7d1bf908ae6110a6548
1d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase/*
2ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * Copyright (C) 2013 The Android Open Source Project
3d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase *
4d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Licensed under the Apache License, Version 2.0 (the "License");
5d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * you may not use this file except in compliance with the License.
6d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * You may obtain a copy of the License at
7d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase *
8d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase *      http://www.apache.org/licenses/LICENSE-2.0
9d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase *
10d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Unless required by applicable law or agreed to in writing, software
11d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * distributed under the License is distributed on an "AS IS" BASIS,
12d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * See the License for the specific language governing permissions and
14d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * limitations under the License.
15d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase */
16d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage com.android.server.pm;
18d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
19ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
20959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar
2142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport com.android.internal.util.Preconditions;
2242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport android.content.pm.PackageParser;
2342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport android.util.ArrayMap;
2442e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport android.util.ArraySet;
2542e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport android.util.Base64;
2642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport android.util.Slog;
2742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport android.util.LongSparseArray;
2842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas
2942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport java.io.IOException;
3042e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport java.io.PrintWriter;
310a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport java.security.PublicKey;
322bf89a9bae2b6110a77cf0b3754b567bb07d12a5Yigit Boyarimport java.util.Set;
33c50c4cad31d73e574b27bb3d7581542975e37263Yigit Boyar
348ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyarimport org.xmlpull.v1.XmlPullParser;
350a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport org.xmlpull.v1.XmlPullParserException;
360a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport org.xmlpull.v1.XmlSerializer;
37d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
38e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar/*
39d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Manages system-wide KeySet state.
40d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase */
41310e95e1c6dfe4f26ef594233e65e1ff83e0f1ffYigit Boyarpublic class KeySetManagerService {
42d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
43d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    static final String TAG = "KeySetManagerService";
44c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikas
45c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikas    /* original keysets implementation had no versioning info, so this is the first */
46c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikas    public static final int FIRST_VERSION = 1;
47c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikas
48c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikas    public static final int CURRENT_VERSION = FIRST_VERSION;
49c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikas
5042e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas    /** Sentinel value returned when a {@code KeySet} is not found. */
5142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas    public static final long KEYSET_NOT_FOUND = -1;
5242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas
5342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas    /** Sentinel value returned when public key is not found. */
5442e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas    protected static final long PUBLIC_KEY_NOT_FOUND = -1;
5542e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas
562bf89a9bae2b6110a77cf0b3754b567bb07d12a5Yigit Boyar    private final LongSparseArray<KeySetHandle> mKeySets;
572bf89a9bae2b6110a77cf0b3754b567bb07d12a5Yigit Boyar
58d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    private final LongSparseArray<PublicKeyHandle> mPublicKeys;
5990ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar
60d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    protected final LongSparseArray<ArraySet<Long>> mKeySetMapping;
6190ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar
62d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    private final ArrayMap<String, PackageSetting> mPackages;
63d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
64959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar    private long lastIssuedKeySetId = 0;
6511b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar
6666826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar    private long lastIssuedKeyId = 0;
670a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar
68d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    class PublicKeyHandle {
69d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        private final PublicKey mKey;
70d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        private final long mId;
71b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        private int mRefCount;
72b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
73b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        public PublicKeyHandle(long id, PublicKey key) {
74d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            mId = id;
758ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar            mRefCount = 1;
768ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar            mKey = key;
7766826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar        }
7866826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar
7966826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar        /*
807e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar         * Only used when reading state from packages.xml
81e05fbd9cfe05496e82a3abe19e07e8745985e9a5Yigit Boyar         */
82e05fbd9cfe05496e82a3abe19e07e8745985e9a5Yigit Boyar        private PublicKeyHandle(long id, int refCount, PublicKey key) {
830a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar            mId = id;
8467171c81b114f5a858dd55ec712cb584f255fc93Aurimas Liutikas            mRefCount = refCount;
8567171c81b114f5a858dd55ec712cb584f255fc93Aurimas Liutikas            mKey = key;
860a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar        }
87d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
88b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        public long getId() {
89b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            return mId;
90b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
91b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
92b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        public PublicKey getKey() {
93b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            return mKey;
94b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
957e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar
9666826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar        public int getRefCountLPr() {
9766826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar            return mRefCount;
987e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar        }
997e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar
1007e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar        public void incrRefCountLPw() {
10166826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar            mRefCount++;
10266826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar            return;
10366826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar        }
10466826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar
10566826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar        public long decrRefCountLPw() {
10666826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar            mRefCount--;
10766826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar            return mRefCount;
10866826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar        }
1090a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    }
1100a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar
1110a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public KeySetManagerService(ArrayMap<String, PackageSetting> packages) {
1120a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar        mKeySets = new LongSparseArray<KeySetHandle>();
1130a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar        mPublicKeys = new LongSparseArray<PublicKeyHandle>();
1140a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar        mKeySetMapping = new LongSparseArray<ArraySet<Long>>();
115e05fbd9cfe05496e82a3abe19e07e8745985e9a5Yigit Boyar        mPackages = packages;
1169f5e74d12c89334c2bd439b1bf19fdc5ebfbc137Aurimas Liutikas    }
117e05fbd9cfe05496e82a3abe19e07e8745985e9a5Yigit Boyar
118e05fbd9cfe05496e82a3abe19e07e8745985e9a5Yigit Boyar    /**
119e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar     * Determine if a package is signed by the given KeySet.
120e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar     *
12142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas     * Returns false if the package was not signed by all the
122e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar     * keys in the KeySet.
123e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar     *
124e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar     * Returns true if the package was signed by at least the
125e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar     * keys in the given KeySet.
126e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar     *
127e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar     * Note that this can return true for multiple KeySets.
128e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar     */
129e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar    public boolean packageIsSignedByLPr(String packageName, KeySetHandle ks) {
130e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar        PackageSetting pkg = mPackages.get(packageName);
131e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar        if (pkg == null) {
132959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar            throw new NullPointerException("Invalid package name");
133959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        }
134959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        if (pkg.keySetData == null) {
135959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar            throw new NullPointerException("Package has no KeySet data");
1362bf89a9bae2b6110a77cf0b3754b567bb07d12a5Yigit Boyar        }
1372bf89a9bae2b6110a77cf0b3754b567bb07d12a5Yigit Boyar        long id = getIdByKeySetLPr(ks);
1382bf89a9bae2b6110a77cf0b3754b567bb07d12a5Yigit Boyar        if (id == KEYSET_NOT_FOUND) {
1390a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar                return false;
1402bf89a9bae2b6110a77cf0b3754b567bb07d12a5Yigit Boyar        }
1412bf89a9bae2b6110a77cf0b3754b567bb07d12a5Yigit Boyar        ArraySet<Long> pkgKeys = mKeySetMapping.get(pkg.keySetData.getProperSigningKeySet());
1420b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar        ArraySet<Long> testKeys = mKeySetMapping.get(id);
14342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        return pkgKeys.containsAll(testKeys);
1440b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar    }
1450b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar
1460b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar    /**
1470b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar     * Determine if a package is signed by the given KeySet.
1480b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar     *
1490b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar     * Returns false if the package was not signed by all the
1500b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar     * keys in the KeySet, or if the package was signed by keys
1519c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * not in the KeySet.
1529c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     *
1539c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     * Note that this can return only for one KeySet.
1549c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri     */
1559c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri    public boolean packageIsSignedByExactlyLPr(String packageName, KeySetHandle ks) {
156f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar        PackageSetting pkg = mPackages.get(packageName);
157d8d42d52f8ae53107ffa849b86496650182e24b8Yigit Boyar        if (pkg == null) {
15842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas            throw new NullPointerException("Invalid package name");
159f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar        }
160f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar        if (pkg.keySetData == null
161f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar            || pkg.keySetData.getProperSigningKeySet()
162f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar            == PackageKeySetData.KEYSET_UNASSIGNED) {
163f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar            throw new NullPointerException("Package has no KeySet data");
164f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar         }
165d8d42d52f8ae53107ffa849b86496650182e24b8Yigit Boyar        long id = getIdByKeySetLPr(ks);
166f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar        if (id == KEYSET_NOT_FOUND) {
167f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar                return false;
1689c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        }
1699c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        ArraySet<Long> pkgKeys = mKeySetMapping.get(pkg.keySetData.getProperSigningKeySet());
1709c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri        ArraySet<Long> testKeys = mKeySetMapping.get(id);
171d8d42d52f8ae53107ffa849b86496650182e24b8Yigit Boyar        return pkgKeys.equals(testKeys);
172f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar    }
173f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar
174e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar    /**
175e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar     * addScannedPackageLPw directly modifies the package metadata in  pm.Settings
176e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar     * at a point of no-return.  We need to make sure that the scanned package does
177e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar     * not contain bad keyset meta-data that could generate an incorrect
178e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar     * PackageSetting. Verify that there is a signing keyset, there are no issues
179e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar     * with null objects, and the upgrade and defined keysets match.
1800b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar     *
1810b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar     * Returns true if the package can safely be added to the keyset metadata.
18242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas     */
1830b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar    public void assertScannedPackageValid(PackageParser.Package pkg)
1840b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar            throws PackageManagerException {
185824a7db96feacf3b68f56993ed72712bc935153eYigit Boyar        if (pkg == null || pkg.packageName == null) {
186824a7db96feacf3b68f56993ed72712bc935153eYigit Boyar            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
187824a7db96feacf3b68f56993ed72712bc935153eYigit Boyar                    "Passed invalid package to keyset validation.");
188824a7db96feacf3b68f56993ed72712bc935153eYigit Boyar        }
189824a7db96feacf3b68f56993ed72712bc935153eYigit Boyar        ArraySet<PublicKey> signingKeys = pkg.mSigningKeys;
1900b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar        if (signingKeys == null || !(signingKeys.size() > 0) || signingKeys.contains(null)) {
1910b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
192824a7db96feacf3b68f56993ed72712bc935153eYigit Boyar                    "Package has invalid signing-key-set.");
1930b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar        }
1940b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar        ArrayMap<String, ArraySet<PublicKey>> definedMapping = pkg.mKeySetMapping;
1957e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar        if (definedMapping != null) {
196e05fbd9cfe05496e82a3abe19e07e8745985e9a5Yigit Boyar            if (definedMapping.containsKey(null) || definedMapping.containsValue(null)) {
197e05fbd9cfe05496e82a3abe19e07e8745985e9a5Yigit Boyar                throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
198e05fbd9cfe05496e82a3abe19e07e8745985e9a5Yigit Boyar                        "Package has null defined key set.");
19966826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar            }
2006e83751247c5be0211d7bffaf057431c03dfef38Yigit Boyar            int defMapSize = definedMapping.size();
2016e83751247c5be0211d7bffaf057431c03dfef38Yigit Boyar            for (int i = 0; i < defMapSize; i++) {
20290ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar                if (!(definedMapping.valueAt(i).size() > 0)
20366826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar                        || definedMapping.valueAt(i).contains(null)) {
2046e83751247c5be0211d7bffaf057431c03dfef38Yigit Boyar                    throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
2056e83751247c5be0211d7bffaf057431c03dfef38Yigit Boyar                            "Package has null/no public keys for defined key-sets.");
2067e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar                }
2077e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar            }
2087e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar        }
2097e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar        ArraySet<String> upgradeAliases = pkg.mUpgradeKeySets;
2107f5e94985f795f81884334ca2752a0469a998762Yigit Boyar        if (upgradeAliases != null) {
2117f5e94985f795f81884334ca2752a0469a998762Yigit Boyar            if (definedMapping == null || !(definedMapping.keySet().containsAll(upgradeAliases))) {
2127f5e94985f795f81884334ca2752a0469a998762Yigit Boyar                throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
2137f5e94985f795f81884334ca2752a0469a998762Yigit Boyar                        "Package has upgrade-key-sets without corresponding definitions.");
2147e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar            }
2157e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar        }
2167e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar    }
2177e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar
2180a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void addScannedPackageLPw(PackageParser.Package pkg) {
2190a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar        Preconditions.checkNotNull(pkg, "Attempted to add null pkg to ksms.");
2200a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar        Preconditions.checkNotNull(pkg.packageName, "Attempted to add null pkg to ksms.");
2210a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar        PackageSetting ps = mPackages.get(pkg.packageName);
2220a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar        Preconditions.checkNotNull(ps, "pkg: " + pkg.packageName
2230a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar                    + "does not have a corresponding entry in mPackages.");
2248ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar        addSigningKeySetToPackageLPw(ps, pkg.mSigningKeys);
2258ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar        if (pkg.mKeySetMapping != null) {
2268ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar            addDefinedKeySetsToPackageLPw(ps, pkg.mKeySetMapping);
2278ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar            if (pkg.mUpgradeKeySets != null) {
2288ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar                addUpgradeKeySetsToPackageLPw(ps, pkg.mUpgradeKeySets);
2298ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar            }
2308ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar        }
2318ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar    }
232ca9ce7ccdccf6b6a2a81da73dd1e6425d90e4b23Yigit Boyar
2336e83751247c5be0211d7bffaf057431c03dfef38Yigit Boyar    /**
2346e83751247c5be0211d7bffaf057431c03dfef38Yigit Boyar     * Informs the system that the given package was signed by the provided KeySet.
2356e83751247c5be0211d7bffaf057431c03dfef38Yigit Boyar     */
2366e83751247c5be0211d7bffaf057431c03dfef38Yigit Boyar    void addSigningKeySetToPackageLPw(PackageSetting pkg,
2376e83751247c5be0211d7bffaf057431c03dfef38Yigit Boyar            ArraySet<PublicKey> signingKeys) {
238121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar
2396e83751247c5be0211d7bffaf057431c03dfef38Yigit Boyar        /* check existing keyset for reuse or removal */
2408ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar        long signingKeySetId = pkg.keySetData.getProperSigningKeySet();
2418ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar
242c50c4cad31d73e574b27bb3d7581542975e37263Yigit Boyar        if (signingKeySetId != PackageKeySetData.KEYSET_UNASSIGNED) {
243c50c4cad31d73e574b27bb3d7581542975e37263Yigit Boyar            ArraySet<PublicKey> existingKeys = getPublicKeysFromKeySetLPr(signingKeySetId);
244c50c4cad31d73e574b27bb3d7581542975e37263Yigit Boyar            if (existingKeys != null && existingKeys.equals(signingKeys)) {
245c50c4cad31d73e574b27bb3d7581542975e37263Yigit Boyar
24629c349ed8863cc15c2580465227c37771ac49576Yigit Boyar                /* no change in signing keys, leave PackageSetting alone */
24729c349ed8863cc15c2580465227c37771ac49576Yigit Boyar                return;
248c50c4cad31d73e574b27bb3d7581542975e37263Yigit Boyar            } else {
249c50c4cad31d73e574b27bb3d7581542975e37263Yigit Boyar
250c50c4cad31d73e574b27bb3d7581542975e37263Yigit Boyar                /* old keyset no longer valid, remove ref */
251b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                decrementKeySetLPw(signingKeySetId);
252d7e2f2ab1d253133fa54f309e74a7ee384c33971Yigit Boyar            }
253d7e2f2ab1d253133fa54f309e74a7ee384c33971Yigit Boyar        }
254d7e2f2ab1d253133fa54f309e74a7ee384c33971Yigit Boyar
25590ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar        /* create and add a new keyset */
25690ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar        KeySetHandle ks = addKeySetLPw(signingKeys);
25790ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar        long id = ks.getId();
25842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        pkg.keySetData.setProperSigningKeySet(id);
259b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        return;
260b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    }
261abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar
26266826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar    /**
26366826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar     * Fetches the stable identifier associated with the given KeySet. Returns
26466826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar     * {@link #KEYSET_NOT_FOUND} if the KeySet... wasn't found.
26566826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar     */
26666826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar    private long getIdByKeySetLPr(KeySetHandle ks) {
26766826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar        for (int keySetIndex = 0; keySetIndex < mKeySets.size(); keySetIndex++) {
26866826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar            KeySetHandle value = mKeySets.valueAt(keySetIndex);
269abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar            if (ks.equals(value)) {
270a90fb62f06861beb3af9f9b3356ef0bb0685547cYigit Boyar                return mKeySets.keyAt(keySetIndex);
271abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar            }
272abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar        }
27390ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar        return KEYSET_NOT_FOUND;
274b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    }
275b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
27690ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar    /**
277b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar     * Inform the system that the given package defines the given KeySets.
278b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar     * Remove any KeySets the package no longer defines.
2799051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar     */
2809051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar    void addDefinedKeySetsToPackageLPw(PackageSetting pkg,
28142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas            ArrayMap<String, ArraySet<PublicKey>> definedMapping) {
2829051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar        ArrayMap<String, Long> prevDefinedKeySets = pkg.keySetData.getAliases();
2839051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar
2849051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar        /* add all of the newly defined KeySets */
2859051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar        ArrayMap<String, Long> newKeySetAliases = new ArrayMap<String, Long>();
2869051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar        final int defMapSize = definedMapping.size();
2879051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar        for (int i = 0; i < defMapSize; i++) {
2889051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar            String alias = definedMapping.keyAt(i);
2899051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar            ArraySet<PublicKey> pubKeys = definedMapping.valueAt(i);
2909051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar            if (alias != null && pubKeys != null && pubKeys.size() > 0) {
2919051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar                KeySetHandle ks = addKeySetLPw(pubKeys);
2929051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar                newKeySetAliases.put(alias, ks.getId());
2939051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar            }
2949051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar        }
2959051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar
296504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar        /* remove each of the old references */
297504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar        final int prevDefSize = prevDefinedKeySets.size();
298959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        for (int i = 0; i < prevDefSize; i++) {
299959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar            decrementKeySetLPw(prevDefinedKeySets.valueAt(i));
30042e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        }
301959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        pkg.keySetData.removeAllUpgradeKeySets();
302959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar
303959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        /* switch to the just-added */
304959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        pkg.keySetData.setAliases(newKeySetAliases);
305959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        return;
306959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar    }
307959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar
308959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar    /**
309959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar     * This informs the system that the given package has defined a KeySet
310959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar     * alias in its manifest to be an upgradeKeySet.  This must be called
311959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar     * after all of the defined KeySets have been added.
312959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar     */
313959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar    void addUpgradeKeySetsToPackageLPw(PackageSetting pkg,
314959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar            ArraySet<String> upgradeAliases) {
315959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        final int uaSize = upgradeAliases.size();
316959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        for (int i = 0; i < uaSize; i++) {
317959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar            pkg.keySetData.addUpgradeKeySet(upgradeAliases.valueAt(i));
318959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        }
319959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        return;
320959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar    }
321959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar
322959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar    /**
323542f1260934df280985294eaef1ec8469863281fYigit Boyar     * Fetched the {@link KeySetHandle} that a given package refers to by the
32442e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas     * provided alias.  Returns null if the package is unknown or does not have a
32542e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas     * KeySet corresponding to that alias.
32642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas     */
32742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas    public KeySetHandle getKeySetByAliasAndPackageNameLPr(String packageName, String alias) {
32842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        PackageSetting p = mPackages.get(packageName);
32942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        if (p == null || p.keySetData == null) {
330046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard            return null;
331046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard        }
332046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard        Long keySetId = p.keySetData.getAliases().get(alias);
333046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard        if (keySetId == null) {
334046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard            throw new IllegalArgumentException("Unknown KeySet alias: " + alias);
335046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard        }
336959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        return mKeySets.get(keySetId);
337959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar    }
338959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar
339542f1260934df280985294eaef1ec8469863281fYigit Boyar    /* Checks if an identifier refers to a known keyset */
340542f1260934df280985294eaef1ec8469863281fYigit Boyar    public boolean isIdValidKeySetId(long id) {
341542f1260934df280985294eaef1ec8469863281fYigit Boyar        return mKeySets.get(id) != null;
342b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    }
3430b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar
3440b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar    /**
3450b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar     * Fetches the {@link PublicKey public keys} which belong to the specified
3460b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar     * KeySet id.
347f129f1b050d2542a91fe8175eac30183beb07b41Chris Banes     *
348e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar     * Returns {@code null} if the identifier doesn't
349e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar     * identify a {@link KeySetHandle}.
350e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar     */
351e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar    public ArraySet<PublicKey> getPublicKeysFromKeySetLPr(long id) {
352b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        ArraySet<Long> pkIds = mKeySetMapping.get(id);
3530b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar        if (pkIds == null) {
3540b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar            return null;
3550b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar        }
3560b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar        ArraySet<PublicKey> mPubKeys = new ArraySet<PublicKey>();
3570b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar        final int pkSize = pkIds.size();
3580b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar        for (int i = 0; i < pkSize; i++) {
3590b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar            mPubKeys.add(mPublicKeys.get(pkIds.valueAt(i)).getKey());
3600b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar        }
3610b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar        return mPubKeys;
3620b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar    }
3630b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar
3640b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar    /**
3650b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar     * Fetches the proper {@link KeySetHandle KeySet} that signed the given
3668da5bba529a2fe9bd2aafab28010e11ec4de93c7Yigit Boyar     * package.
3678da5bba529a2fe9bd2aafab28010e11ec4de93c7Yigit Boyar     *
3680b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar     * @throws IllegalArgumentException if the package has no keyset data.
3690b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar     * @throws NullPointerException if the packgae is unknown.
370619ac016831a5ad75c2e0921c9036b6f030a9e63Yigit Boyar     */
3710b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar    public KeySetHandle  getSigningKeySetByPackageNameLPr(String packageName) {
3720b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar        PackageSetting p = mPackages.get(packageName);
3730b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar        if (p == null
3740b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar            || p.keySetData == null
3750b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar            || p.keySetData.getProperSigningKeySet()
376e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar            == PackageKeySetData.KEYSET_UNASSIGNED) {
377e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar            return null;
378e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar        }
379e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar        return mKeySets.get(p.keySetData.getProperSigningKeySet());
380e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar    }
381e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar
382e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar    /**
383e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar     * Creates a new KeySet corresponding to the given keys.
3840a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar     *
3850a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar     * If the {@link PublicKey PublicKeys} aren't known to the system, this
386e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar     * adds them. Otherwise, they're deduped and the reference count
387e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar     * incremented.
388e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar     *
389e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar     * If the KeySet isn't known to the system, this adds that and creates the
3908ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar     * mapping to the PublicKeys. If it is known, then it's deduped and the
39142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas     * reference count is incremented.
392b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar     *
393b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar     * Throws if the provided set is {@code null}.
394a90fb62f06861beb3af9f9b3356ef0bb0685547cYigit Boyar     */
395b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    private KeySetHandle addKeySetLPw(ArraySet<PublicKey> keys) {
396b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        if (keys == null || keys.size() == 0) {
397b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            throw new IllegalArgumentException("Cannot add an empty set of keys!");
398b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
399310e95e1c6dfe4f26ef594233e65e1ff83e0f1ffYigit Boyar
400a90fb62f06861beb3af9f9b3356ef0bb0685547cYigit Boyar        /* add each of the keys in the provided set */
401310e95e1c6dfe4f26ef594233e65e1ff83e0f1ffYigit Boyar        ArraySet<Long> addedKeyIds = new ArraySet<Long>(keys.size());
402310e95e1c6dfe4f26ef594233e65e1ff83e0f1ffYigit Boyar        final int kSize = keys.size();
40342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        for (int i = 0; i < kSize; i++) {
40442e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas            long id = addPublicKeyLPw(keys.valueAt(i));
40542e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas            addedKeyIds.add(id);
40642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        }
40742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas
40842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        /* check to see if the resulting keyset is new */
40942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        long existingKeySetId = getIdFromKeyIdsLPr(addedKeyIds);
410b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        if (existingKeySetId != KEYSET_NOT_FOUND) {
411b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar
41242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas            /* public keys were incremented, but we aren't adding a new keyset: undo */
41342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas            for (int i = 0; i < kSize; i++) {
41442e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas                decrementPublicKeyLPw(addedKeyIds.valueAt(i));
41542e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas            }
41642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas            KeySetHandle ks = mKeySets.get(existingKeySetId);
41742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas            ks.incrRefCountLPw();
41842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas            return ks;
41942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        }
420e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar
421d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        // get the next keyset id
42242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        long id = getFreeKeySetIDLPw();
42342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas
42442e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        // create the KeySet object and add to mKeySets and mapping
425c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        KeySetHandle ks = new KeySetHandle(id);
42642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mKeySets.put(id, ks);
42742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mKeySetMapping.put(id, addedKeyIds);
42842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        return ks;
42942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas    }
43042e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas
43142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas    /*
43242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas     * Decrements the reference to KeySet represented by the given id.  If this
43342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas     * drops to zero, then also decrement the reference to each public key it
434c587f7dba5a337169e854e235da59f595255d6ccAga Madurska     * contains and remove the KeySet.
43542e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas     */
43642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas    private void decrementKeySetLPw(long id) {
43742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        KeySetHandle ks = mKeySets.get(id);
438c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        if (ks == null) {
439c587f7dba5a337169e854e235da59f595255d6ccAga Madurska            /* nothing to do */
440c587f7dba5a337169e854e235da59f595255d6ccAga Madurska            return;
4418edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar        }
44242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        if (ks.decrRefCountLPw() <= 0) {
4438edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar            ArraySet<Long> pubKeys = mKeySetMapping.get(id);
4448edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar            final int pkSize = pubKeys.size();
4458edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar            for (int i = 0; i < pkSize; i++) {
4468edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar                decrementPublicKeyLPw(pubKeys.valueAt(i));
4478edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar            }
4488edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar            mKeySets.delete(id);
4498edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar            mKeySetMapping.delete(id);
450959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        }
451959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar    }
452959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar
453959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar    /*
454959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar     * Decrements the reference to PublicKey represented by the given id.  If
455619ac016831a5ad75c2e0921c9036b6f030a9e63Yigit Boyar     * this drops to zero, then remove it.
456619ac016831a5ad75c2e0921c9036b6f030a9e63Yigit Boyar     */
457619ac016831a5ad75c2e0921c9036b6f030a9e63Yigit Boyar    private void decrementPublicKeyLPw(long id) {
458959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        PublicKeyHandle pk = mPublicKeys.get(id);
459959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        if (pk == null) {
460959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar            /* nothing to do */
461959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar            return;
4628a11e6829c522aa1efcc903afa4c01d337082eabChris Craik        }
463959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        if (pk.decrRefCountLPw() <= 0) {
464959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar            mPublicKeys.delete(id);
465959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        }
466959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar    }
467959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar
4688a11e6829c522aa1efcc903afa4c01d337082eabChris Craik    /**
469959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar     * Adds the given PublicKey to the system, deduping as it goes.
470959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar     */
471959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar    private long addPublicKeyLPw(PublicKey key) {
47242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        Preconditions.checkNotNull(key, "Cannot add null public key!");
473959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        long id = getIdForPublicKeyLPr(key);
474959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        if (id != PUBLIC_KEY_NOT_FOUND) {
475959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar
476959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar            /* We already know about this key, increment its ref count and ret */
477959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar            mPublicKeys.get(id).incrRefCountLPw();
478959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar            return id;
479959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        }
480959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar
481959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        /* if it's new find the first unoccupied slot in the public keys */
482959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        id = getFreePublicKeyIdLPw();
483959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        mPublicKeys.put(id, new PublicKeyHandle(id, key));
484959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        return id;
485959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar    }
48642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas
4878edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar    /**
4888edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar     * Finds the stable identifier for a KeySet based on a set of PublicKey stable IDs.
4898edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar     *
4908edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar     * Returns KEYSET_NOT_FOUND if there isn't one.
4918edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar     */
492de5f54783555fa2e778c4ed6760472a002b2589bYigit Boyar    private long getIdFromKeyIdsLPr(Set<Long> publicKeyIds) {
493959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        for (int keyMapIndex = 0; keyMapIndex < mKeySetMapping.size(); keyMapIndex++) {
4949c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri            ArraySet<Long> value = mKeySetMapping.valueAt(keyMapIndex);
495959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar            if (value.equals(publicKeyIds)) {
496959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar                return mKeySetMapping.keyAt(keyMapIndex);
497619ac016831a5ad75c2e0921c9036b6f030a9e63Yigit Boyar            }
498619ac016831a5ad75c2e0921c9036b6f030a9e63Yigit Boyar        }
499619ac016831a5ad75c2e0921c9036b6f030a9e63Yigit Boyar        return KEYSET_NOT_FOUND;
500959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar    }
50142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas
502959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar    /**
503959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar     * Finds the stable identifier for a PublicKey or PUBLIC_KEY_NOT_FOUND.
504959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar     */
505959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar    private long getIdForPublicKeyLPr(PublicKey k) {
506959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        String encodedPublicKey = new String(k.getEncoded());
507959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar        for (int publicKeyIndex = 0; publicKeyIndex < mPublicKeys.size(); publicKeyIndex++) {
508504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar            PublicKey value = mPublicKeys.valueAt(publicKeyIndex).getKey();
5098edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar            String encodedExistingKey = new String(value.getEncoded());
5108edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar            if (encodedPublicKey.equals(encodedExistingKey)) {
511ef3e37fe088c7d8e614bbc4ed58d6c0d3fa807a1Dake Gu                return mPublicKeys.keyAt(publicKeyIndex);
51242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas            }
513ef3e37fe088c7d8e614bbc4ed58d6c0d3fa807a1Dake Gu        }
514ef3e37fe088c7d8e614bbc4ed58d6c0d3fa807a1Dake Gu        return PUBLIC_KEY_NOT_FOUND;
515ef3e37fe088c7d8e614bbc4ed58d6c0d3fa807a1Dake Gu    }
516ef3e37fe088c7d8e614bbc4ed58d6c0d3fa807a1Dake Gu
517ef3e37fe088c7d8e614bbc4ed58d6c0d3fa807a1Dake Gu    /**
518ef3e37fe088c7d8e614bbc4ed58d6c0d3fa807a1Dake Gu     * Gets an unused stable identifier for a KeySet.
519ef3e37fe088c7d8e614bbc4ed58d6c0d3fa807a1Dake Gu     */
5204bcf88a56f3048a7ead6f423faa8fa08b95c5daeYigit Boyar    private long getFreeKeySetIDLPw() {
52142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        lastIssuedKeySetId += 1;
5224bcf88a56f3048a7ead6f423faa8fa08b95c5daeYigit Boyar        return lastIssuedKeySetId;
5234bcf88a56f3048a7ead6f423faa8fa08b95c5daeYigit Boyar    }
5244bcf88a56f3048a7ead6f423faa8fa08b95c5daeYigit Boyar
5254bcf88a56f3048a7ead6f423faa8fa08b95c5daeYigit Boyar    /**
5264bcf88a56f3048a7ead6f423faa8fa08b95c5daeYigit Boyar     * Same as above, but for public keys.
5274bcf88a56f3048a7ead6f423faa8fa08b95c5daeYigit Boyar     */
5284bcf88a56f3048a7ead6f423faa8fa08b95c5daeYigit Boyar    private long getFreePublicKeyIdLPw() {
5293d37afbbf7bf547c1e1c541df9be9696da668884Yigit Boyar        lastIssuedKeyId += 1;
530d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        return lastIssuedKeyId;
531115ba0c7b2a14aa4cd0273952195e1d8f6468f87Yigit Boyar    }
532178c4e15a0ebb501d2bb4f3ac3176e4c44954954Yigit Boyar
533d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    /*
534d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * This package is being removed from the system, so we need to
535d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     * remove its keyset and public key references, then remove its
536310e95e1c6dfe4f26ef594233e65e1ff83e0f1ffYigit Boyar     * keyset data.
537d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase     */
538504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar    public void removeAppKeySetDataLPw(String packageName) {
539504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar
540504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar        /* remove refs from common keysets and public keys */
541178c4e15a0ebb501d2bb4f3ac3176e4c44954954Yigit Boyar        PackageSetting pkg = mPackages.get(packageName);
542178c4e15a0ebb501d2bb4f3ac3176e4c44954954Yigit Boyar        Preconditions.checkNotNull(pkg, "pkg name: " + packageName
543178c4e15a0ebb501d2bb4f3ac3176e4c44954954Yigit Boyar                + "does not have a corresponding entry in mPackages.");
544178c4e15a0ebb501d2bb4f3ac3176e4c44954954Yigit Boyar        long signingKeySetId = pkg.keySetData.getProperSigningKeySet();
545178c4e15a0ebb501d2bb4f3ac3176e4c44954954Yigit Boyar        decrementKeySetLPw(signingKeySetId);
546178c4e15a0ebb501d2bb4f3ac3176e4c44954954Yigit Boyar        ArrayMap<String, Long> definedKeySets = pkg.keySetData.getAliases();
547178c4e15a0ebb501d2bb4f3ac3176e4c44954954Yigit Boyar        for (int i = 0; i < definedKeySets.size(); i++) {
548178c4e15a0ebb501d2bb4f3ac3176e4c44954954Yigit Boyar            decrementKeySetLPw(definedKeySets.valueAt(i));
549178c4e15a0ebb501d2bb4f3ac3176e4c44954954Yigit Boyar        }
550504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar
551d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        /* remove from package */
552da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        clearPackageKeySetDataLPw(pkg);
553da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        return;
554da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar    }
555da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar
556da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar    private void clearPackageKeySetDataLPw(PackageSetting pkg) {
557da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        pkg.keySetData.setProperSigningKeySet(PackageKeySetData.KEYSET_UNASSIGNED);
558da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        pkg.keySetData.removeAllDefinedKeySets();
559da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        pkg.keySetData.removeAllUpgradeKeySets();
560da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        return;
561da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar    }
5629c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri
563e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar    public String encodePublicKey(PublicKey k) throws IOException {
564f129f1b050d2542a91fe8175eac30183beb07b41Chris Banes        return new String(Base64.encode(k.getEncoded(), Base64.NO_WRAP));
565f129f1b050d2542a91fe8175eac30183beb07b41Chris Banes    }
566e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar
567e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar    public void dumpLPr(PrintWriter pw, String packageName,
568d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                        PackageManagerService.DumpState dumpState) {
569d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        boolean printedHeader = false;
570d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        for (ArrayMap.Entry<String, PackageSetting> e : mPackages.entrySet()) {
571d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            String keySetPackage = e.getKey();
572d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            if (packageName != null && !packageName.equals(keySetPackage)) {
57366826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar                continue;
57466826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar            }
57566826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar            if (!printedHeader) {
57666826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar                if (dumpState.onTitlePrinted())
57766826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar                    pw.println();
57866826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar                pw.println("Key Set Manager:");
57966826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar                printedHeader = true;
58066826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar            }
58166826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar            PackageSetting pkg = e.getValue();
58266826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar            pw.print("  ["); pw.print(keySetPackage); pw.println("]");
58366826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar            if (pkg.keySetData != null) {
584629687bba8da1a73c48d8fe87393a13581ce46caYigit Boyar                boolean printedLabel = false;
585629687bba8da1a73c48d8fe87393a13581ce46caYigit Boyar                for (ArrayMap.Entry<String, Long> entry : pkg.keySetData.getAliases().entrySet()) {
586e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar                    if (!printedLabel) {
587e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar                        pw.print("      KeySets Aliases: ");
588e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar                        printedLabel = true;
589e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar                    } else {
590e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar                        pw.print(", ");
591e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar                    }
592e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar                    pw.print(entry.getKey());
593e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar                    pw.print('=');
594e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar                    pw.print(Long.toString(entry.getValue()));
595e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar                }
596e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar                if (printedLabel) {
597e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar                    pw.println("");
598e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar                }
599b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                printedLabel = false;
600b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                if (pkg.keySetData.isUsingDefinedKeySets()) {
601b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                    ArrayMap<String, Long> definedKeySets = pkg.keySetData.getAliases();
602b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                    final int dksSize = definedKeySets.size();
603b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                    for (int i = 0; i < dksSize; i++) {
604b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                        if (!printedLabel) {
605b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                            pw.print("      Defined KeySets: ");
606b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                            printedLabel = true;
607b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                        } else {
608b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                            pw.print(", ");
609d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                        }
610d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                        pw.print(Long.toString(definedKeySets.valueAt(i)));
611d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                    }
612d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                }
613d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                if (printedLabel) {
614d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                    pw.println("");
615d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                }
616d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                printedLabel = false;
617d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                final long signingKeySet = pkg.keySetData.getProperSigningKeySet();
618d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                pw.print("      Signing KeySets: ");
619d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                pw.print(Long.toString(signingKeySet));
620d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                pw.println("");
621115ba0c7b2a14aa4cd0273952195e1d8f6468f87Yigit Boyar                if (pkg.keySetData.isUsingUpgradeKeySets()) {
622b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                    for (long keySetId : pkg.keySetData.getUpgradeKeySets()) {
623d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                        if (!printedLabel) {
624d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                            pw.print("      Upgrade KeySets: ");
6258ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar                            printedLabel = true;
6268ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar                        } else {
6278ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar                            pw.print(", ");
6288ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar                        }
6298ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar                        pw.print(Long.toString(keySetId));
630d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                    }
631d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                }
632d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                if (printedLabel) {
633b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                    pw.println("");
634b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar                }
635b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            }
636b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        }
637e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar    }
638fe3996cf5af65fe11cc3ed47b67123ec267bd336Yigit Boyar
639b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar    void writeKeySetManagerServiceLPr(XmlSerializer serializer) throws IOException {
640d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        serializer.startTag(null, "keyset-settings");
641d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        serializer.attribute(null, "version", Integer.toString(CURRENT_VERSION));
6425ced882cabdcefbb469e332f6f73983999aad0e5Yigit Boyar        writePublicKeysLPr(serializer);
643504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar        writeKeySetsLPr(serializer);
6445ced882cabdcefbb469e332f6f73983999aad0e5Yigit Boyar        serializer.startTag(null, "lastIssuedKeyId");
645b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        serializer.attribute(null, "value", Long.toString(lastIssuedKeyId));
646d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        serializer.endTag(null, "lastIssuedKeyId");
647d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        serializer.startTag(null, "lastIssuedKeySetId");
648d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        serializer.attribute(null, "value", Long.toString(lastIssuedKeySetId));
649b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        serializer.endTag(null, "lastIssuedKeySetId");
650b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar        serializer.endTag(null, "keyset-settings");
651c8b0ff5869e17a656a3a1d7fb306efa5b99fa07fYigit Boyar    }
652c8b0ff5869e17a656a3a1d7fb306efa5b99fa07fYigit Boyar
653c8b0ff5869e17a656a3a1d7fb306efa5b99fa07fYigit Boyar    void writePublicKeysLPr(XmlSerializer serializer) throws IOException {
654c8b0ff5869e17a656a3a1d7fb306efa5b99fa07fYigit Boyar        serializer.startTag(null, "keys");
655c8b0ff5869e17a656a3a1d7fb306efa5b99fa07fYigit Boyar        for (int pKeyIndex = 0; pKeyIndex < mPublicKeys.size(); pKeyIndex++) {
656c8b0ff5869e17a656a3a1d7fb306efa5b99fa07fYigit Boyar            long id = mPublicKeys.keyAt(pKeyIndex);
657c8b0ff5869e17a656a3a1d7fb306efa5b99fa07fYigit Boyar            PublicKeyHandle pkh = mPublicKeys.valueAt(pKeyIndex);
658b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar            String encodedKey = encodePublicKey(pkh.getKey());
6598da5bba529a2fe9bd2aafab28010e11ec4de93c7Yigit Boyar            serializer.startTag(null, "public-key");
6608da5bba529a2fe9bd2aafab28010e11ec4de93c7Yigit Boyar            serializer.attribute(null, "identifier", Long.toString(id));
661c8b0ff5869e17a656a3a1d7fb306efa5b99fa07fYigit Boyar            serializer.attribute(null, "value", encodedKey);
662d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            serializer.endTag(null, "public-key");
663e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar        }
664e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar        serializer.endTag(null, "keys");
665e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar    }
666e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar
667e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar    void writeKeySetsLPr(XmlSerializer serializer) throws IOException {
668e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar        serializer.startTag(null, "keysets");
669e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar        for (int keySetIndex = 0; keySetIndex < mKeySetMapping.size(); keySetIndex++) {
670e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar            long id = mKeySetMapping.keyAt(keySetIndex);
671504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar            ArraySet<Long> keys = mKeySetMapping.valueAt(keySetIndex);
672d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            serializer.startTag(null, "keyset");
673d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            serializer.attribute(null, "identifier", Long.toString(id));
674fe3996cf5af65fe11cc3ed47b67123ec267bd336Yigit Boyar            for (long keyId : keys) {
675fe3996cf5af65fe11cc3ed47b67123ec267bd336Yigit Boyar                serializer.startTag(null, "key-id");
676e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar                serializer.attribute(null, "identifier", Long.toString(keyId));
677e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar                serializer.endTag(null, "key-id");
678e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar            }
679e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar            serializer.endTag(null, "keyset");
680e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar        }
681fe3996cf5af65fe11cc3ed47b67123ec267bd336Yigit Boyar        serializer.endTag(null, "keysets");
682fe3996cf5af65fe11cc3ed47b67123ec267bd336Yigit Boyar    }
683bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar
684bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar    void readKeySetsLPw(XmlPullParser parser, ArrayMap<Long, Integer> keySetRefCounts)
685bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar            throws XmlPullParserException, IOException {
686bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar        int type;
687bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar        long currentKeySetId = 0;
688bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar        int outerDepth = parser.getDepth();
689bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar        String recordedVersionStr = parser.getAttributeValue(null, "version");
690bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar        if (recordedVersionStr == null) {
691bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar            // The keyset information comes from pre-versioned devices, and
692bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar            // is inaccurate, don't collect any of it.
693bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
694bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
695bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar                continue;
696bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar            }
697f129f1b050d2542a91fe8175eac30183beb07b41Chris Banes            // The KeySet information read previously from packages.xml is invalid.
698bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar            // Destroy it all.
699bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar            for (PackageSetting p : mPackages.values()) {
700bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar                clearPackageKeySetDataLPw(p);
701bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar            }
702bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar            return;
703bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar        }
704f129f1b050d2542a91fe8175eac30183beb07b41Chris Banes        int recordedVersion = Integer.parseInt(recordedVersionStr);
705bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
706bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar               && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
7079290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
7089290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar                continue;
7099290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar            }
7109290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar            final String tagName = parser.getName();
7119290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar            if (tagName.equals("keys")) {
7129290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar                readKeysLPw(parser);
7139290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar            } else if (tagName.equals("keysets")) {
7149290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar                readKeySetListLPw(parser);
7159290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar            } else if (tagName.equals("lastIssuedKeyId")) {
7169290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar                lastIssuedKeyId = Long.parseLong(parser.getAttributeValue(null, "value"));
7179290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar            } else if (tagName.equals("lastIssuedKeySetId")) {
7189290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar                lastIssuedKeySetId = Long.parseLong(parser.getAttributeValue(null, "value"));
7199290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar            }
7209290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar        }
7219290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar
7229290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar        addRefCountsFromSavedPackagesLPw(keySetRefCounts);
7239290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar    }
7249290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar
7259290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar    void readKeysLPw(XmlPullParser parser)
7269290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar            throws XmlPullParserException, IOException {
7279290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar        int outerDepth = parser.getDepth();
7289290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar        int type;
7299290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
7309290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
7319290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
7329290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar                continue;
7339290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar            }
7349290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar            final String tagName = parser.getName();
7359290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar            if (tagName.equals("public-key")) {
7369290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar                readPublicKeyLPw(parser);
7379290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar            }
7389290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar        }
7399290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar    }
7409290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar
7419290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar    void readKeySetListLPw(XmlPullParser parser)
7429290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar            throws XmlPullParserException, IOException {
7439290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar        int outerDepth = parser.getDepth();
7449290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar        int type;
7459290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar        long currentKeySetId = 0;
7469290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
7479290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
7489290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
7499290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar                continue;
7509290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar            }
7519290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar            final String tagName = parser.getName();
7529290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar            if (tagName.equals("keyset")) {
7539290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar                String encodedID = parser.getAttributeValue(null, "identifier");
7549290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar                currentKeySetId = Long.parseLong(encodedID);
7559290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar                int refCount = 0;
7569290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar                mKeySets.put(currentKeySetId, new KeySetHandle(currentKeySetId, refCount));
7579290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar                mKeySetMapping.put(currentKeySetId, new ArraySet<Long>());
7589290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar            } else if (tagName.equals("key-id")) {
7599290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar                String encodedID = parser.getAttributeValue(null, "identifier");
7609290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar                long id = Long.parseLong(encodedID);
7619290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar                mKeySetMapping.get(currentKeySetId).add(id);
7629290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar            }
7639290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar        }
764d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    }
765d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase
766d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase    void readPublicKeyLPw(XmlPullParser parser)
76711b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar            throws XmlPullParserException {
76811b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar        String encodedID = parser.getAttributeValue(null, "identifier");
769d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        long identifier = Long.parseLong(encodedID);
7702d2e8d88103866b631eb0f3805da137ebcfb0275Yigit Boyar        int refCount = 0;
771d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase        String encodedPublicKey = parser.getAttributeValue(null, "value");
7729eeb624e8d3a9e7dc4e70eec759ab60104aab459Dake Gu        PublicKey pub = PackageParser.parsePublicKey(encodedPublicKey);
7739051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar        if (pub != null) {
77465dea0f8960efe2487c05abeeccb92689bab1332Keyvan Amiri            PublicKeyHandle pkh = new PublicKeyHandle(identifier, refCount, pub);
775d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase            mPublicKeys.put(identifier, pkh);
7762d2e8d88103866b631eb0f3805da137ebcfb0275Yigit Boyar        }
7772d2e8d88103866b631eb0f3805da137ebcfb0275Yigit Boyar    }
7782d2e8d88103866b631eb0f3805da137ebcfb0275Yigit Boyar
77965dea0f8960efe2487c05abeeccb92689bab1332Keyvan Amiri    /*
78065dea0f8960efe2487c05abeeccb92689bab1332Keyvan Amiri     * Set each KeySet ref count.  Also increment all public keys in each keyset.
78165dea0f8960efe2487c05abeeccb92689bab1332Keyvan Amiri     */
78265dea0f8960efe2487c05abeeccb92689bab1332Keyvan Amiri    private void addRefCountsFromSavedPackagesLPw(ArrayMap<Long, Integer> keySetRefCounts) {
78365dea0f8960efe2487c05abeeccb92689bab1332Keyvan Amiri        final int numRefCounts = keySetRefCounts.size();
78465dea0f8960efe2487c05abeeccb92689bab1332Keyvan Amiri        for (int i = 0; i < numRefCounts; i++) {
78565dea0f8960efe2487c05abeeccb92689bab1332Keyvan Amiri            KeySetHandle ks = mKeySets.get(keySetRefCounts.keyAt(i));
78665dea0f8960efe2487c05abeeccb92689bab1332Keyvan Amiri            if (ks == null) {
78765dea0f8960efe2487c05abeeccb92689bab1332Keyvan Amiri                /* something went terribly wrong and we have references to a non-existent key-set */
788d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase                Slog.wtf(TAG, "Encountered non-existent key-set reference when reading settings");
7898ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar                continue;
7908ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar            }
7918ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar            ks.setRefCountLPw(keySetRefCounts.valueAt(i));
7928ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar        }
7938ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar
7942d2e8d88103866b631eb0f3805da137ebcfb0275Yigit Boyar        /*
7952d2e8d88103866b631eb0f3805da137ebcfb0275Yigit Boyar         * In case something went terribly wrong and we have keysets with no associated packges
7968ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar         * that refer to them, record the orphaned keyset ids, and remove them using
7978ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar         * decrementKeySetLPw() after all keyset references have been set so that the associtaed
798d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase         * public keys have the appropriate references from all keysets.
799d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase         */
800046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard        ArraySet<Long> orphanedKeySets = new ArraySet<Long>();
801151e43e7057619d714bc0f91ac7e2139ee334058Keyvan Amiri        final int numKeySets = mKeySets.size();
802046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard        for (int i = 0; i < numKeySets; i++) {
803046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard            if (mKeySets.valueAt(i).getRefCountLPr() == 0) {
804046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard                Slog.wtf(TAG, "Encountered key-set w/out package references when reading settings");
805046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard                orphanedKeySets.add(mKeySets.keyAt(i));
806151e43e7057619d714bc0f91ac7e2139ee334058Keyvan Amiri            }
807151e43e7057619d714bc0f91ac7e2139ee334058Keyvan Amiri            ArraySet<Long> pubKeys = mKeySetMapping.valueAt(i);
808151e43e7057619d714bc0f91ac7e2139ee334058Keyvan Amiri            final int pkSize = pubKeys.size();
8098a11e6829c522aa1efcc903afa4c01d337082eabChris Craik            for (int j = 0; j < pkSize; j++) {
810046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard                mPublicKeys.get(pubKeys.valueAt(j)).incrRefCountLPw();
811046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard            }
812151e43e7057619d714bc0f91ac7e2139ee334058Keyvan Amiri        }
813046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard        final int numOrphans = orphanedKeySets.size();
814046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard        for (int i = 0; i < numOrphans; i++) {
815046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard            decrementKeySetLPw(orphanedKeySets.valueAt(i));
816151e43e7057619d714bc0f91ac7e2139ee334058Keyvan Amiri        }
817151e43e7057619d714bc0f91ac7e2139ee334058Keyvan Amiri    }
818151e43e7057619d714bc0f91ac7e2139ee334058Keyvan Amiri}
8198a11e6829c522aa1efcc903afa4c01d337082eabChris Craik