Home | History | Annotate | Download | only in pm
      1 /*
      2  * Copyright (C) 2011 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 
     17 package com.android.server.pm;
     18 
     19 import com.android.internal.util.XmlUtils;
     20 
     21 import org.xmlpull.v1.XmlPullParser;
     22 import org.xmlpull.v1.XmlPullParserException;
     23 import org.xmlpull.v1.XmlSerializer;
     24 
     25 import android.content.pm.Signature;
     26 import android.util.Log;
     27 
     28 import java.io.IOException;
     29 import java.util.ArrayList;
     30 
     31 class PackageSignatures {
     32     Signature[] mSignatures;
     33 
     34     PackageSignatures(PackageSignatures orig) {
     35         if (orig != null && orig.mSignatures != null) {
     36             mSignatures = orig.mSignatures.clone();
     37         }
     38     }
     39 
     40     PackageSignatures(Signature[] sigs) {
     41         assignSignatures(sigs);
     42     }
     43 
     44     PackageSignatures() {
     45     }
     46 
     47     void writeXml(XmlSerializer serializer, String tagName,
     48             ArrayList<Signature> pastSignatures) throws IOException {
     49         if (mSignatures == null) {
     50             return;
     51         }
     52         serializer.startTag(null, tagName);
     53         serializer.attribute(null, "count",
     54                 Integer.toString(mSignatures.length));
     55         for (int i=0; i<mSignatures.length; i++) {
     56             serializer.startTag(null, "cert");
     57             final Signature sig = mSignatures[i];
     58             final int sigHash = sig.hashCode();
     59             final int numPast = pastSignatures.size();
     60             int j;
     61             for (j=0; j<numPast; j++) {
     62                 Signature pastSig = pastSignatures.get(j);
     63                 if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
     64                     serializer.attribute(null, "index", Integer.toString(j));
     65                     break;
     66                 }
     67             }
     68             if (j >= numPast) {
     69                 pastSignatures.add(sig);
     70                 serializer.attribute(null, "index", Integer.toString(numPast));
     71                 serializer.attribute(null, "key", sig.toCharsString());
     72             }
     73             serializer.endTag(null, "cert");
     74         }
     75         serializer.endTag(null, tagName);
     76     }
     77 
     78     void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
     79             throws IOException, XmlPullParserException {
     80         String countStr = parser.getAttributeValue(null, "count");
     81         if (countStr == null) {
     82             PackageManagerService.reportSettingsProblem(Log.WARN,
     83                     "Error in package manager settings: <signatures> has"
     84                        + " no count at " + parser.getPositionDescription());
     85             XmlUtils.skipCurrentTag(parser);
     86         }
     87         final int count = Integer.parseInt(countStr);
     88         mSignatures = new Signature[count];
     89         int pos = 0;
     90 
     91         int outerDepth = parser.getDepth();
     92         int type;
     93         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
     94                && (type != XmlPullParser.END_TAG
     95                        || parser.getDepth() > outerDepth)) {
     96             if (type == XmlPullParser.END_TAG
     97                     || type == XmlPullParser.TEXT) {
     98                 continue;
     99             }
    100 
    101             String tagName = parser.getName();
    102             if (tagName.equals("cert")) {
    103                 if (pos < count) {
    104                     String index = parser.getAttributeValue(null, "index");
    105                     if (index != null) {
    106                         try {
    107                             int idx = Integer.parseInt(index);
    108                             String key = parser.getAttributeValue(null, "key");
    109                             if (key == null) {
    110                                 if (idx >= 0 && idx < pastSignatures.size()) {
    111                                     Signature sig = pastSignatures.get(idx);
    112                                     if (sig != null) {
    113                                         mSignatures[pos] = pastSignatures.get(idx);
    114                                         pos++;
    115                                     } else {
    116                                         PackageManagerService.reportSettingsProblem(Log.WARN,
    117                                                 "Error in package manager settings: <cert> "
    118                                                    + "index " + index + " is not defined at "
    119                                                    + parser.getPositionDescription());
    120                                     }
    121                                 } else {
    122                                     PackageManagerService.reportSettingsProblem(Log.WARN,
    123                                             "Error in package manager settings: <cert> "
    124                                                + "index " + index + " is out of bounds at "
    125                                                + parser.getPositionDescription());
    126                                 }
    127                             } else {
    128                                 while (pastSignatures.size() <= idx) {
    129                                     pastSignatures.add(null);
    130                                 }
    131                                 Signature sig = new Signature(key);
    132                                 pastSignatures.set(idx, sig);
    133                                 mSignatures[pos] = sig;
    134                                 pos++;
    135                             }
    136                         } catch (NumberFormatException e) {
    137                             PackageManagerService.reportSettingsProblem(Log.WARN,
    138                                     "Error in package manager settings: <cert> "
    139                                        + "index " + index + " is not a number at "
    140                                        + parser.getPositionDescription());
    141                         } catch (IllegalArgumentException e) {
    142                             PackageManagerService.reportSettingsProblem(Log.WARN,
    143                                     "Error in package manager settings: <cert> "
    144                                        + "index " + index + " has an invalid signature at "
    145                                        + parser.getPositionDescription() + ": "
    146                                        + e.getMessage());
    147                         }
    148                     } else {
    149                         PackageManagerService.reportSettingsProblem(Log.WARN,
    150                                 "Error in package manager settings: <cert> has"
    151                                    + " no index at " + parser.getPositionDescription());
    152                     }
    153                 } else {
    154                     PackageManagerService.reportSettingsProblem(Log.WARN,
    155                             "Error in package manager settings: too "
    156                                + "many <cert> tags, expected " + count
    157                                + " at " + parser.getPositionDescription());
    158                 }
    159             } else {
    160                 PackageManagerService.reportSettingsProblem(Log.WARN,
    161                         "Unknown element under <cert>: "
    162                         + parser.getName());
    163             }
    164             XmlUtils.skipCurrentTag(parser);
    165         }
    166 
    167         if (pos < count) {
    168             // Should never happen -- there is an error in the written
    169             // settings -- but if it does we don't want to generate
    170             // a bad array.
    171             Signature[] newSigs = new Signature[pos];
    172             System.arraycopy(mSignatures, 0, newSigs, 0, pos);
    173             mSignatures = newSigs;
    174         }
    175     }
    176 
    177     void assignSignatures(Signature[] sigs) {
    178         if (sigs == null) {
    179             mSignatures = null;
    180             return;
    181         }
    182         mSignatures = new Signature[sigs.length];
    183         for (int i=0; i<sigs.length; i++) {
    184             mSignatures[i] = sigs[i];
    185         }
    186     }
    187 
    188     @Override
    189     public String toString() {
    190         StringBuffer buf = new StringBuffer(128);
    191         buf.append("PackageSignatures{");
    192         buf.append(Integer.toHexString(System.identityHashCode(this)));
    193         buf.append(" [");
    194         if (mSignatures != null) {
    195             for (int i=0; i<mSignatures.length; i++) {
    196                 if (i > 0) buf.append(", ");
    197                 buf.append(Integer.toHexString(
    198                         System.identityHashCode(mSignatures[i])));
    199             }
    200         }
    201         buf.append("]}");
    202         return buf.toString();
    203     }
    204 }