1 /* 2 * Copyright (C) 2010 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.sdklib.internal.export; 18 19 import com.android.sdklib.xml.ManifestData; 20 21 import java.util.HashMap; 22 import java.util.Map; 23 24 /** 25 * Class representing one apk (or more if there are soft variants) that needs to be generated. 26 * This contains a link to the project used for the export, and which extra filters should be used. 27 * 28 * This class is meant to be sortable in a way that allows generation of the buildInfo 29 * value that goes in the composite versionCode. 30 */ 31 public final class ApkData implements Comparable<ApkData> { 32 33 private static final String PROP_PROJECT = "project"; 34 private static final String PROP_BUILDINFO = "buildInfo"; 35 private static final String PROP_MINOR = "minorCode"; 36 private static final String PROP_ABI = "abi"; 37 private static final String PROP_RESOURCES = "resources"; 38 39 /** 40 * List of ABI order. 41 * This is meant to be a list of CPU/CPU2 to indicate the order required by the build info. 42 * If the ABIs being compared in {@link #compareTo(ApkData)} are in the same String array, 43 * then the value returned must ensure that the {@link ApkData} will ordered the same as the 44 * array. 45 * If the ABIs are not in the same array, any order can be returned. 46 */ 47 private static final String[][] ABI_SORTING = new String[][] { 48 new String[] { "armeabi", "armeabi-v7a" } 49 }; 50 51 private final ProjectConfig mProjectConfig; 52 private final HashMap<String, String> mOutputNames = new HashMap<String, String>(); 53 private int mBuildInfo; 54 private int mMinorCode; 55 56 // the following are used to sort the export data and generate buildInfo 57 private final String mAbi; 58 private final Map<String, String> mSoftVariantMap = new HashMap<String, String>(); 59 60 ApkData(ProjectConfig projectConfig, String abi, Map<String, String> softVariants) { 61 mProjectConfig = projectConfig; 62 mAbi = abi; 63 if (softVariants != null) { 64 mSoftVariantMap.putAll(softVariants); 65 } 66 } 67 68 ApkData(ProjectConfig projectConfig, String abi) { 69 this(projectConfig, abi, null /*softVariants*/); 70 } 71 72 ApkData(ProjectConfig projectConfig, Map<String, String> softVariants) { 73 this(projectConfig, null /*abi*/, softVariants); 74 } 75 76 ApkData(ProjectConfig projectConfig) { 77 this(projectConfig, null /*abi*/, null /*softVariants*/); 78 } 79 80 public ProjectConfig getProjectConfig() { 81 return mProjectConfig; 82 } 83 84 public String getOutputName(String key) { 85 return mOutputNames.get(key); 86 } 87 88 public void setOutputName(String key, String outputName) { 89 mOutputNames.put(key, outputName); 90 } 91 92 public int getBuildInfo() { 93 return mBuildInfo; 94 } 95 96 void setBuildInfo(int buildInfo) { 97 mBuildInfo = buildInfo; 98 } 99 100 public int getMinorCode() { 101 return mMinorCode; 102 } 103 104 void setMinorCode(int minor) { 105 mMinorCode = minor; 106 } 107 108 public String getAbi() { 109 return mAbi; 110 } 111 112 public Map<String, String> getSoftVariantMap() { 113 return mSoftVariantMap; 114 } 115 116 /** 117 * Computes and returns the composite version code 118 * @param versionCode the major version code. 119 * @return the composite versionCode to be used in the manifest. 120 */ 121 public int getCompositeVersionCode(int versionCode) { 122 int trueVersionCode = versionCode * MultiApkExportHelper.OFFSET_VERSION_CODE; 123 trueVersionCode += getBuildInfo() * MultiApkExportHelper.OFFSET_BUILD_INFO; 124 trueVersionCode += getMinorCode(); 125 126 return trueVersionCode; 127 } 128 129 @Override 130 public String toString() { 131 return getLogLine(null); 132 } 133 134 public String getLogLine(String key) { 135 StringBuilder sb = new StringBuilder(); 136 sb.append(getOutputName(key)).append(':'); 137 138 LogHelper.write(sb, PROP_BUILDINFO, mBuildInfo); 139 LogHelper.write(sb, PROP_MINOR, mMinorCode); 140 LogHelper.write(sb, PROP_PROJECT, mProjectConfig.getRelativePath()); 141 sb.append(mProjectConfig.getConfigString(true /*onlyManifestData*/)); 142 143 if (mAbi != null) { 144 LogHelper.write(sb, PROP_ABI, mAbi); 145 } 146 147 String filter = mSoftVariantMap.get(key); 148 if (filter != null) { 149 LogHelper.write(sb, PROP_RESOURCES, filter); 150 } 151 152 return sb.toString(); 153 } 154 155 public int compareTo(ApkData o) { 156 // compare only the hard properties, and in a specific order: 157 158 // 1. minSdkVersion 159 int minSdkDiff = mProjectConfig.getMinSdkVersion() - o.mProjectConfig.getMinSdkVersion(); 160 if (minSdkDiff != 0) { 161 return minSdkDiff; 162 } 163 164 // 2. <supports-screens> 165 // only compare if they have don't have the same size support. This is because 166 // this compare method throws an exception if the values cannot be compared. 167 if (mProjectConfig.getSupportsScreens().hasSameScreenSupportAs( 168 o.mProjectConfig.getSupportsScreens()) == false) { 169 return mProjectConfig.getSupportsScreens().compareScreenSizesWith( 170 o.mProjectConfig.getSupportsScreens()); 171 } 172 173 // 3. glEsVersion 174 int comp; 175 if (mProjectConfig.getGlEsVersion() != ManifestData.GL_ES_VERSION_NOT_SET) { 176 if (o.mProjectConfig.getGlEsVersion() != ManifestData.GL_ES_VERSION_NOT_SET) { 177 comp = mProjectConfig.getGlEsVersion() - o.mProjectConfig.getGlEsVersion(); 178 if (comp != 0) return comp; 179 } else { 180 return -1; 181 } 182 } else if (o.mProjectConfig.getGlEsVersion() != ManifestData.GL_ES_VERSION_NOT_SET) { 183 return 1; 184 } 185 186 // 4. ABI 187 // here the returned value is only important if both abi are non null. 188 if (mAbi != null && o.mAbi != null) { 189 comp = compareAbi(mAbi, o.mAbi); 190 if (comp != 0) return comp; 191 } 192 193 return 0; 194 } 195 196 private int compareAbi(String abi, String abi2) { 197 // look for the abis in each of the ABI sorting array 198 for (String[] abiArray : ABI_SORTING) { 199 int abiIndex = -1, abiIndex2 = -1; 200 final int count = abiArray.length; 201 for (int i = 0 ; i < count ; i++) { 202 if (abiArray[i].equals(abi)) { 203 abiIndex = i; 204 } 205 if (abiArray[i].equals(abi2)) { 206 abiIndex2 = i; 207 } 208 } 209 210 // if both were found 211 if (abiIndex != -1 && abiIndex != -1) { 212 return abiIndex - abiIndex2; 213 } 214 } 215 216 return 0; 217 } 218 } 219