From 851a54143c15a1c33361efae2db3f7f45059b472 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Fri, 8 May 2009 12:06:44 -0700 Subject: 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. --- api/current.xml | 125 +++++++++++++++++++++ cmds/pm/src/com/android/commands/pm/Pm.java | 3 + core/java/android/content/pm/ApplicationInfo.java | 14 ++- core/java/android/content/pm/PackageManager.java | 8 ++ core/java/android/content/pm/PackageParser.java | 82 ++++++++++++-- core/java/android/os/Build.java | 38 ++++++- core/res/res/values/attrs_manifest.xml | 25 ++++- core/res/res/values/public.xml | 4 +- .../com/android/server/PackageManagerService.java | 10 +- 9 files changed, 284 insertions(+), 25 deletions(-) diff --git a/api/current.xml b/api/current.xml index f809c09..656b12b 100644 --- a/api/current.xml +++ b/api/current.xml @@ -5113,6 +5113,17 @@ visibility="public" > + + + + + + + + + + + + + + + + + + + + + + @@ -86088,6 +86203,16 @@ visibility="public" > + + = 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 abstract class PackageManager { 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 @@ public class PackageParser { private String mArchiveSourcePath; private String[] mSeparateProcesses; private int mSdkVersion; + private String mSdkCodename; private int mParseError = PackageManager.INSTALL_SUCCEEDED; @@ -123,8 +124,9 @@ public class PackageParser { 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 @@ public class PackageParser { 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 @@ public class PackageParser { 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 @@ public class PackageParser { 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 @@ public class PackageParser { // 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 class Build { 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. --> - + 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. --> + + + + + @@ -1097,6 +1097,8 @@ + + diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index a60f059..237b70d 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -59,6 +59,7 @@ import android.content.pm.ServiceInfo; import android.content.pm.Signature; import android.net.Uri; import android.os.Binder; +import android.os.Build; import android.os.Bundle; import android.os.HandlerThread; import android.os.Parcel; @@ -140,8 +141,9 @@ class PackageManagerService extends IPackageManager.Stub { Process.THREAD_PRIORITY_BACKGROUND); final Handler mHandler; - final int mSdkVersion = SystemProperties.getInt( - "ro.build.version.sdk", 0); + final int mSdkVersion = Build.VERSION.SDK_INT; + final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME) + ? null : Build.VERSION.CODENAME; final Context mContext; final boolean mFactoryTest; @@ -1751,7 +1753,7 @@ class PackageManagerService extends IPackageManager.Stub { parseFlags |= mDefParseFlags; PackageParser pp = new PackageParser(scanFile.getPath()); pp.setSeparateProcesses(mSeparateProcesses); - pp.setSdkVersion(mSdkVersion); + pp.setSdkVersion(mSdkVersion, mSdkCodename); final PackageParser.Package pkg = pp.parsePackage(scanFile, destCodeFile.getAbsolutePath(), mMetrics, parseFlags); if (pkg == null) { @@ -3693,7 +3695,7 @@ class PackageManagerService extends IPackageManager.Stub { parseFlags |= mDefParseFlags; PackageParser pp = new PackageParser(tmpPackageFile.getPath()); pp.setSeparateProcesses(mSeparateProcesses); - pp.setSdkVersion(mSdkVersion); + pp.setSdkVersion(mSdkVersion, mSdkCodename); final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile, destPackageFile.getAbsolutePath(), mMetrics, parseFlags); if (pkg == null) { -- cgit v1.1