com.android.sdklib.repository.descriptors.PkgDesc Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sdklib Show documentation
Show all versions of sdklib Show documentation
A library to parse and download the Android SDK.
/*
* Copyright (C) 2013 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.repository.descriptors;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.annotations.VisibleForTesting;
import com.android.annotations.VisibleForTesting.Visibility;
import com.android.sdklib.AndroidTargetHash;
import com.android.sdklib.AndroidVersion;
import com.android.sdklib.SystemImage;
import com.android.sdklib.internal.repository.packages.License;
import com.android.sdklib.internal.repository.packages.Package;
import com.android.sdklib.io.FileOp;
import com.android.sdklib.repository.FullRevision;
import com.android.sdklib.repository.FullRevision.PreviewComparison;
import com.android.sdklib.repository.MajorRevision;
import com.android.sdklib.repository.NoPreviewRevision;
import java.io.File;
import java.util.Locale;
/**
* {@link PkgDesc} keeps information on individual SDK packages
* (both local or remote packages definitions.)
*
* Packages have different attributes depending on their type.
*
* To create a new {@link PkgDesc}, use one of the package-specific constructors
* provided here.
*
* To query packages capabilities, rely on {@link #getType()} and the {@code PkgDesc.hasXxx()}
* methods provided in the base {@link PkgDesc}.
*/
public class PkgDesc implements IPkgDesc {
private final PkgType mType;
private final FullRevision mFullRevision;
private final MajorRevision mMajorRevision;
private final AndroidVersion mAndroidVersion;
private final String mPath;
private final IdDisplay mTag;
private final IdDisplay mVendor;
private final FullRevision mMinToolsRev;
private final FullRevision mMinPlatformToolsRev;
private final IIsUpdateFor mCustomIsUpdateFor;
private final IGetPath mCustomPath;
private final License mLicense;
private final String mListDisplay;
private final String mDescriptionShort;
private final String mDescriptionUrl;
private final boolean mIsObsolete;
protected PkgDesc(@NonNull PkgType type,
@Nullable License license,
@Nullable String listDisplay,
@Nullable String descriptionShort,
@Nullable String descriptionUrl,
boolean isObsolete,
@Nullable FullRevision fullRevision,
@Nullable MajorRevision majorRevision,
@Nullable AndroidVersion androidVersion,
@Nullable String path,
@Nullable IdDisplay tag,
@Nullable IdDisplay vendor,
@Nullable FullRevision minToolsRev,
@Nullable FullRevision minPlatformToolsRev,
@Nullable IIsUpdateFor customIsUpdateFor,
@Nullable IGetPath customPath) {
mType = type;
mIsObsolete = isObsolete;
mLicense = license;
mListDisplay = listDisplay;
mDescriptionShort = descriptionShort;
mDescriptionUrl = descriptionUrl;
mFullRevision = fullRevision;
mMajorRevision = majorRevision;
mAndroidVersion = androidVersion;
mPath = path;
mTag = tag;
mVendor = vendor;
mMinToolsRev = minToolsRev;
mMinPlatformToolsRev = minPlatformToolsRev;
mCustomIsUpdateFor = customIsUpdateFor;
mCustomPath = customPath;
}
@NonNull
@Override
public PkgType getType() {
return mType;
}
@Override
@Nullable
public String getListDisplay() {
return mListDisplay;
}
@Override
@Nullable
public String getDescriptionShort() {
return mDescriptionShort;
}
@Override
@Nullable
public String getDescriptionUrl() {
return mDescriptionUrl;
}
@Override
@Nullable
public License getLicense() {
return mLicense;
}
@Override
public boolean isObsolete() {
return mIsObsolete;
}
@Override
public final boolean hasFullRevision() {
return getType().hasFullRevision();
}
@Override
public final boolean hasMajorRevision() {
return getType().hasMajorRevision();
}
@Override
public final boolean hasAndroidVersion() {
return getType().hasAndroidVersion();
}
@Override
public final boolean hasPath() {
return getType().hasPath();
}
@Override
public final boolean hasTag() {
return getType().hasTag();
}
@Override
public boolean hasVendor() {
return getType().hasVendor();
}
@Override
public final boolean hasMinToolsRev() {
return getType().hasMinToolsRev();
}
@Override
public final boolean hasMinPlatformToolsRev() {
return getType().hasMinPlatformToolsRev();
}
@Nullable
@Override
public FullRevision getFullRevision() {
return mFullRevision;
}
@Nullable
@Override
public MajorRevision getMajorRevision() {
return mMajorRevision;
}
@Nullable
@Override
public AndroidVersion getAndroidVersion() {
return mAndroidVersion;
}
@Nullable
@Override
public String getPath() {
if (mCustomPath != null) {
return mCustomPath.getPath(this);
} else {
return mPath;
}
}
@Nullable
@Override
public IdDisplay getTag() {
return mTag;
}
@Nullable
@Override
public IdDisplay getVendor() {
return mVendor;
}
@Nullable
@Override
public FullRevision getMinToolsRev() {
return mMinToolsRev;
}
@Nullable
@Override
public FullRevision getMinPlatformToolsRev() {
return mMinPlatformToolsRev;
}
@Override
public String getInstallId() {
StringBuilder sb = new StringBuilder();
/* iid patterns:
tools, platform-tools => FOLDER / FOLDER-preview
build-tools => FOLDER-REV
doc, sample, source => ENUM-API
extra => ENUM-VENDOR.id-PATH
platform => android-API
add-on => addon-NAME.id-VENDOR.id-API
platform sys-img => sys-img-ABI-TAG|android-API
add-on sys-img => sys-img-ABI-addon-NAME.id-VENDOR.id-API
*/
switch (mType) {
case PKG_TOOLS:
case PKG_PLATFORM_TOOLS:
sb.append(mType.getFolderName());
if (getFullRevision().isPreview()) {
sb.append("-preview");
}
break;
case PKG_BUILD_TOOLS:
sb.append(mType.getFolderName());
sb.append('-').append(getFullRevision().toString());
break;
case PKG_DOC:
case PKG_SAMPLE:
case PKG_SOURCE:
sb.append(mType.toString().toLowerCase(Locale.US).replace("pkg_", ""));
sb.append('-').append(getAndroidVersion().getApiString());
break;
case PKG_EXTRA:
sb.append("extra-")
.append(getVendor().getId())
.append('-')
.append(getPath());
break;
case PKG_PLATFORM:
sb.append(AndroidTargetHash.PLATFORM_HASH_PREFIX).append(getAndroidVersion().getApiString());
break;
case PKG_ADDON:
sb.append("addon-")
.append(((IPkgDescAddon) this).getName().getId())
.append('-')
.append(getVendor().getId())
.append('-')
.append(getAndroidVersion().getApiString());
break;
case PKG_SYS_IMAGE:
sb.append("sys-img-")
.append(getPath()) // path==ABI for sys-img
.append('-')
.append(SystemImage.DEFAULT_TAG.equals(getTag()) ? "android" : getTag().getId())
.append('-')
.append(getAndroidVersion().getApiString());
break;
case PKG_ADDON_SYS_IMAGE:
sb.append("sys-img-")
.append(getPath()) // path==ABI for sys-img
.append("-addon-")
.append(SystemImage.DEFAULT_TAG.equals(getTag()) ? "android" : getTag().getId())
.append('-')
.append(getVendor().getId())
.append('-')
.append(getAndroidVersion().getApiString());
break;
default:
throw new IllegalArgumentException("IID not defined for type " + mType.toString());
}
return sanitize(sb.toString());
}
@Override
public File getCanonicalInstallFolder(@NonNull File sdkLocation) {
File f = FileOp.append(sdkLocation, mType.getFolderName());
/* folder patterns:
tools, platform-tools, doc => FOLDER
build-tools, add-on => FOLDER/IID
platform, sample, source => FOLDER/android-API
platform sys-img => FOLDER/android-API/TAG/ABI
add-on sys-img => FOLDER/addon-NAME.id-VENDOR.id-API/ABI
extra => FOLDER/VENDOR.id/PATH
*/
switch (mType) {
case PKG_TOOLS:
case PKG_PLATFORM_TOOLS:
case PKG_DOC:
// no-op, top-folder is all what is needed here
break;
case PKG_BUILD_TOOLS:
case PKG_ADDON:
f = FileOp.append(f, getInstallId());
break;
case PKG_PLATFORM:
case PKG_SAMPLE:
case PKG_SOURCE:
f = FileOp.append(f, AndroidTargetHash.PLATFORM_HASH_PREFIX + sanitize(getAndroidVersion().getApiString()));
break;
case PKG_SYS_IMAGE:
f = FileOp.append(f,
AndroidTargetHash.PLATFORM_HASH_PREFIX + sanitize(getAndroidVersion().getApiString()),
sanitize(SystemImage.DEFAULT_TAG.equals(getTag()) ? "android" : getTag().getId()),
sanitize(getPath())); // path==abi
break;
case PKG_ADDON_SYS_IMAGE:
String name = "addon-"
+ (SystemImage.DEFAULT_TAG.equals(getTag()) ? "android" : getTag().getId())
+ '-'
+ getVendor().getId()
+ '-'
+ getAndroidVersion().getApiString();
f = FileOp.append(f,
sanitize(name),
sanitize(getPath())); // path==abi
break;
case PKG_EXTRA:
f = FileOp.append(f,
sanitize(getVendor().getId()),
sanitize(getPath()));
break;
default:
throw new IllegalArgumentException("CanonicalFolder not defined for type " + mType.toString());
}
return f;
}
//---- Updating ----
/**
* Computes the most general case of {@link #isUpdateFor(IPkgDesc)}.
* Individual package types use this and complement with their own specific cases
* as needed.
*
* @param existingDesc A non-null package descriptor to compare with.
* @return True if this package descriptor would generally update the given one.
*/
@Override
public boolean isUpdateFor(@NonNull IPkgDesc existingDesc) {
if (mCustomIsUpdateFor != null) {
return mCustomIsUpdateFor.isUpdateFor(this, existingDesc);
} else {
return isGenericUpdateFor(existingDesc);
}
}
/**
* Computes the most general case of {@link #isUpdateFor(IPkgDesc)}.
* Individual package types use this and complement with their own specific cases
* as needed.
*
* @param existingDesc A non-null package descriptor to compare with.
* @return True if this package descriptor would generally update the given one.
*/
private boolean isGenericUpdateFor(@NonNull IPkgDesc existingDesc) {
if (existingDesc == null || !getType().equals(existingDesc.getType())) {
return false;
}
// Packages that have an Android version can generally only be updated
// for the same Android version (otherwise it's a new artifact.)
if (hasAndroidVersion() && !getAndroidVersion().equals(existingDesc.getAndroidVersion())) {
return false;
}
// Packages that have a vendor id need the same vendor id on both sides
if (hasVendor() && !getVendor().equals(existingDesc.getVendor())) {
return false;
}
// Packages that have a tag id need the same tag id on both sides
if (hasTag() && !getTag().getId().equals(existingDesc.getTag().getId())) {
return false;
}
// Packages that have a path can generally only be updated if both use the same path
if (hasPath()) {
if (this instanceof IPkgDescExtra) {
// Extra package handle paths differently, they need to use the old_path
// to allow upgrade compatibility.
if (!PkgDescExtra.compatibleVendorAndPath((IPkgDescExtra) this,
(IPkgDescExtra) existingDesc)) {
return false;
}
} else if (!getPath().equals(existingDesc.getPath())) {
return false;
}
}
// Packages that have a major version are generally updates if it increases.
if (hasMajorRevision() &&
getMajorRevision().compareTo(existingDesc.getMajorRevision()) > 0) {
return true;
}
// Packages that have a full revision are generally updates if it increases
// but keeps the same kind of preview (e.g. previews are only updates by previews.)
if (hasFullRevision() &&
getFullRevision().isPreview() == existingDesc.getFullRevision().isPreview()) {
// If both packages match in their preview type (both previews or both not previews)
// then is the RC/preview number an update?
return getFullRevision().compareTo(existingDesc.getFullRevision(),
PreviewComparison.COMPARE_NUMBER) > 0;
}
return false;
}
//---- Ordering ----
/**
* Compares this descriptor to another one.
* All fields must match for equality.
*
* This is must not be used an indication that a package is a suitable update for another one.
* The comparison order is however suitable for sorting packages for display purposes.
*/
@Override
public int compareTo(@NonNull IPkgDesc o) {
int t1 = getType().getIntValue();
int t2 = o.getType().getIntValue();
if (t1 != t2) {
return t1 - t2;
}
if (hasAndroidVersion() && o.hasAndroidVersion()) {
t1 = getAndroidVersion().compareTo(o.getAndroidVersion());
if (t1 != 0) {
return t1;
}
}
if (hasVendor() && o.hasVendor()) {
t1 = getVendor().compareTo(o.getVendor());
if (t1 != 0) {
return t1;
}
}
if (hasTag() && o.hasTag()) {
t1 = getTag().compareTo(o.getTag());
if (t1 != 0) {
return t1;
}
}
if (hasPath() && o.hasPath()) {
t1 = getPath().compareTo(o.getPath());
if (t1 != 0) {
return t1;
}
}
if (hasFullRevision() && o.hasFullRevision()) {
t1 = getFullRevision().compareTo(o.getFullRevision());
if (t1 != 0) {
return t1;
}
}
if (hasMajorRevision() && o.hasMajorRevision()) {
t1 = getMajorRevision().compareTo(o.getMajorRevision());
if (t1 != 0) {
return t1;
}
}
if (hasMinToolsRev() && o.hasMinToolsRev()) {
t1 = getMinToolsRev().compareTo(o.getMinToolsRev());
if (t1 != 0) {
return t1;
}
}
if (hasMinPlatformToolsRev() && o.hasMinPlatformToolsRev()) {
t1 = getMinPlatformToolsRev().compareTo(o.getMinPlatformToolsRev());
if (t1 != 0) {
return t1;
}
}
return 0;
}
// --- display description ----
@NonNull
@Override
public String getListDescription() {
if (mListDisplay != null && !mListDisplay.isEmpty()) {
return mListDisplay;
}
return patternReplaceImpl(getType().getListDisplayPattern());
}
@VisibleForTesting(visibility=Visibility.PRIVATE)
protected String patternReplaceImpl(String result) {
// Flags for list description pattern string, used in PkgType:
// $MAJ $FULL $API $PATH $TAG $VEND $NAME (for extras)
result = result.replace("$MAJ", hasMajorRevision() ? getMajorRevision().toShortString() : "");
result = result.replace("$FULL", hasFullRevision() ? getFullRevision() .toShortString() : "");
result = result.replace("$API", hasAndroidVersion() ? getAndroidVersion().getApiString() : "");
result = result.replace("$PATH", hasPath() ? getPath() : "");
result = result.replace("$TAG", hasTag() && !getTag().equals(SystemImage.DEFAULT_TAG) ?
getTag().getDisplay() : "");
result = result.replace("$VEND", hasVendor() ? getVendor().getDisplay() : "");
String name = "";
if (this instanceof IPkgDescExtra) {
name = ((IPkgDescExtra) this).getNameDisplay();
} else if (this instanceof IPkgDescAddon) {
name = ((IPkgDescAddon) this).getName().getDisplay();
}
result = result.replace("$NAME", name);
// Evaluate replacements.
// {|choice1|choice2|...|choiceN|} gets replaced by the first non-empty choice.
for (int start = result.indexOf("{|");
start >= 0;
start = result.indexOf("{|")) {
int end = result.indexOf('}', start);
int last = start + 1;
for (int pipe = result.indexOf('|', last+1);
pipe > start;
last = pipe, pipe = result.indexOf('|', last+1)) {
if (pipe - last > 1) {
result = result.substring(0, start) +
result.substring(last+1, pipe) +
result.substring(end+1);
break;
}
}
}
// Evaluate conditions.
// {?value>1:text to use} -- uses the text if value is greater than 1.
// Simplification: this is our only test right now so hard-code it instead of
// using a generic expression evaluation.
for (int start = result.indexOf("{?");
start >= 0;
start = result.indexOf("{?")) {
int end = result.indexOf('}', start);
int op = result.indexOf(">1:");
if (op > start) {
String value = "";
try {
FullRevision i = FullRevision.parseRevision(result.substring(start+2, op));
if (i.compareTo(new FullRevision(1)) > 0) {
value = result.substring(op+3, end);
}
} catch (NumberFormatException e) {
value = "ERROR " + e.getMessage() + " in " + result.substring(start, end+1);
}
result = result.substring(0, start) +
value +
result.substring(end+1);
}
}
return result;
}
/** String representation for debugging purposes. */
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("');
return builder.toString();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (hasAndroidVersion() ? getAndroidVersion().hashCode() : 0);
result = prime * result + (hasVendor() ? getVendor() .hashCode() : 0);
result = prime * result + (hasTag() ? getTag() .hashCode() : 0);
result = prime * result + (hasPath() ? getPath() .hashCode() : 0);
result = prime * result + (hasFullRevision() ? getFullRevision() .hashCode() : 0);
result = prime * result + (hasMajorRevision() ? getMajorRevision() .hashCode() : 0);
result = prime * result + (hasMinToolsRev() ? getMinToolsRev() .hashCode() : 0);
result = prime * result + (hasMinPlatformToolsRev() ?
getMinPlatformToolsRev().hashCode() : 0);
return result;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof IPkgDesc)) return false;
IPkgDesc rhs = (IPkgDesc) obj;
if (hasAndroidVersion() != rhs.hasAndroidVersion()) {
return false;
}
if (hasAndroidVersion() && !getAndroidVersion().equals(rhs.getAndroidVersion())) {
return false;
}
if (hasTag() != rhs.hasTag()) {
return false;
}
if (hasTag() && !getTag().equals(rhs.getTag())) {
return false;
}
if (hasPath() != rhs.hasPath()) {
return false;
}
if (hasPath() && !getPath().equals(rhs.getPath())) {
return false;
}
if (hasFullRevision() != rhs.hasFullRevision()) {
return false;
}
if (hasFullRevision() && !getFullRevision().equals(rhs.getFullRevision())) {
return false;
}
if (hasMajorRevision() != rhs.hasMajorRevision()) {
return false;
}
if (hasMajorRevision() && !getMajorRevision().equals(rhs.getMajorRevision())) {
return false;
}
if (hasMinToolsRev() != rhs.hasMinToolsRev()) {
return false;
}
if (hasMinToolsRev() && !getMinToolsRev().equals(rhs.getMinToolsRev())) {
return false;
}
if (hasMinPlatformToolsRev() != rhs.hasMinPlatformToolsRev()) {
return false;
}
if (hasMinPlatformToolsRev() &&
!getMinPlatformToolsRev().equals(rhs.getMinPlatformToolsRev())) {
return false;
}
return true;
}
// ---- Constructors -----
public interface IIsUpdateFor {
public boolean isUpdateFor(@NonNull PkgDesc thisPkgDesc, @NonNull IPkgDesc existingDesc);
}
public interface IGetPath {
public String getPath(@NonNull PkgDesc thisPkgDesc);
}
public static class Builder {
private final PkgType mType;
private FullRevision mFullRevision;
private MajorRevision mMajorRevision;
private AndroidVersion mAndroidVersion;
private String mPath;
private IdDisplay mTag;
private IdDisplay mVendor;
private FullRevision mMinToolsRev;
private FullRevision mMinPlatformToolsRev;
private IIsUpdateFor mCustomIsUpdateFor;
private IGetPath mCustomPath;
private String[] mOldPaths;
private String mNameDisplay;
private IdDisplay mNameIdDisplay;
private License mLicense;
private String mListDisplay;
private String mDescriptionShort;
private String mDescriptionUrl;
private boolean mIsObsolete;
private Builder(PkgType type) {
mType = type;
}
/**
* Creates a new tool package descriptor.
*
* @param revision The revision of the tool package.
* @param minPlatformToolsRev The {@code min-platform-tools-rev}.
* Use {@link FullRevision#NOT_SPECIFIED} to indicate there is no requirement.
* @return A {@link PkgDesc} describing this tool package.
*/
@NonNull
public static Builder newTool(@NonNull FullRevision revision,
@NonNull FullRevision minPlatformToolsRev) {
Builder p = new Builder(PkgType.PKG_TOOLS);
p.mFullRevision = revision;
p.mMinPlatformToolsRev = minPlatformToolsRev;
return p;
}
/**
* Creates a new platform-tool package descriptor.
*
* @param revision The revision of the platform-tool package.
* @return A {@link PkgDesc} describing this platform-tool package.
*/
@NonNull
public static Builder newPlatformTool(@NonNull FullRevision revision) {
Builder p = new Builder(PkgType.PKG_PLATFORM_TOOLS);
p.mFullRevision = revision;
return p;
}
/**
* Creates a new build-tool package descriptor.
*
* @param revision The revision of the build-tool package.
* @return A {@link PkgDesc} describing this build-tool package.
*/
@NonNull
public static Builder newBuildTool(@NonNull FullRevision revision) {
Builder p = new Builder(PkgType.PKG_BUILD_TOOLS);
p.mFullRevision = revision;
p.mCustomIsUpdateFor = new IIsUpdateFor() {
@Override
public boolean isUpdateFor(PkgDesc thisPkgDesc, IPkgDesc existingDesc) {
// Generic test checks that the preview type is the same (both previews or not).
// Build tool is different in that the full revision must be an exact match
// and not an increase.
return thisPkgDesc.isGenericUpdateFor(existingDesc) &&
thisPkgDesc.getFullRevision().compareTo(
existingDesc.getFullRevision(),
PreviewComparison.COMPARE_TYPE) == 0;
}
};
return p;
}
/**
* Creates a new doc package descriptor.
*
* @param revision The revision of the doc package.
* @return A {@link PkgDesc} describing this doc package.
*/
@NonNull
public static Builder newDoc(@NonNull AndroidVersion version,
@NonNull MajorRevision revision) {
Builder p = new Builder(PkgType.PKG_DOC);
p.mAndroidVersion = version;
p.mMajorRevision = revision;
p.mCustomIsUpdateFor = new IIsUpdateFor() {
@Override
public boolean isUpdateFor(PkgDesc thisPkgDesc, IPkgDesc existingDesc) {
if (existingDesc == null ||
!thisPkgDesc.getType().equals(existingDesc.getType())) {
return false;
}
// This package is unique in the SDK. It's an update if the API is newer
// or the revision is newer for the same API.
int diff = thisPkgDesc.getAndroidVersion().compareTo(
existingDesc.getAndroidVersion());
return diff > 0 ||
(diff == 0 && thisPkgDesc.getMajorRevision().compareTo(
existingDesc.getMajorRevision()) > 0);
}
};
return p;
}
/**
* Creates a new extra package descriptor.
*
* @param vendor The vendor id string of the extra package.
* @param path The path id string of the extra package.
* @param displayName The display name. If missing, caller should build one using the path.
* @param oldPaths An optional list of older paths for this extra package.
* @param revision The revision of the extra package.
* @return A {@link PkgDesc} describing this extra package.
*/
@NonNull
public static Builder newExtra(@NonNull IdDisplay vendor,
@NonNull String path,
@NonNull String displayName,
@Nullable String[] oldPaths,
@NonNull NoPreviewRevision revision) {
Builder p = new Builder(PkgType.PKG_EXTRA);
p.mFullRevision = revision;
p.mVendor = vendor;
p.mPath = path;
p.mNameDisplay = displayName;
p.mOldPaths = oldPaths;
return p;
}
/**
* Creates a new platform package descriptor.
*
* @param version The android version of the platform package.
* @param revision The revision of the extra package.
* @param minToolsRev An optional {@code min-tools-rev}.
* Use {@link FullRevision#NOT_SPECIFIED} to indicate
* there is no requirement.
* @return A {@link PkgDesc} describing this platform package.
*/
@NonNull
public static Builder newPlatform(@NonNull AndroidVersion version,
@NonNull MajorRevision revision,
@NonNull FullRevision minToolsRev) {
Builder p = new Builder(PkgType.PKG_PLATFORM);
p.mAndroidVersion = version;
p.mMajorRevision = revision;
p.mMinToolsRev = minToolsRev;
p.mCustomPath = new IGetPath() {
@Override
public String getPath(PkgDesc thisPkgDesc) {
/** The "path" of a Platform is its Target Hash. */
return AndroidTargetHash.getPlatformHashString(thisPkgDesc.getAndroidVersion());
}
};
return p;
}
/**
* Create a new add-on package descriptor.
*
* The vendor id and the name id provided are used to compute the add-on's
* target hash.
*
* @param version The android version of the add-on package.
* @param revision The revision of the add-on package.
* @param addonVendor The vendor id/display of the add-on package.
* @param addonName The name id/display of the add-on package.
* @return A {@link PkgDesc} describing this add-on package.
*/
@NonNull
public static Builder newAddon(@NonNull AndroidVersion version,
@NonNull MajorRevision revision,
@NonNull IdDisplay addonVendor,
@NonNull IdDisplay addonName) {
Builder p = new Builder(PkgType.PKG_ADDON);
p.mAndroidVersion = version;
p.mMajorRevision = revision;
p.mVendor = addonVendor;
p.mNameIdDisplay = addonName;
return p;
}
/**
* Create a new platform system-image package descriptor.
*
* For system-images, {@link PkgDesc#getPath()} returns the ABI.
*
* @param version The android version of the system-image package.
* @param tag The tag of the system-image package.
* @param abi The ABI of the system-image package.
* @param revision The revision of the system-image package.
* @return A {@link PkgDesc} describing this system-image package.
*/
@NonNull
public static Builder newSysImg(@NonNull AndroidVersion version,
@NonNull IdDisplay tag,
@NonNull String abi,
@NonNull MajorRevision revision) {
Builder p = new Builder(PkgType.PKG_SYS_IMAGE);
p.mAndroidVersion = version;
p.mMajorRevision = revision;
p.mTag = tag;
p.mPath = abi;
p.mVendor = null;
return p;
}
/**
* Create a new add-on system-image package descriptor.
*
* For system-images, {@link PkgDesc#getPath()} returns the ABI.
*
* @param version The android version of the system-image package.
* @param addonVendor The vendor id/display of an associated add-on.
* @param addonName The tag of the system-image package is the add-on name.
* @param abi The ABI of the system-image package.
* @param revision The revision of the system-image package.
* @return A {@link PkgDesc} describing this system-image package.
*/
@NonNull
public static Builder newAddonSysImg(@NonNull AndroidVersion version,
@NonNull IdDisplay addonVendor,
@NonNull IdDisplay addonName,
@NonNull String abi,
@NonNull MajorRevision revision) {
Builder p = new Builder(PkgType.PKG_ADDON_SYS_IMAGE);
p.mAndroidVersion = version;
p.mMajorRevision = revision;
p.mTag = addonName;
p.mPath = abi;
p.mVendor = addonVendor;
return p;
}
/**
* Create a new source package descriptor.
*
* @param version The android version of the source package.
* @param revision The revision of the source package.
* @return A {@link PkgDesc} describing this source package.
*/
@NonNull
public static Builder newSource(@NonNull AndroidVersion version,
@NonNull MajorRevision revision) {
Builder p = new Builder(PkgType.PKG_SOURCE);
p.mAndroidVersion = version;
p.mMajorRevision = revision;
return p;
}
/**
* Create a new sample package descriptor.
*
* @param version The android version of the sample package.
* @param revision The revision of the sample package.
* @param minToolsRev An optional {@code min-tools-rev}.
* Use {@link FullRevision#NOT_SPECIFIED} to indicate
* there is no requirement.
* @return A {@link PkgDesc} describing this sample package.
*/
@NonNull
public static Builder newSample(@NonNull AndroidVersion version,
@NonNull MajorRevision revision,
@NonNull FullRevision minToolsRev) {
Builder p = new Builder(PkgType.PKG_SAMPLE);
p.mAndroidVersion = version;
p.mMajorRevision = revision;
p.mMinToolsRev = minToolsRev;
return p;
}
public Builder setDescriptions(@NonNull Package pkg) {
mDescriptionShort = pkg.getShortDescription();
mDescriptionUrl = pkg.getDescUrl();
mListDisplay = pkg.getListDisplay();
mIsObsolete = pkg.isObsolete();
mLicense = pkg.getLicense();
return this;
}
public Builder setLicense(@Nullable License license) {
mLicense = license;
return this;
}
public Builder setListDisplay(@Nullable String text) {
mListDisplay = text;
return this;
}
public Builder setDescriptionShort(@Nullable String text) {
mDescriptionShort = text;
return this;
}
public Builder setDescriptionUrl(@Nullable String text) {
mDescriptionUrl = text;
return this;
}
public Builder setIsObsolete(boolean isObsolete) {
mIsObsolete = isObsolete;
return this;
}
public IPkgDesc create() {
if (mType == PkgType.PKG_ADDON) {
return new PkgDescAddon(
mType,
mLicense,
mListDisplay,
mDescriptionShort,
mDescriptionUrl,
mIsObsolete,
mMajorRevision,
mAndroidVersion,
mVendor,
mNameIdDisplay);
}
if (mType == PkgType.PKG_EXTRA) {
return new PkgDescExtra(
mType,
mLicense,
mListDisplay,
mDescriptionShort,
mDescriptionUrl,
mIsObsolete,
mFullRevision,
mMajorRevision,
mAndroidVersion,
mPath,
mTag,
mVendor,
mMinToolsRev,
mMinPlatformToolsRev,
mNameDisplay,
mOldPaths);
}
return new PkgDesc(
mType,
mLicense,
mListDisplay,
mDescriptionShort,
mDescriptionUrl,
mIsObsolete,
mFullRevision,
mMajorRevision,
mAndroidVersion,
mPath,
mTag,
mVendor,
mMinToolsRev,
mMinPlatformToolsRev,
mCustomIsUpdateFor,
mCustomPath);
}
}
// ---- Helpers -----
@NonNull
private static String sanitize(@NonNull String str) {
str = str.toLowerCase(Locale.US).replaceAll("[^a-z0-9_.-]+", "_").replaceAll("_+", "_");
return str;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy