= npi.sdkVersion) {
+ break;
+ }
+ if (!pkg.requestedPermissions.contains(npi.name)) {
+ Log.i(TAG, "Impliciting adding " + npi.name + " to old pkg "
+ + pkg.packageName);
+ pkg.requestedPermissions.add(npi.name);
+ }
}
if (pkg.usesLibraries.size() > 0) {
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 5487c545c12ad..4a4285eb8b892 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -86,6 +86,12 @@ public class Build {
* increment monotonically with each official platform release.
*/
public static class VERSION_CODES {
+ /**
+ * Magic version number for a current development build, which has
+ * not yet turned into an official release.
+ */
+ public static final int CUR_DEVELOPMENT = 10000;
+
/**
* October 2008: The original, first, version of Android. Yay!
*/
@@ -98,6 +104,19 @@ public class Build {
* May 2009: Android 1.5.
*/
public static final int CUPCAKE = 3;
+ /**
+ * Current work on "Donut" development branch.
+ *
+ * Applications targeting this or a later release will get these
+ * new changes in behavior:
+ *
+ * - They must explicitly request the
+ * {@link android.Manifest.permission#WRITE_SDCARD} permission to be
+ * able to modify the contents of the SD card. (Apps targeting
+ * earlier versions will always request the permission.)
+ *
+ */
+ public static final int DONUT = CUR_DEVELOPMENT;
}
/** The type of build, like "user" or "eng". */
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 05fbe64e432ca..d4b314a465732 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -389,11 +389,11 @@
android:description="@string/permgroupdesc_storage" />
-
+ android:protectionLevel="dangerous" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 9ddfa82aacf23..ce716b1871d8a 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1076,7 +1076,7 @@
user dictionary.
- write to SD card
+ modify/delete SD card contents
Allows an application to write to the SD card.
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index f80bd6b00cdc4..526b6d908e13c 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -54,7 +54,7 @@
-
+
@@ -84,6 +84,24 @@
others should have a fairly open environment in which to
interact with the system. -->
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -114,6 +132,8 @@
+
+
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 5194aea902d85..0007066080d2e 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -2831,6 +2831,21 @@ class PackageManagerService extends IPackageManager.Stub {
// we can't add any new permissions to it.
if (!gp.loadedPermissions.contains(perm)) {
allowed = false;
+ // Except... if this is a permission that was added
+ // to the platform (note: need to only do this when
+ // updating the platform).
+ final int NP = PackageParser.NEW_PERMISSIONS.length;
+ for (int ip=0; ip& getNoCompressExtensions() const { return mNoCompressExtensions; }
void addNoCompressExtension(const char* ext) { mNoCompressExtensions.add(ext); }
+ const char* getMinSdkVersion() const { return mMinSdkVersion; }
+ void setMinSdkVersion(const char* val) { mMinSdkVersion = val; }
+ const char* getTargetSdkVersion() const { return mTargetSdkVersion; }
+ void setTargetSdkVersion(const char* val) { mTargetSdkVersion = val; }
+ const char* getMaxSdkVersion() const { return mMaxSdkVersion; }
+ void setMaxSdkVersion(const char* val) { mMaxSdkVersion = val; }
+ const char* getVersionCode() const { return mVersionCode; }
+ void setVersionCode(const char* val) { mVersionCode = val; }
+ const char* getVersionName() const { return mVersionName; }
+ void setVersionName(const char* val) { mVersionName = val; }
+
/*
* Set and get the file specification.
*
@@ -151,6 +162,12 @@ private:
android::Vector mNoCompressExtensions;
android::Vector mResourceSourceDirs;
+ const char* mMinSdkVersion;
+ const char* mTargetSdkVersion;
+ const char* mMaxSdkVersion;
+ const char* mVersionCode;
+ const char* mVersionName;
+
/* file specification */
int mArgc;
char* const* mArgv;
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index 71b1a3c86317f..8bf2b075e6fe4 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -54,9 +54,10 @@ void usage(void)
" xmlstrings Print the strings of the given compiled xml assets.\n\n", gProgName);
fprintf(stderr,
" %s p[ackage] [-d][-f][-m][-u][-v][-x][-z][-M AndroidManifest.xml] \\\n"
- " [-0 extension [-0 extension ...]] \\\n"
- " [-g tolerance] \\\n"
- " [-j jarfile] \\\n"
+ " [-0 extension [-0 extension ...]] [-g tolerance] [-j jarfile] \\\n"
+ " [--min-sdk-version VAL] [--target-sdk-version VAL] \\\n"
+ " [--max-sdk-version VAL] [--app-version VAL] \\\n"
+ " [--app-version-name TEXT] \\\n"
" [-I base-package [-I base-package ...]] \\\n"
" [-A asset-source-dir] [-P public-definitions-file] \\\n"
" [-S resource-sources [-S resource-sources ...]] "
@@ -115,7 +116,17 @@ void usage(void)
" and the first match found (left to right) will take precedence."
" -0 specifies an additional extension for which such files will not\n"
" be stored compressed in the .apk. An empty string means to not\n"
- " compress any files at all.\n");
+ " compress any files at all.\n"
+ " --min-sdk-version\n"
+ " inserts android:minSdkVersion in to manifest.\n"
+ " --target-sdk-version\n"
+ " inserts android:targetSdkVersion in to manifest.\n"
+ " --max-sdk-version\n"
+ " inserts android:maxSdkVersion in to manifest.\n"
+ " --version-code\n"
+ " inserts android:versionCode in to manifest.\n"
+ " --version-name\n"
+ " inserts android:versionName in to manifest.\n");
}
/*
@@ -339,6 +350,59 @@ int main(int argc, char* const argv[])
bundle.setCompressionMethod(ZipEntry::kCompressStored);
}
break;
+ case '-':
+ if (strcmp(cp, "-min-sdk-version") == 0) {
+ argc--;
+ argv++;
+ if (!argc) {
+ fprintf(stderr, "ERROR: No argument supplied for '--min-sdk-version' option\n");
+ wantUsage = true;
+ goto bail;
+ }
+ bundle.setMinSdkVersion(argv[0]);
+ } else if (strcmp(cp, "-target-sdk-version") == 0) {
+ argc--;
+ argv++;
+ if (!argc) {
+ fprintf(stderr, "ERROR: No argument supplied for '--target-sdk-version' option\n");
+ wantUsage = true;
+ goto bail;
+ }
+ bundle.setTargetSdkVersion(argv[0]);
+ } else if (strcmp(cp, "-max-sdk-version") == 0) {
+ argc--;
+ argv++;
+ if (!argc) {
+ fprintf(stderr, "ERROR: No argument supplied for '--max-sdk-version' option\n");
+ wantUsage = true;
+ goto bail;
+ }
+ bundle.setMaxSdkVersion(argv[0]);
+ } else if (strcmp(cp, "-version-code") == 0) {
+ argc--;
+ argv++;
+ if (!argc) {
+ fprintf(stderr, "ERROR: No argument supplied for '--version-code' option\n");
+ wantUsage = true;
+ goto bail;
+ }
+ bundle.setVersionCode(argv[0]);
+ } else if (strcmp(cp, "-version-name") == 0) {
+ argc--;
+ argv++;
+ if (!argc) {
+ fprintf(stderr, "ERROR: No argument supplied for '--version-name' option\n");
+ wantUsage = true;
+ goto bail;
+ }
+ bundle.setVersionName(argv[0]);
+ } else {
+ fprintf(stderr, "ERROR: Unknown option '-%s'\n", cp);
+ wantUsage = true;
+ goto bail;
+ }
+ cp += strlen(cp) - 1;
+ break;
default:
fprintf(stderr, "ERROR: Unknown flag '-%c'\n", *cp);
wantUsage = true;
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 2e4d0a4747c67..76b9d0ab7c9fb 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -488,6 +488,58 @@ static void applyFileOverlay(const sp& assets,
return;
}
+void addTagAttribute(const sp& node, const char* ns8,
+ const char* attr8, const char* value)
+{
+ if (value == NULL) {
+ return;
+ }
+
+ const String16 ns(ns8);
+ const String16 attr(attr8);
+
+ if (node->getAttribute(ns, attr) != NULL) {
+ fprintf(stderr, "Warning: AndroidManifest.xml already defines %s (in %s)\n",
+ String8(attr).string(), String8(ns).string());
+ return;
+ }
+
+ node->addAttribute(ns, attr, String16(value));
+}
+
+status_t massageManifest(Bundle* bundle, sp root)
+{
+ root = root->searchElement(String16(), String16("manifest"));
+ if (root == NULL) {
+ fprintf(stderr, "No tag.\n");
+ return UNKNOWN_ERROR;
+ }
+
+ addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "versionCode",
+ bundle->getVersionCode());
+ addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "versionName",
+ bundle->getVersionName());
+
+ if (bundle->getMinSdkVersion() != NULL
+ || bundle->getTargetSdkVersion() != NULL
+ || bundle->getMaxSdkVersion() != NULL) {
+ sp vers = root->getChildElement(String16(), String16("uses-sdk"));
+ if (vers == NULL) {
+ vers = XMLNode::newElement(root->getFilename(), String16(), String16("uses-sdk"));
+ root->insertChildAt(vers, 0);
+ }
+
+ addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "minSdkVersion",
+ bundle->getMinSdkVersion());
+ addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "targetSdkVersion",
+ bundle->getTargetSdkVersion());
+ addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "maxSdkVersion",
+ bundle->getMaxSdkVersion());
+ }
+
+ return NO_ERROR;
+}
+
#define ASSIGN_IT(n) \
do { \
ssize_t index = resources->indexOfKey(String8(#n)); \
@@ -1006,7 +1058,15 @@ status_t buildResources(Bundle* bundle, const sp& assets)
// Generate final compiled manifest file.
manifestFile->clearData();
- err = compileXmlFile(assets, manifestFile, &table);
+ sp manifestTree = XMLNode::parse(manifestFile);
+ if (manifestTree == NULL) {
+ return UNKNOWN_ERROR;
+ }
+ err = massageManifest(bundle, manifestTree);
+ if (err < NO_ERROR) {
+ return err;
+ }
+ err = compileXmlFile(assets, manifestTree, manifestFile, &table);
if (err < NO_ERROR) {
return err;
}
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index ef11a83c83875..25ab1474d9486 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -23,6 +23,16 @@ status_t compileXmlFile(const sp& assets,
if (root == NULL) {
return UNKNOWN_ERROR;
}
+
+ return compileXmlFile(assets, root, target, table, options);
+}
+
+status_t compileXmlFile(const sp& assets,
+ const sp& root,
+ const sp& target,
+ ResourceTable* table,
+ int options)
+{
if ((options&XML_COMPILE_STRIP_WHITESPACE) != 0) {
root->removeWhitespace(true, NULL);
} else if ((options&XML_COMPILE_COMPACT_WHITESPACE) != 0) {
@@ -1307,7 +1317,7 @@ status_t ResourceTable::addIncludedResources(Bundle* bundle, const sp& assets,
ResourceTable* table,
int options = XML_COMPILE_STANDARD_RESOURCE);
+status_t compileXmlFile(const sp& assets,
+ const sp& xmlTree,
+ const sp& target,
+ ResourceTable* table,
+ int options = XML_COMPILE_STANDARD_RESOURCE);
+
status_t compileResourceFile(Bundle* bundle,
const sp& assets,
const sp& in,
diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp
index 50a21857462c4..832ba6ca6c5f7 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -525,12 +525,30 @@ const Vector >& XMLNode::getChildren() const
return mChildren;
}
+const String8& XMLNode::getFilename() const
+{
+ return mFilename;
+}
+
const Vector&
XMLNode::getAttributes() const
{
return mAttributes;
}
+const XMLNode::attribute_entry* XMLNode::getAttribute(const String16& ns,
+ const String16& name) const
+{
+ for (size_t i=0; i XMLNode::searchElement(const String16& tagNamespace, const String16& tagName)
+{
+ if (getType() == XMLNode::TYPE_ELEMENT
+ && mNamespaceUri == tagNamespace
+ && mElementName == tagName) {
+ return this;
+ }
+
+ for (size_t i=0; i found = mChildren.itemAt(i)->searchElement(tagNamespace, tagName);
+ if (found != NULL) {
+ return found;
+ }
+ }
+
+ return NULL;
+}
+
+sp XMLNode::getChildElement(const String16& tagNamespace, const String16& tagName)
+{
+ for (size_t i=0; i child = mChildren.itemAt(i);
+ if (child->getType() == XMLNode::TYPE_ELEMENT
+ && child->mNamespaceUri == tagNamespace
+ && child->mElementName == tagName) {
+ return child;
+ }
+ }
+
+ return NULL;
+}
+
status_t XMLNode::addChild(const sp& child)
{
if (getType() == TYPE_CDATA) {
@@ -562,6 +612,17 @@ status_t XMLNode::addChild(const sp& child)
return NO_ERROR;
}
+status_t XMLNode::insertChildAt(const sp& child, size_t index)
+{
+ if (getType() == TYPE_CDATA) {
+ SourcePos(mFilename, child->getStartLineNumber()).error("Child to CDATA node.");
+ return UNKNOWN_ERROR;
+ }
+ //printf("Adding child %p to parent %p\n", child.get(), this);
+ mChildren.insertAt(child, index);
+ return NO_ERROR;
+}
+
status_t XMLNode::addAttribute(const String16& ns, const String16& name,
const String16& value)
{
diff --git a/tools/aapt/XMLNode.h b/tools/aapt/XMLNode.h
index 86548a22c8580..a9bea4312eccd 100644
--- a/tools/aapt/XMLNode.h
+++ b/tools/aapt/XMLNode.h
@@ -68,6 +68,8 @@ public:
const String16& getElementName() const;
const Vector >& getChildren() const;
+ const String8& getFilename() const;
+
struct attribute_entry {
attribute_entry() : index(~(uint32_t)0), nameResId(0)
{
@@ -91,6 +93,8 @@ public:
const Vector& getAttributes() const;
+ const attribute_entry* getAttribute(const String16& ns, const String16& name) const;
+
const String16& getCData() const;
const String16& getComment() const;
@@ -98,8 +102,14 @@ public:
int32_t getStartLineNumber() const;
int32_t getEndLineNumber() const;
+ sp searchElement(const String16& tagNamespace, const String16& tagName);
+
+ sp getChildElement(const String16& tagNamespace, const String16& tagName);
+
status_t addChild(const sp& child);
+ status_t insertChildAt(const sp& child, size_t index);
+
status_t addAttribute(const String16& ns, const String16& name,
const String16& value);