--- /dev/null
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.sdklib.internal.export;
+
+import com.android.sdklib.xml.ManifestData;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Class representing one apk (or more if there are soft variants) that needs to be generated.
+ * This contains a link to the project used for the export, and which extra filters should be used.
+ *
+ * This class is meant to be sortable in a way that allows generation of the buildInfo
+ * value that goes in the composite versionCode.
+ */
+public final class ApkData implements Comparable<ApkData> {
+
+ private static final String PROP_PROJECT = "project";
+ private static final String PROP_BUILDINFO = "buildInfo";
+ private static final String PROP_MINOR = "minorCode";
+ private static final String PROP_ABI = "abi";
+ private static final String PROP_RESOURCES = "resources";
+
+ /**
+ * List of ABI order.
+ * This is meant to be a list of CPU/CPU2 to indicate the order required by the build info.
+ * If the ABIs being compared in {@link #compareTo(ApkData)} are in the same String array,
+ * then the value returned must ensure that the {@link ApkData} will ordered the same as the
+ * array.
+ * If the ABIs are not in the same array, any order can be returned.
+ */
+ private static final String[][] ABI_SORTING = new String[][] {
+ new String[] { "armeabi", "armeabi-v7a" }
+ };
+
+ private final ProjectConfig mProjectConfig;
+ private final HashMap<String, String> mOutputNames = new HashMap<String, String>();
+ private int mBuildInfo;
+ private int mMinorCode;
+
+ // the following are used to sort the export data and generate buildInfo
+ private final String mAbi;
+ private final Map<String, String> mSoftVariantMap = new HashMap<String, String>();
+
+ ApkData(ProjectConfig projectConfig, String abi, Map<String, String> softVariants) {
+ mProjectConfig = projectConfig;
+ mAbi = abi;
+ if (softVariants != null) {
+ mSoftVariantMap.putAll(softVariants);
+ }
+ }
+
+ ApkData(ProjectConfig projectConfig, String abi) {
+ this(projectConfig, abi, null /*softVariants*/);
+ }
+
+ ApkData(ProjectConfig projectConfig, Map<String, String> softVariants) {
+ this(projectConfig, null /*abi*/, softVariants);
+ }
+
+ ApkData(ProjectConfig projectConfig) {
+ this(projectConfig, null /*abi*/, null /*softVariants*/);
+ }
+
+ public ProjectConfig getProjectConfig() {
+ return mProjectConfig;
+ }
+
+ public String getOutputName(String key) {
+ return mOutputNames.get(key);
+ }
+
+ public void setOutputName(String key, String outputName) {
+ mOutputNames.put(key, outputName);
+ }
+
+ public int getBuildInfo() {
+ return mBuildInfo;
+ }
+
+ void setBuildInfo(int buildInfo) {
+ mBuildInfo = buildInfo;
+ }
+
+ public int getMinorCode() {
+ return mMinorCode;
+ }
+
+ void setMinorCode(int minor) {
+ mMinorCode = minor;
+ }
+
+ public String getAbi() {
+ return mAbi;
+ }
+
+ public Map<String, String> getSoftVariantMap() {
+ return mSoftVariantMap;
+ }
+
+ /**
+ * Computes and returns the composite version code
+ * @param versionCode the major version code.
+ * @return the composite versionCode to be used in the manifest.
+ */
+ public int getCompositeVersionCode(int versionCode) {
+ int trueVersionCode = versionCode * MultiApkExportHelper.OFFSET_VERSION_CODE;
+ trueVersionCode += getBuildInfo() * MultiApkExportHelper.OFFSET_BUILD_INFO;
+ trueVersionCode += getMinorCode();
+
+ return trueVersionCode;
+ }
+
+ @Override
+ public String toString() {
+ return getLogLine(null);
+ }
+
+ public String getLogLine(String key) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(getOutputName(key)).append(':');
+
+ LogHelper.write(sb, PROP_BUILDINFO, mBuildInfo);
+ LogHelper.write(sb, PROP_MINOR, mMinorCode);
+ LogHelper.write(sb, PROP_PROJECT, mProjectConfig.getRelativePath());
+ sb.append(mProjectConfig.getConfigString(true /*onlyManifestData*/));
+
+ if (mAbi != null) {
+ LogHelper.write(sb, PROP_ABI, mAbi);
+ }
+
+ String filter = mSoftVariantMap.get(key);
+ if (filter != null) {
+ LogHelper.write(sb, PROP_RESOURCES, filter);
+ }
+
+ return sb.toString();
+ }
+
+ public int compareTo(ApkData o) {
+ // compare only the hard properties, and in a specific order:
+
+ // 1. minSdkVersion
+ int minSdkDiff = mProjectConfig.getMinSdkVersion() - o.mProjectConfig.getMinSdkVersion();
+ if (minSdkDiff != 0) {
+ return minSdkDiff;
+ }
+
+ // 2. <supports-screens>
+ // only compare if they have don't have the same size support. This is because
+ // this compare method throws an exception if the values cannot be compared.
+ if (mProjectConfig.getSupportsScreens().hasSameScreenSupportAs(
+ o.mProjectConfig.getSupportsScreens()) == false) {
+ return mProjectConfig.getSupportsScreens().compareScreenSizesWith(
+ o.mProjectConfig.getSupportsScreens());
+ }
+
+ // 3. glEsVersion
+ int comp;
+ if (mProjectConfig.getGlEsVersion() != ManifestData.GL_ES_VERSION_NOT_SET) {
+ if (o.mProjectConfig.getGlEsVersion() != ManifestData.GL_ES_VERSION_NOT_SET) {
+ comp = mProjectConfig.getGlEsVersion() - o.mProjectConfig.getGlEsVersion();
+ if (comp != 0) return comp;
+ } else {
+ return -1;
+ }
+ } else if (o.mProjectConfig.getGlEsVersion() != ManifestData.GL_ES_VERSION_NOT_SET) {
+ return 1;
+ }
+
+ // 4. ABI
+ // here the returned value is only important if both abi are non null.
+ if (mAbi != null && o.mAbi != null) {
+ comp = compareAbi(mAbi, o.mAbi);
+ if (comp != 0) return comp;
+ }
+
+ return 0;
+ }
+
+ private int compareAbi(String abi, String abi2) {
+ // look for the abis in each of the ABI sorting array
+ for (String[] abiArray : ABI_SORTING) {
+ int abiIndex = -1, abiIndex2 = -1;
+ final int count = abiArray.length;
+ for (int i = 0 ; i < count ; i++) {
+ if (abiArray[i].equals(abi)) {
+ abiIndex = i;
+ }
+ if (abiArray[i].equals(abi2)) {
+ abiIndex2 = i;
+ }
+ }
+
+ // if both were found
+ if (abiIndex != -1 && abiIndex != -1) {
+ return abiIndex - abiIndex2;
+ }
+ }
+
+ return 0;
+ }
+}