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}