17767eac3232ba2fb9828766813cdb481d6a97584Dianne Hackborn/*
27767eac3232ba2fb9828766813cdb481d6a97584Dianne Hackborn * Copyright (C) 2012 The Android Open Source Project
37767eac3232ba2fb9828766813cdb481d6a97584Dianne Hackborn *
47767eac3232ba2fb9828766813cdb481d6a97584Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
57767eac3232ba2fb9828766813cdb481d6a97584Dianne Hackborn * you may not use this file except in compliance with the License.
67767eac3232ba2fb9828766813cdb481d6a97584Dianne Hackborn * You may obtain a copy of the License at
77767eac3232ba2fb9828766813cdb481d6a97584Dianne Hackborn *
87767eac3232ba2fb9828766813cdb481d6a97584Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
97767eac3232ba2fb9828766813cdb481d6a97584Dianne Hackborn *
107767eac3232ba2fb9828766813cdb481d6a97584Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
117767eac3232ba2fb9828766813cdb481d6a97584Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
127767eac3232ba2fb9828766813cdb481d6a97584Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137767eac3232ba2fb9828766813cdb481d6a97584Dianne Hackborn * See the License for the specific language governing permissions and
147767eac3232ba2fb9828766813cdb481d6a97584Dianne Hackborn * limitations under the License.
157767eac3232ba2fb9828766813cdb481d6a97584Dianne Hackborn */
167767eac3232ba2fb9828766813cdb481d6a97584Dianne Hackborn
17bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Rootpackage android.content.pm;
18bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
19bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Rootimport android.os.Parcel;
20bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Rootimport android.os.Parcelable;
21bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Rootimport android.util.Base64;
22bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
23bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Rootimport java.util.Arrays;
24bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Rootimport java.util.jar.Attributes;
25bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
26bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root/**
27bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root * Represents the manifest digest for a package. This is suitable for comparison
28bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root * of two packages to know whether the manifests are identical.
29bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root *
30bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root * @hide
31bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root */
32bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Rootpublic class ManifestDigest implements Parcelable {
33bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    /** The digest of the manifest in our preferred order. */
34bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    private final byte[] mDigest;
35bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
36bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    /** Digest field names to look for in preferred order. */
37bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    private static final String[] DIGEST_TYPES = {
38bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root            "SHA1-Digest", "SHA-Digest", "MD5-Digest",
39bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    };
40bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
41bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    /** What we print out first when toString() is called. */
42bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    private static final String TO_STRING_PREFIX = "ManifestDigest {mDigest=";
43bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
44bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    ManifestDigest(byte[] digest) {
45bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        mDigest = digest;
46bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    }
47bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
48bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    private ManifestDigest(Parcel source) {
49bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        mDigest = source.createByteArray();
50bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    }
51bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
52bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    static ManifestDigest fromAttributes(Attributes attributes) {
53bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        if (attributes == null) {
54bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root            return null;
55bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        }
56bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
57bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        String encodedDigest = null;
58bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
59bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        for (int i = 0; i < DIGEST_TYPES.length; i++) {
60bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root            final String value = attributes.getValue(DIGEST_TYPES[i]);
61bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root            if (value != null) {
62bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root                encodedDigest = value;
63bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root                break;
64bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root            }
65bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        }
66bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
67bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        if (encodedDigest == null) {
68bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root            return null;
69bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        }
70bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
71bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        final byte[] digest = Base64.decode(encodedDigest, Base64.DEFAULT);
72bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        return new ManifestDigest(digest);
73bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    }
74bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
75bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    @Override
76bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    public int describeContents() {
77bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        return 0;
78bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    }
79bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
80bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    @Override
81bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    public boolean equals(Object o) {
82bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        if (!(o instanceof ManifestDigest)) {
83bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root            return false;
84bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        }
85bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
86bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        final ManifestDigest other = (ManifestDigest) o;
87bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
88bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        return this == other || Arrays.equals(mDigest, other.mDigest);
89bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    }
90bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
91bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    @Override
92bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    public int hashCode() {
93bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        return Arrays.hashCode(mDigest);
94bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    }
95bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
96bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    @Override
97bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    public String toString() {
98bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        final StringBuilder sb = new StringBuilder(TO_STRING_PREFIX.length()
99bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root                + (mDigest.length * 3) + 1);
100bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
101bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        sb.append(TO_STRING_PREFIX);
102bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
103bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        final int N = mDigest.length;
104bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        for (int i = 0; i < N; i++) {
105bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root            final byte b = mDigest[i];
106bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root            IntegralToString.appendByteAsHex(sb, b, false);
107bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root            sb.append(',');
108bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        }
109bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        sb.append('}');
110bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
111bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        return sb.toString();
112bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    }
113bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
114bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    @Override
115bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    public void writeToParcel(Parcel dest, int flags) {
116bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        dest.writeByteArray(mDigest);
117bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    }
118bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
119bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    public static final Parcelable.Creator<ManifestDigest> CREATOR
120bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root            = new Parcelable.Creator<ManifestDigest>() {
121bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        public ManifestDigest createFromParcel(Parcel source) {
122bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root            return new ManifestDigest(source);
123bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        }
124bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
125bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        public ManifestDigest[] newArray(int size) {
126bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root            return new ManifestDigest[size];
127bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root        }
128bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root    };
129bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root
130bcc954d772e8cd5ef640060cbc0be50e7e4778f2Kenny Root}