Implement targetSdkVersion and maxSdkVersion, plus version code names.
This adds new attributes for specifying a targetSdkVersion and maxSdkVersion.
There is a new ApplicationInfo flag that is set if the application has set
its targetSdkVersion to the current platform or later. Also you can now
use a string for minSdkVersion and targetSdkVerion, to indicate you are
building against a development tree instead of an official platform.
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 173057c..fa9ec6e 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -113,19 +113,25 @@
*/
public static final int FLAG_ALLOW_CLEAR_USER_DATA = 1<<6;
-
/**
- * Value for {@link #flags}: default value for the corresponding ActivityInfo flag.
- * {@hide}
+ * Value for {@link #flags}: this is set if this application has been
+ * install as an update to a built-in system application.
*/
public static final int FLAG_UPDATED_SYSTEM_APP = 1<<7;
+
+ /**
+ * Value for {@link #flags}: this is set of the application has set
+ * its android:targetSdkVersion to something >= the current SDK version.
+ */
+ public static final int FLAG_TARGETS_SDK = 1<<8;
/**
* Flags associated with the application. Any combination of
* {@link #FLAG_SYSTEM}, {@link #FLAG_DEBUGGABLE}, {@link #FLAG_HAS_CODE},
* {@link #FLAG_PERSISTENT}, {@link #FLAG_FACTORY_TEST}, and
* {@link #FLAG_ALLOW_TASK_REPARENTING}
- * {@link #FLAG_ALLOW_CLEAR_USER_DATA}.
+ * {@link #FLAG_ALLOW_CLEAR_USER_DATA}, {@link #FLAG_UPDATED_SYSTEM_APP},
+ * {@link #FLAG_TARGETS_SDK}.
*/
public int flags = 0;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 9e06666..d21252b 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -355,6 +355,14 @@
public static final int INSTALL_FAILED_CONFLICTING_PROVIDER = -13;
/**
+ * Installation return code: this is passed to the {@link IPackageInstallObserver} by
+ * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
+ * the new package failed because the current SDK version is newer than
+ * that required by the package.
+ */
+ public static final int INSTALL_FAILED_NEWER_SDK = -14;
+
+ /**
* Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
* {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
* if the parser was given a path that is not a file, or does not end with the expected
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index f9c4984..12df5bd 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -59,6 +59,7 @@
private String mArchiveSourcePath;
private String[] mSeparateProcesses;
private int mSdkVersion;
+ private String mSdkCodename;
private int mParseError = PackageManager.INSTALL_SUCCEEDED;
@@ -123,8 +124,9 @@
mSeparateProcesses = procs;
}
- public void setSdkVersion(int sdkVersion) {
+ public void setSdkVersion(int sdkVersion, String codename) {
mSdkVersion = sdkVersion;
+ mSdkCodename = codename;
}
private static final boolean isPackageFilename(String name) {
@@ -613,9 +615,9 @@
int type;
final Package pkg = new Package(pkgName);
- pkg.mSystem = (flags&PARSE_IS_SYSTEM) != 0;
boolean foundApp = false;
-
+ boolean targetsSdk = false;
+
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifest);
pkg.mVersionCode = sa.getInteger(
@@ -721,19 +723,74 @@
XmlUtils.skipCurrentTag(parser);
- } else if (tagName.equals("uses-sdk")) {
+ } else if (tagName.equals("uses-sdk")) {
if (mSdkVersion > 0) {
sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifestUsesSdk);
- int vers = sa.getInt(
- com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion, 0);
+ int minVers = 0;
+ String minCode = null;
+ int targetVers = 0;
+ String targetCode = null;
+
+ TypedValue val = sa.peekValue(
+ com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
+ if (val != null) {
+ if (val.type == TypedValue.TYPE_STRING && val.string != null) {
+ targetCode = minCode = val.string.toString();
+ } else {
+ // If it's not a string, it's an integer.
+ minVers = val.data;
+ }
+ }
+
+ val = sa.peekValue(
+ com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
+ if (val != null) {
+ if (val.type == TypedValue.TYPE_STRING && val.string != null) {
+ targetCode = minCode = val.string.toString();
+ } else {
+ // If it's not a string, it's an integer.
+ targetVers = val.data;
+ }
+ }
+
+ int maxVers = sa.getInt(
+ com.android.internal.R.styleable.AndroidManifestUsesSdk_maxSdkVersion,
+ mSdkVersion);
sa.recycle();
- if (vers > mSdkVersion) {
- outError[0] = "Requires newer sdk version #" + vers
- + " (current version is #" + mSdkVersion + ")";
+ if (targetCode != null) {
+ if (!targetCode.equals(mSdkCodename)) {
+ if (mSdkCodename != null) {
+ outError[0] = "Requires development platform " + targetCode
+ + " (current platform is " + mSdkCodename + ")";
+ } else {
+ outError[0] = "Requires development platform " + targetCode
+ + " but this is a release platform.";
+ }
+ mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
+ return null;
+ }
+ // If the code matches, it definitely targets this SDK.
+ targetsSdk = true;
+ } else if (targetVers >= mSdkVersion) {
+ // If they have explicitly targeted our current version
+ // or something after it, then note this.
+ targetsSdk = true;
+ }
+
+ if (minVers > mSdkVersion) {
+ outError[0] = "Requires newer sdk version #" + minVers
+ + " (current version is #" + mSdkVersion + ")";
+ mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
+ return null;
+ }
+
+ if (maxVers < mSdkVersion) {
+ outError[0] = "Requires older sdk version #" + maxVers
+ + " (current version is #" + mSdkVersion + ")";
mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
return null;
}
@@ -767,6 +824,10 @@
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
}
+ if (targetsSdk) {
+ pkg.applicationInfo.flags |= ApplicationInfo.FLAG_TARGETS_SDK;
+ }
+
if (pkg.usesLibraries.size() > 0) {
pkg.usesLibraryFiles = new String[pkg.usesLibraries.size()];
pkg.usesLibraries.toArray(pkg.usesLibraryFiles);
@@ -2133,9 +2194,6 @@
// If this is a 3rd party app, this is the path of the zip file.
public String mPath;
- // True if this package is part of the system image.
- public boolean mSystem;
-
// The version code declared for this package.
public int mVersionCode;
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 467c17f..5487c54 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -59,11 +59,47 @@
public static final String RELEASE = getString("ro.build.version.release");
/**
- * The user-visible SDK version of the framework. It is an integer starting at 1.
+ * The user-visible SDK version of the framework in its raw String
+ * representation; use {@link #SDK_INT} instead.
+ *
+ * @deprecated Use {@link #SDK_INT} to easily get this as an integer.
*/
public static final String SDK = getString("ro.build.version.sdk");
+
+ /**
+ * The user-visible SDK version of the framework; its possible
+ * values are defined in {@link Build.VERSION_CODES}.
+ */
+ public static final int SDK_INT = SystemProperties.getInt(
+ "ro.build.version.sdk", 0);
+
+ /**
+ * The current development codename, or the string "REL" if this is
+ * a release build.
+ */
+ public static final String CODENAME = getString("ro.build.version.codename");
}
+ /**
+ * Enumeration of the currently known SDK version codes. These are the
+ * values that can be found in {@link VERSION#SDK}. Version numbers
+ * increment monotonically with each official platform release.
+ */
+ public static class VERSION_CODES {
+ /**
+ * October 2008: The original, first, version of Android. Yay!
+ */
+ public static final int BASE = 1;
+ /**
+ * February 2009: First Android update, officially called 1.1.
+ */
+ public static final int BASE_1_1 = 2;
+ /**
+ * May 2009: Android 1.5.
+ */
+ public static final int CUPCAKE = 3;
+ }
+
/** The type of build, like "user" or "eng". */
public static final String TYPE = getString("ro.build.type");
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 54da326..1319c77 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -753,9 +753,28 @@
{@link #AndroidManifest manifest} tag. -->
<declare-styleable name="AndroidManifestUsesSdk" parent="AndroidManifest">
<!-- This is the minimum SDK version number that the application
- requires. Currently there is only one SDK version, 1. If
- not supplied, the application will work on any SDK. -->
- <attr name="minSdkVersion" format="integer" />
+ requires. This number is an abstract integer, from the list
+ in {@link android.os.Build.VERSION_CODES} If
+ not supplied, the application will work on any SDK. This
+ may also be string (such as "Donut") if the application was built
+ against a development branch, in which case it will only work against
+ the development builds. -->
+ <attr name="minSdkVersion" format="integer|string" />
+ <!-- This is the SDK version number that the application is targeting.
+ It is able to run on older versions (down to minSdkVersion), but
+ was explicitly tested to work with the version specified here.
+ Specifying this version allows the platform to disable compatibility
+ code that are not required or enable newer features that are not
+ available to older applications. This may also be a string
+ (such as "Donut") if this is built against a development
+ branch, in which case minSdkVersion is also forced to be that
+ string. -->
+ <attr name="targetSdkVersion" format="integer|string" />
+ <!-- This is the maximum SDK version number that an application works
+ on. You can use this to ensure your application is filtered out
+ of later versions of the platform when you know you have
+ incompatibility with them. -->
+ <attr name="maxSdkVersion" format="integer" />
</declare-styleable>
<!-- The <code>uses-libraries</code> specifies a shared library that this
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 9e4c6a9..df5d879 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1087,7 +1087,7 @@
<public type="integer" name="config_longAnimTime" id="0x010e0002" />
<!-- ===============================================================
- Resources added in version 4 of the platform.
+ Resources added in Donut.
=============================================================== -->
<eat-comment />
@@ -1097,6 +1097,8 @@
<public type="attr" name="searchSuggestThreshold" id="0x0101026d" />
<public type="attr" name="includeInGlobalSearch" id="0x0101026e" />
<public type="attr" name="onClick" id="0x0101026f" />
+ <public type="attr" name="targetSdkVersion" id="0x01010270" />
+ <public type="attr" name="maxSdkVersion" id="0x01010271" />
<public type="anim" name="anticipate_interpolator" id="0x010a0007" />
<public type="anim" name="overshoot_interpolator" id="0x010a0008" />