1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.content.pm; 18 19import android.content.ComponentName; 20import android.os.Parcel; 21import android.os.Parcelable; 22 23import java.lang.ref.SoftReference; 24import java.util.Arrays; 25 26/** 27 * Opaque, immutable representation of a signature associated with an 28 * application package. 29 */ 30public class Signature implements Parcelable { 31 private final byte[] mSignature; 32 private int mHashCode; 33 private boolean mHaveHashCode; 34 private SoftReference<String> mStringRef; 35 36 /** 37 * Create Signature from an existing raw byte array. 38 */ 39 public Signature(byte[] signature) { 40 mSignature = signature.clone(); 41 } 42 43 /** 44 * Create Signature from a text representation previously returned by 45 * {@link #toChars} or {@link #toCharsString()}. 46 */ 47 public Signature(String text) { 48 final int N = text.length()/2; 49 byte[] sig = new byte[N]; 50 for (int i=0; i<N; i++) { 51 char c = text.charAt(i*2); 52 byte b = (byte)( 53 (c >= 'a' ? (c - 'a' + 10) : (c - '0'))<<4); 54 c = text.charAt(i*2 + 1); 55 b |= (byte)(c >= 'a' ? (c - 'a' + 10) : (c - '0')); 56 sig[i] = b; 57 } 58 mSignature = sig; 59 } 60 61 /** 62 * Encode the Signature as ASCII text. 63 */ 64 public char[] toChars() { 65 return toChars(null, null); 66 } 67 68 /** 69 * Encode the Signature as ASCII text in to an existing array. 70 * 71 * @param existingArray Existing char array or null. 72 * @param outLen Output parameter for the number of characters written in 73 * to the array. 74 * @return Returns either <var>existingArray</var> if it was large enough 75 * to hold the ASCII representation, or a newly created char[] array if 76 * needed. 77 */ 78 public char[] toChars(char[] existingArray, int[] outLen) { 79 byte[] sig = mSignature; 80 final int N = sig.length; 81 final int N2 = N*2; 82 char[] text = existingArray == null || N2 > existingArray.length 83 ? new char[N2] : existingArray; 84 for (int j=0; j<N; j++) { 85 byte v = sig[j]; 86 int d = (v>>4)&0xf; 87 text[j*2] = (char)(d >= 10 ? ('a' + d - 10) : ('0' + d)); 88 d = v&0xf; 89 text[j*2+1] = (char)(d >= 10 ? ('a' + d - 10) : ('0' + d)); 90 } 91 if (outLen != null) outLen[0] = N; 92 return text; 93 } 94 95 /** 96 * Return the result of {@link #toChars()} as a String. This result is 97 * cached so future calls will return the same String. 98 */ 99 public String toCharsString() { 100 String str = mStringRef == null ? null : mStringRef.get(); 101 if (str != null) { 102 return str; 103 } 104 str = new String(toChars()); 105 mStringRef = new SoftReference<String>(str); 106 return str; 107 } 108 109 /** 110 * @return the contents of this signature as a byte array. 111 */ 112 public byte[] toByteArray() { 113 byte[] bytes = new byte[mSignature.length]; 114 System.arraycopy(mSignature, 0, bytes, 0, mSignature.length); 115 return bytes; 116 } 117 118 @Override 119 public boolean equals(Object obj) { 120 try { 121 if (obj != null) { 122 Signature other = (Signature)obj; 123 return Arrays.equals(mSignature, other.mSignature); 124 } 125 } catch (ClassCastException e) { 126 } 127 return false; 128 } 129 130 @Override 131 public int hashCode() { 132 if (mHaveHashCode) { 133 return mHashCode; 134 } 135 mHashCode = Arrays.hashCode(mSignature); 136 mHaveHashCode = true; 137 return mHashCode; 138 } 139 140 public int describeContents() { 141 return 0; 142 } 143 144 public void writeToParcel(Parcel dest, int parcelableFlags) { 145 dest.writeByteArray(mSignature); 146 } 147 148 public static final Parcelable.Creator<Signature> CREATOR 149 = new Parcelable.Creator<Signature>() { 150 public Signature createFromParcel(Parcel source) { 151 return new Signature(source); 152 } 153 154 public Signature[] newArray(int size) { 155 return new Signature[size]; 156 } 157 }; 158 159 private Signature(Parcel source) { 160 mSignature = source.createByteArray(); 161 } 162} 163