diff options
author | Jeff Sharkey <jsharkey@android.com> | 2014-11-22 16:49:34 -0800 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2014-11-24 12:13:11 -0800 |
commit | 88d2a3c0e1b4a8c53a489db5d627beb80b1b9957 (patch) | |
tree | 18761183dea3ba5e0c63283feb938934a3454294 /core/java/android/content | |
parent | 4dfce43e976a294b3b575564c855214a8e5cef58 (diff) | |
download | frameworks_base-88d2a3c0e1b4a8c53a489db5d627beb80b1b9957.zip frameworks_base-88d2a3c0e1b4a8c53a489db5d627beb80b1b9957.tar.gz frameworks_base-88d2a3c0e1b4a8c53a489db5d627beb80b1b9957.tar.bz2 |
Introduce revision codes for split APKs.
Apps delivered as multiple split APKs must have identical package
names, version code, and signatures. However, developers may want
to iterate quickly on a subset of splits without having to increment
the version code, which would require delivery of the entire app.
This change introduces "revision codes" which can vary between
split APKs belonging to the same app. An install is valid as long
as the normal version code is identical across all splits. Splits
can be added/removed to an app over time, but if a split is present
across an upgrade the revision code must not decrease.
Since system apps could have been updated with splits, only revert
to the built-in APKs if the version code is strictly greater than the
data version. Also fix bug to enable inheriting from system apps
when adding splits.
Bug: 18481866
Change-Id: I34d8e14c141a8eb95c33ffe24b4e52d6af5c8260
Diffstat (limited to 'core/java/android/content')
-rw-r--r-- | core/java/android/content/pm/PackageInfo.java | 31 | ||||
-rw-r--r-- | core/java/android/content/pm/PackageInfoLite.java | 16 | ||||
-rw-r--r-- | core/java/android/content/pm/PackageParser.java | 50 |
3 files changed, 79 insertions, 18 deletions
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java index b66bd01..9223269 100644 --- a/core/java/android/content/pm/PackageInfo.java +++ b/core/java/android/content/pm/PackageInfo.java @@ -41,14 +41,30 @@ public class PackageInfo implements Parcelable { * attribute. */ public int versionCode; - + /** * The version name of this package, as specified by the <manifest> * tag's {@link android.R.styleable#AndroidManifest_versionName versionName} * attribute. */ public String versionName; - + + /** + * The revision number of the base APK for this package, as specified by the + * <manifest> tag's + * {@link android.R.styleable#AndroidManifest_revisionCode revisionCode} + * attribute. + */ + public int baseRevisionCode; + + /** + * The revision number of any split APKs for this package, as specified by + * the <manifest> tag's + * {@link android.R.styleable#AndroidManifest_revisionCode revisionCode} + * attribute. Indexes are a 1:1 mapping against {@link #splitNames}. + */ + public int[] splitRevisionCodes; + /** * The shared user ID name of this package, as specified by the <manifest> * tag's {@link android.R.styleable#AndroidManifest_sharedUserId sharedUserId} @@ -257,21 +273,26 @@ public class PackageInfo implements Parcelable { public PackageInfo() { } + @Override public String toString() { return "PackageInfo{" + Integer.toHexString(System.identityHashCode(this)) + " " + packageName + "}"; } + @Override public int describeContents() { return 0; } + @Override public void writeToParcel(Parcel dest, int parcelableFlags) { dest.writeString(packageName); dest.writeStringArray(splitNames); dest.writeInt(versionCode); dest.writeString(versionName); + dest.writeInt(baseRevisionCode); + dest.writeIntArray(splitRevisionCodes); dest.writeString(sharedUserId); dest.writeInt(sharedUserLabel); if (applicationInfo != null) { @@ -305,10 +326,12 @@ public class PackageInfo implements Parcelable { public static final Parcelable.Creator<PackageInfo> CREATOR = new Parcelable.Creator<PackageInfo>() { + @Override public PackageInfo createFromParcel(Parcel source) { return new PackageInfo(source); } + @Override public PackageInfo[] newArray(int size) { return new PackageInfo[size]; } @@ -316,9 +339,11 @@ public class PackageInfo implements Parcelable { private PackageInfo(Parcel source) { packageName = source.readString(); - splitNames = source.readStringArray(); + splitNames = source.createStringArray(); versionCode = source.readInt(); versionName = source.readString(); + baseRevisionCode = source.readInt(); + splitRevisionCodes = source.createIntArray(); sharedUserId = source.readString(); sharedUserLabel = source.readInt(); int hasApp = source.readInt(); diff --git a/core/java/android/content/pm/PackageInfoLite.java b/core/java/android/content/pm/PackageInfoLite.java index e336c5f..1efe082 100644 --- a/core/java/android/content/pm/PackageInfoLite.java +++ b/core/java/android/content/pm/PackageInfoLite.java @@ -19,6 +19,8 @@ package android.content.pm; import android.os.Parcel; import android.os.Parcelable; +import com.android.internal.content.PackageHelper; + /** * Basic information about a package as specified in its manifest. * Utility class used in PackageManager methods @@ -31,11 +33,19 @@ public class PackageInfoLite implements Parcelable { */ public String packageName; + /** Names of any split APKs, ordered by parsed splitName */ + public String[] splitNames; + /** * The android:versionCode of the package. */ public int versionCode; + /** Revision code of base APK */ + public int baseRevisionCode; + /** Revision codes of any split APKs, ordered by parsed splitName */ + public int[] splitRevisionCodes; + /** * The android:multiArch flag from the package manifest. If set, * we will extract all native libraries for the given app, not just those @@ -70,7 +80,10 @@ public class PackageInfoLite implements Parcelable { public void writeToParcel(Parcel dest, int parcelableFlags) { dest.writeString(packageName); + dest.writeStringArray(splitNames); dest.writeInt(versionCode); + dest.writeInt(baseRevisionCode); + dest.writeIntArray(splitRevisionCodes); dest.writeInt(recommendedInstallLocation); dest.writeInt(installLocation); dest.writeInt(multiArch ? 1 : 0); @@ -96,7 +109,10 @@ public class PackageInfoLite implements Parcelable { private PackageInfoLite(Parcel source) { packageName = source.readString(); + splitNames = source.createStringArray(); versionCode = source.readInt(); + baseRevisionCode = source.readInt(); + splitRevisionCodes = source.createIntArray(); recommendedInstallLocation = source.readInt(); installLocation = source.readInt(); multiArch = (source.readInt() != 0); diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 8515520..82da7c5 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -261,11 +261,16 @@ public class PackageParser { /** Paths of any split APKs, ordered by parsed splitName */ public final String[] splitCodePaths; + /** Revision code of base APK */ + public final int baseRevisionCode; + /** Revision codes of any split APKs, ordered by parsed splitName */ + public final int[] splitRevisionCodes; + public final boolean coreApp; public final boolean multiArch; public PackageLite(String codePath, ApkLite baseApk, String[] splitNames, - String[] splitCodePaths) { + String[] splitCodePaths, int[] splitRevisionCodes) { this.packageName = baseApk.packageName; this.versionCode = baseApk.versionCode; this.installLocation = baseApk.installLocation; @@ -274,6 +279,8 @@ public class PackageParser { this.codePath = codePath; this.baseCodePath = baseApk.codePath; this.splitCodePaths = splitCodePaths; + this.baseRevisionCode = baseApk.revisionCode; + this.splitRevisionCodes = splitRevisionCodes; this.coreApp = baseApk.coreApp; this.multiArch = baseApk.multiArch; } @@ -296,6 +303,7 @@ public class PackageParser { public final String packageName; public final String splitName; public final int versionCode; + public final int revisionCode; public final int installLocation; public final VerifierInfo[] verifiers; public final Signature[] signatures; @@ -303,12 +311,13 @@ public class PackageParser { public final boolean multiArch; public ApkLite(String codePath, String packageName, String splitName, int versionCode, - int installLocation, List<VerifierInfo> verifiers, Signature[] signatures, - boolean coreApp, boolean multiArch) { + int revisionCode, int installLocation, List<VerifierInfo> verifiers, + Signature[] signatures, boolean coreApp, boolean multiArch) { this.codePath = codePath; this.packageName = packageName; this.splitName = splitName; this.versionCode = versionCode; + this.revisionCode = revisionCode; this.installLocation = installLocation; this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]); this.signatures = signatures; @@ -409,6 +418,8 @@ public class PackageParser { pi.packageName = p.packageName; pi.splitNames = p.splitNames; pi.versionCode = p.mVersionCode; + pi.baseRevisionCode = p.baseRevisionCode; + pi.splitRevisionCodes = p.splitRevisionCodes; pi.versionName = p.mVersionName; pi.sharedUserId = p.mSharedUserId; pi.sharedUserLabel = p.mSharedUserLabel; @@ -647,7 +658,7 @@ public class PackageParser { throws PackageParserException { final ApkLite baseApk = parseApkLite(packageFile, flags); final String packagePath = packageFile.getAbsolutePath(); - return new PackageLite(packagePath, baseApk, null, null); + return new PackageLite(packagePath, baseApk, null, null, null); } private static PackageLite parseClusterPackageLite(File packageDir, int flags) @@ -704,20 +715,24 @@ public class PackageParser { String[] splitNames = null; String[] splitCodePaths = null; + int[] splitRevisionCodes = null; if (size > 0) { splitNames = new String[size]; splitCodePaths = new String[size]; + splitRevisionCodes = new int[size]; splitNames = apks.keySet().toArray(splitNames); Arrays.sort(splitNames, sSplitNameComparator); for (int i = 0; i < size; i++) { splitCodePaths[i] = apks.get(splitNames[i]).codePath; + splitRevisionCodes[i] = apks.get(splitNames[i]).revisionCode; } } final String codePath = packageDir.getAbsolutePath(); - return new PackageLite(codePath, baseApk, splitNames, splitCodePaths); + return new PackageLite(codePath, baseApk, splitNames, splitCodePaths, + splitRevisionCodes); } /** @@ -782,6 +797,7 @@ public class PackageParser { final int num = lite.splitNames.length; pkg.splitNames = lite.splitNames; pkg.splitCodePaths = lite.splitCodePaths; + pkg.splitRevisionCodes = lite.splitRevisionCodes; pkg.splitFlags = new int[num]; for (int i = 0; i < num; i++) { @@ -1249,25 +1265,21 @@ public class PackageParser { int installLocation = PARSE_DEFAULT_INSTALL_LOCATION; int versionCode = 0; + int revisionCode = 0; boolean coreApp = false; boolean multiArch = false; - int numFound = 0; for (int i = 0; i < attrs.getAttributeCount(); i++) { - String attr = attrs.getAttributeName(i); + final String attr = attrs.getAttributeName(i); if (attr.equals("installLocation")) { installLocation = attrs.getAttributeIntValue(i, PARSE_DEFAULT_INSTALL_LOCATION); - numFound++; } else if (attr.equals("versionCode")) { versionCode = attrs.getAttributeIntValue(i, 0); - numFound++; + } else if (attr.equals("revisionCode")) { + revisionCode = attrs.getAttributeIntValue(i, 0); } else if (attr.equals("coreApp")) { coreApp = attrs.getAttributeBooleanValue(i, false); - numFound++; - } - if (numFound >= 3) { - break; } } @@ -1301,7 +1313,7 @@ public class PackageParser { } return new ApkLite(codePath, packageSplit.first, packageSplit.second, versionCode, - installLocation, verifiers, signatures, coreApp, multiArch); + revisionCode, installLocation, verifiers, signatures, coreApp, multiArch); } /** @@ -1359,6 +1371,8 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifest); pkg.mVersionCode = pkg.applicationInfo.versionCode = sa.getInteger( com.android.internal.R.styleable.AndroidManifest_versionCode, 0); + pkg.baseRevisionCode = sa.getInteger( + com.android.internal.R.styleable.AndroidManifest_revisionCode, 0); pkg.mVersionName = sa.getNonConfigurationString( com.android.internal.R.styleable.AndroidManifest_versionName, 0); if (pkg.mVersionName != null) { @@ -4168,6 +4182,7 @@ public class PackageParser { public final static class Package { public String packageName; + /** Names of any split APKs, ordered by parsed splitName */ public String[] splitNames; @@ -4185,6 +4200,11 @@ public class PackageParser { /** Paths of any split APKs, ordered by parsed splitName */ public String[] splitCodePaths; + /** Revision code of base APK */ + public int baseRevisionCode; + /** Revision codes of any split APKs, ordered by parsed splitName */ + public int[] splitRevisionCodes; + /** Flags of any split APKs; ordered by parsed splitName */ public int[] splitFlags; @@ -4222,7 +4242,7 @@ public class PackageParser { // The version code declared for this package. public int mVersionCode; - + // The version name declared for this package. public String mVersionName; |